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.
12 // Strings of content from a trusted source.
14 // CSS encapsulates known safe content that matches any of:
15 // 1. The CSS3 stylesheet production, such as `p { color: purple }`.
16 // 2. The CSS3 rule production, such as `a[href=~"https:"].foo#bar`.
17 // 3. CSS3 declaration productions, such as `color: red; margin: 2px`.
18 // 4. The CSS3 value production, such as `rgba(0, 0, 255, 127)`.
19 // See http://www.w3.org/TR/css3-syntax/#parsing and
20 // https://web.archive.org/web/20090211114933/http://w3.org/TR/css3-syntax#style
22 // Use of this type presents a security risk:
23 // the encapsulated content should come from a trusted source,
24 // as it will be included verbatim in the template output.
27 // HTML encapsulates a known safe HTML document fragment.
28 // It should not be used for HTML from a third-party, or HTML with
29 // unclosed tags or comments. The outputs of a sound HTML sanitizer
30 // and a template escaped by this package are fine for use with HTML.
32 // Use of this type presents a security risk:
33 // the encapsulated content should come from a trusted source,
34 // as it will be included verbatim in the template output.
37 // HTMLAttr encapsulates an HTML attribute from a trusted source,
38 // for example, ` dir="ltr"`.
40 // Use of this type presents a security risk:
41 // the encapsulated content should come from a trusted source,
42 // as it will be included verbatim in the template output.
45 // JS encapsulates a known safe EcmaScript5 Expression, for example,
47 // Template authors are responsible for ensuring that typed expressions
48 // do not break the intended precedence and that there is no
49 // statement/expression ambiguity as when passing an expression like
50 // "{ foo: bar() }\n['foo']()", which is both a valid Expression and a
51 // valid Program with a very different meaning.
53 // Use of this type presents a security risk:
54 // the encapsulated content should come from a trusted source,
55 // as it will be included verbatim in the template output.
57 // Using JS to include valid but untrusted JSON is not safe.
58 // A safe alternative is to parse the JSON with json.Unmarshal and then
59 // pass the resultant object into the template, where it will be
60 // converted to sanitized JSON when presented in a JavaScript context.
63 // JSStr encapsulates a sequence of characters meant to be embedded
64 // between quotes in a JavaScript expression.
65 // The string must match a series of StringCharacters:
66 // StringCharacter :: SourceCharacter but not `\` or LineTerminator
68 // Note that LineContinuations are not allowed.
69 // JSStr("foo\\nbar") is fine, but JSStr("foo\\\nbar") is not.
71 // Use of this type presents a security risk:
72 // the encapsulated content should come from a trusted source,
73 // as it will be included verbatim in the template output.
76 // URL encapsulates a known safe URL or URL substring (see RFC 3986).
77 // A URL like `javascript:checkThatFormNotEditedBeforeLeavingPage()`
78 // from a trusted source should go in the page, but by default dynamic
79 // `javascript:` URLs are filtered out since they are a frequently
80 // exploited injection vector.
82 // Use of this type presents a security risk:
83 // the encapsulated content should come from a trusted source,
84 // as it will be included verbatim in the template output.
87 // Srcset encapsulates a known safe srcset attribute
88 // (see http://w3c.github.io/html/semantics-embedded-content.html#element-attrdef-img-srcset).
90 // Use of this type presents a security risk:
91 // the encapsulated content should come from a trusted source,
92 // as it will be included verbatim in the template output.
96 type contentType
uint8
99 contentTypePlain contentType
= iota
107 // contentTypeUnsafe is used in attr.go for values that affect how
108 // embedded content and network messages are formed, vetted,
109 // or interpreted; or which credentials network messages carry.
113 // indirect returns the value, after dereferencing as many times
114 // as necessary to reach the base type (or nil).
115 func indirect(a
interface{}) interface{} {
119 if t
:= reflect
.TypeOf(a
); t
.Kind() != reflect
.Ptr
{
120 // Avoid creating a reflect.Value if it's not a pointer.
123 v
:= reflect
.ValueOf(a
)
124 for v
.Kind() == reflect
.Ptr
&& !v
.IsNil() {
131 errorType
= reflect
.TypeOf((*error
)(nil)).Elem()
132 fmtStringerType
= reflect
.TypeOf((*fmt
.Stringer
)(nil)).Elem()
135 // indirectToStringerOrError returns the value, after dereferencing as many times
136 // as necessary to reach the base type (or nil) or an implementation of fmt.Stringer
138 func indirectToStringerOrError(a
interface{}) interface{} {
142 v
:= reflect
.ValueOf(a
)
143 for !v
.Type().Implements(fmtStringerType
) && !v
.Type().Implements(errorType
) && v
.Kind() == reflect
.Ptr
&& !v
.IsNil() {
149 // stringify converts its arguments to a string and the type of the content.
150 // All pointers are dereferenced, as in the text/template package.
151 func stringify(args
...interface{}) (string, contentType
) {
153 switch s
:= indirect(args
[0]).(type) {
155 return s
, contentTypePlain
157 return string(s
), contentTypeCSS
159 return string(s
), contentTypeHTML
161 return string(s
), contentTypeHTMLAttr
163 return string(s
), contentTypeJS
165 return string(s
), contentTypeJSStr
167 return string(s
), contentTypeURL
169 return string(s
), contentTypeSrcset
172 for i
, arg
:= range args
{
173 args
[i
] = indirectToStringerOrError(arg
)
175 return fmt
.Sprint(args
...), contentTypePlain