doc.go (7973B)
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 package 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 package 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 template "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate"
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 template "github.com/gohugoio/hugo/tpl/internal/go_templates/htmltemplate"
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
58 Contexts
59
60 This package understands HTML, CSS, JavaScript, and URIs. It adds sanitizing
61 functions to each simple action pipeline, so given the excerpt
62
63 <a href="/search?q={{.}}">{{.}}</a>
64
65 At parse time each {{.}} is overwritten to add escaping functions as necessary.
66 In this case it becomes
67
68 <a href="/search?q={{. | urlescaper | attrescaper}}">{{. | htmlescaper}}</a>
69
70 where urlescaper, attrescaper, and htmlescaper are aliases for internal escaping
71 functions.
72
73 For these internal escaping functions, if an action pipeline evaluates to
74 a nil interface value, it is treated as though it were an empty string.
75
76 Namespaced and data- attributes
77
78 Attributes with a namespace are treated as if they had no namespace.
79 Given the excerpt
80
81 <a my:href="{{.}}"></a>
82
83 At parse time the attribute will be treated as if it were just "href".
84 So at parse time the template becomes:
85
86 <a my:href="{{. | urlescaper | attrescaper}}"></a>
87
88 Similarly to attributes with namespaces, attributes with a "data-" prefix are
89 treated as if they had no "data-" prefix. So given
90
91 <a data-href="{{.}}"></a>
92
93 At parse time this becomes
94
95 <a data-href="{{. | urlescaper | attrescaper}}"></a>
96
97 If an attribute has both a namespace and a "data-" prefix, only the namespace
98 will be removed when determining the context. For example
99
100 <a my:data-href="{{.}}"></a>
101
102 This is handled as if "my:data-href" was just "data-href" and not "href" as
103 it would be if the "data-" prefix were to be ignored too. Thus at parse
104 time this becomes just
105
106 <a my:data-href="{{. | attrescaper}}"></a>
107
108 As a special case, attributes with the namespace "xmlns" are always treated
109 as containing URLs. Given the excerpts
110
111 <a xmlns:title="{{.}}"></a>
112 <a xmlns:href="{{.}}"></a>
113 <a xmlns:onclick="{{.}}"></a>
114
115 At parse time they become:
116
117 <a xmlns:title="{{. | urlescaper | attrescaper}}"></a>
118 <a xmlns:href="{{. | urlescaper | attrescaper}}"></a>
119 <a xmlns:onclick="{{. | urlescaper | attrescaper}}"></a>
120
121 Errors
122
123 See the documentation of ErrorCode for details.
124
125
126 A fuller picture
127
128 The rest of this package comment may be skipped on first reading; it includes
129 details necessary to understand escaping contexts and error messages. Most users
130 will not need to understand these details.
131
132
133 Contexts
134
135 Assuming {{.}} is `O'Reilly: How are <i>you</i>?`, the table below shows
136 how {{.}} appears when used in the context to the left.
137
138 Context {{.}} After
139 {{.}} O'Reilly: How are <i>you</i>?
140 <a title='{{.}}'> O'Reilly: How are you?
141 <a href="/{{.}}"> O'Reilly: How are %3ci%3eyou%3c/i%3e?
142 <a href="?q={{.}}"> O'Reilly%3a%20How%20are%3ci%3e...%3f
143 <a onx='f("{{.}}")'> O\x27Reilly: How are \x3ci\x3eyou...?
144 <a onx='f({{.}})'> "O\x27Reilly: How are \x3ci\x3eyou...?"
145 <a onx='pattern = /{{.}}/;'> O\x27Reilly: How are \x3ci\x3eyou...\x3f
146
147 If used in an unsafe context, then the value might be filtered out:
148
149 Context {{.}} After
150 <a href="{{.}}"> #ZgotmplZ
151
152 since "O'Reilly:" is not an allowed protocol like "http:".
153
154
155 If {{.}} is the innocuous word, `left`, then it can appear more widely,
156
157 Context {{.}} After
158 {{.}} left
159 <a title='{{.}}'> left
160 <a href='{{.}}'> left
161 <a href='/{{.}}'> left
162 <a href='?dir={{.}}'> left
163 <a style="border-{{.}}: 4px"> left
164 <a style="align: {{.}}"> left
165 <a style="background: '{{.}}'> left
166 <a style="background: url('{{.}}')> left
167 <style>p.{{.}} {color:red}</style> left
168
169 Non-string values can be used in JavaScript contexts.
170 If {{.}} is
171
172 struct{A,B string}{ "foo", "bar" }
173
174 in the escaped template
175
176 <script>var pair = {{.}};</script>
177
178 then the template output is
179
180 <script>var pair = {"A": "foo", "B": "bar"};</script>
181
182 See package json to understand how non-string content is marshaled for
183 embedding in JavaScript contexts.
184
185
186 Typed Strings
187
188 By default, this package assumes that all pipelines produce a plain text string.
189 It adds escaping pipeline stages necessary to correctly and safely embed that
190 plain text string in the appropriate context.
191
192 When a data value is not plain text, you can make sure it is not over-escaped
193 by marking it with its type.
194
195 Types HTML, JS, URL, and others from content.go can carry safe content that is
196 exempted from escaping.
197
198 The template
199
200 Hello, {{.}}!
201
202 can be invoked with
203
204 tmpl.Execute(out, template.HTML(`<b>World</b>`))
205
206 to produce
207
208 Hello, <b>World</b>!
209
210 instead of the
211
212 Hello, <b>World<b>!
213
214 that would have been produced if {{.}} was a regular string.
215
216
217 Security Model
218
219 https://rawgit.com/mikesamuel/sanitized-jquery-templates/trunk/safetemplate.html#problem_definition defines "safe" as used by this package.
220
221 This package assumes that template authors are trusted, that Execute's data
222 parameter is not, and seeks to preserve the properties below in the face
223 of untrusted data:
224
225 Structure Preservation Property:
226 "... when a template author writes an HTML tag in a safe templating language,
227 the browser will interpret the corresponding portion of the output as a tag
228 regardless of the values of untrusted data, and similarly for other structures
229 such as attribute boundaries and JS and CSS string boundaries."
230
231 Code Effect Property:
232 "... only code specified by the template author should run as a result of
233 injecting the template output into a page and all code specified by the
234 template author should run as a result of the same."
235
236 Least Surprise Property:
237 "A developer (or code reviewer) familiar with HTML, CSS, and JavaScript, who
238 knows that contextual autoescaping happens should be able to look at a {{.}}
239 and correctly infer what sanitization happens."
240 */
241 package template