Source file src/html/template/doc.go

     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, &lt;script&gt;alert(&#39;you have been pwned&#39;)&lt;/script&gt;!
    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 &lt;i&gt;you&lt;/i&gt;?
   137  	<a title='{{.}}'>                O&#39;Reilly: How are you?
   138  	<a href="/{{.}}">                O&#39;Reilly: How are %3ci%3eyou%3c/i%3e?
   139  	<a href="?q={{.}}">              O&#39;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, &lt;b&gt;World&lt;b&gt;!
   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  As a consequence of the Least Surprise Property, template actions within an
   236  ECMAScript 6 template literal are disabled by default.
   237  Handling string interpolation within these literals is rather complex resulting
   238  in no clear safe way to support it.
   239  To re-enable template actions within ECMAScript 6 template literals, use the
   240  GODEBUG=jstmpllitinterp=1 environment variable.
   241  */
   242  package template
   243  

View as plain text