github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/html/template/doc.go (about)

     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 "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  
    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 &lt;i&gt;you&lt;/i&gt;?
   140    <a title='{{.}}'>                O&#39;Reilly: How are you?
   141    <a href="/{{.}}">                O&#39;Reilly: How are %3ci%3eyou%3c/i%3e?
   142    <a href="?q={{.}}">              O&#39;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, &lt;b&gt;World&lt;b&gt;!
   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