1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 /* 6 Package template (html/template) implements data-driven templates for 7 generating HTML output safe against code injection. It provides the 8 same interface as [text/template] and should be used instead of 9 [text/template] whenever the output is HTML. 10 11 The documentation here focuses on the security features of the package. 12 For information about how to program the templates themselves, see the 13 documentation for [text/template]. 14 15 # Introduction 16 17 This package wraps [text/template] so you can share its template API 18 to parse and execute HTML templates safely. 19 20 tmpl, err := template.New("name").Parse(...) 21 // Error checking elided 22 err = tmpl.Execute(out, data) 23 24 If successful, tmpl will now be injection-safe. Otherwise, err is an error 25 defined in the docs for ErrorCode. 26 27 HTML templates treat data values as plain text which should be encoded so they 28 can be safely embedded in an HTML document. The escaping is contextual, so 29 actions can appear within JavaScript, CSS, and URI contexts. 30 31 The security model used by this package assumes that template authors are 32 trusted, while Execute's data parameter is not. More details are 33 provided below. 34 35 Example 36 37 import "text/template" 38 ... 39 t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`) 40 err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>") 41 42 produces 43 44 Hello, <script>alert('you have been pwned')</script>! 45 46 but the contextual autoescaping in html/template 47 48 import "html/template" 49 ... 50 t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`) 51 err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>") 52 53 produces safe, escaped HTML output 54 55 Hello, <script>alert('you have been pwned')</script>! 56 57 # Contexts 58 59 This package understands HTML, CSS, JavaScript, and URIs. It adds sanitizing 60 functions to each simple action pipeline, so given the excerpt 61 62 <a href="/search?q={{.}}">{{.}}</a> 63 64 At parse time each {{.}} is overwritten to add escaping functions as necessary. 65 In this case it becomes 66 67 <a href="/search?q={{. | urlescaper | attrescaper}}">{{. | htmlescaper}}</a> 68 69 where urlescaper, attrescaper, and htmlescaper are aliases for internal escaping 70 functions. 71 72 For these internal escaping functions, if an action pipeline evaluates to 73 a nil interface value, it is treated as though it were an empty string. 74 75 # Namespaced and data- attributes 76 77 Attributes with a namespace are treated as if they had no namespace. 78 Given the excerpt 79 80 <a my:href="{{.}}"></a> 81 82 At parse time the attribute will be treated as if it were just "href". 83 So at parse time the template becomes: 84 85 <a my:href="{{. | urlescaper | attrescaper}}"></a> 86 87 Similarly to attributes with namespaces, attributes with a "data-" prefix are 88 treated as if they had no "data-" prefix. So given 89 90 <a data-href="{{.}}"></a> 91 92 At parse time this becomes 93 94 <a data-href="{{. | urlescaper | attrescaper}}"></a> 95 96 If an attribute has both a namespace and a "data-" prefix, only the namespace 97 will be removed when determining the context. For example 98 99 <a my:data-href="{{.}}"></a> 100 101 This is handled as if "my:data-href" was just "data-href" and not "href" as 102 it would be if the "data-" prefix were to be ignored too. Thus at parse 103 time this becomes just 104 105 <a my:data-href="{{. | attrescaper}}"></a> 106 107 As a special case, attributes with the namespace "xmlns" are always treated 108 as containing URLs. Given the excerpts 109 110 <a xmlns:title="{{.}}"></a> 111 <a xmlns:href="{{.}}"></a> 112 <a xmlns:onclick="{{.}}"></a> 113 114 At parse time they become: 115 116 <a xmlns:title="{{. | urlescaper | attrescaper}}"></a> 117 <a xmlns:href="{{. | urlescaper | attrescaper}}"></a> 118 <a xmlns:onclick="{{. | urlescaper | attrescaper}}"></a> 119 120 # Errors 121 122 See the documentation of ErrorCode for details. 123 124 # A fuller picture 125 126 The rest of this package comment may be skipped on first reading; it includes 127 details necessary to understand escaping contexts and error messages. Most users 128 will not need to understand these details. 129 130 # Contexts 131 132 Assuming {{.}} is `O'Reilly: How are <i>you</i>?`, the table below shows 133 how {{.}} appears when used in the context to the left. 134 135 Context {{.}} After 136 {{.}} O'Reilly: How are <i>you</i>? 137 <a title='{{.}}'> O'Reilly: How are you? 138 <a href="/{{.}}"> O'Reilly: How are %3ci%3eyou%3c/i%3e? 139 <a href="?q={{.}}"> O'Reilly%3a%20How%20are%3ci%3e...%3f 140 <a onx='f("{{.}}")'> O\x27Reilly: How are \x3ci\x3eyou...? 141 <a onx='f({{.}})'> "O\x27Reilly: How are \x3ci\x3eyou...?" 142 <a onx='pattern = /{{.}}/;'> O\x27Reilly: How are \x3ci\x3eyou...\x3f 143 144 If used in an unsafe context, then the value might be filtered out: 145 146 Context {{.}} After 147 <a href="{{.}}"> #ZgotmplZ 148 149 since "O'Reilly:" is not an allowed protocol like "http:". 150 151 If {{.}} is the innocuous word, `left`, then it can appear more widely, 152 153 Context {{.}} After 154 {{.}} left 155 <a title='{{.}}'> left 156 <a href='{{.}}'> left 157 <a href='/{{.}}'> left 158 <a href='?dir={{.}}'> left 159 <a style="border-{{.}}: 4px"> left 160 <a style="align: {{.}}"> left 161 <a style="background: '{{.}}'> left 162 <a style="background: url('{{.}}')> left 163 <style>p.{{.}} {color:red}</style> left 164 165 Non-string values can be used in JavaScript contexts. 166 If {{.}} is 167 168 struct{A,B string}{ "foo", "bar" } 169 170 in the escaped template 171 172 <script>var pair = {{.}};</script> 173 174 then the template output is 175 176 <script>var pair = {"A": "foo", "B": "bar"};</script> 177 178 See package json to understand how non-string content is marshaled for 179 embedding in JavaScript contexts. 180 181 # Typed Strings 182 183 By default, this package assumes that all pipelines produce a plain text string. 184 It adds escaping pipeline stages necessary to correctly and safely embed that 185 plain text string in the appropriate context. 186 187 When a data value is not plain text, you can make sure it is not over-escaped 188 by marking it with its type. 189 190 Types HTML, JS, URL, and others from content.go can carry safe content that is 191 exempted from escaping. 192 193 The template 194 195 Hello, {{.}}! 196 197 can be invoked with 198 199 tmpl.Execute(out, template.HTML(`<b>World</b>`)) 200 201 to produce 202 203 Hello, <b>World</b>! 204 205 instead of the 206 207 Hello, <b>World<b>! 208 209 that would have been produced if {{.}} was a regular string. 210 211 # Security Model 212 213 https://rawgit.com/mikesamuel/sanitized-jquery-templates/trunk/safetemplate.html#problem_definition defines "safe" as used by this package. 214 215 This package assumes that template authors are trusted, that Execute's data 216 parameter is not, and seeks to preserve the properties below in the face 217 of untrusted data: 218 219 Structure Preservation Property: 220 "... when a template author writes an HTML tag in a safe templating language, 221 the browser will interpret the corresponding portion of the output as a tag 222 regardless of the values of untrusted data, and similarly for other structures 223 such as attribute boundaries and JS and CSS string boundaries." 224 225 Code Effect Property: 226 "... only code specified by the template author should run as a result of 227 injecting the template output into a page and all code specified by the 228 template author should run as a result of the same." 229 230 Least Surprise Property: 231 "A developer (or code reviewer) familiar with HTML, CSS, and JavaScript, who 232 knows that contextual autoescaping happens should be able to look at a {{.}} 233 and correctly infer what sanitization happens." 234 235 Previously, ECMAScript 6 template literal were disabled by default, and could be 236 enabled with the GODEBUG=jstmpllitinterp=1 environment variable. Template 237 literals are now supported by default, and setting jstmpllitinterp has no 238 effect. 239 */ 240 package template 241