diff options
Diffstat (limited to '')
-rw-r--r-- | src/html/template/attr.go | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/src/html/template/attr.go b/src/html/template/attr.go new file mode 100644 index 0000000..6c52211 --- /dev/null +++ b/src/html/template/attr.go @@ -0,0 +1,175 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package template + +import ( + "strings" +) + +// attrTypeMap[n] describes the value of the given attribute. +// If an attribute affects (or can mask) the encoding or interpretation of +// other content, or affects the contents, idempotency, or credentials of a +// network message, then the value in this map is contentTypeUnsafe. +// This map is derived from HTML5, specifically +// https://www.w3.org/TR/html5/Overview.html#attributes-1 +// as well as "%URI"-typed attributes from +// https://www.w3.org/TR/html4/index/attributes.html +var attrTypeMap = map[string]contentType{ + "accept": contentTypePlain, + "accept-charset": contentTypeUnsafe, + "action": contentTypeURL, + "alt": contentTypePlain, + "archive": contentTypeURL, + "async": contentTypeUnsafe, + "autocomplete": contentTypePlain, + "autofocus": contentTypePlain, + "autoplay": contentTypePlain, + "background": contentTypeURL, + "border": contentTypePlain, + "checked": contentTypePlain, + "cite": contentTypeURL, + "challenge": contentTypeUnsafe, + "charset": contentTypeUnsafe, + "class": contentTypePlain, + "classid": contentTypeURL, + "codebase": contentTypeURL, + "cols": contentTypePlain, + "colspan": contentTypePlain, + "content": contentTypeUnsafe, + "contenteditable": contentTypePlain, + "contextmenu": contentTypePlain, + "controls": contentTypePlain, + "coords": contentTypePlain, + "crossorigin": contentTypeUnsafe, + "data": contentTypeURL, + "datetime": contentTypePlain, + "default": contentTypePlain, + "defer": contentTypeUnsafe, + "dir": contentTypePlain, + "dirname": contentTypePlain, + "disabled": contentTypePlain, + "draggable": contentTypePlain, + "dropzone": contentTypePlain, + "enctype": contentTypeUnsafe, + "for": contentTypePlain, + "form": contentTypeUnsafe, + "formaction": contentTypeURL, + "formenctype": contentTypeUnsafe, + "formmethod": contentTypeUnsafe, + "formnovalidate": contentTypeUnsafe, + "formtarget": contentTypePlain, + "headers": contentTypePlain, + "height": contentTypePlain, + "hidden": contentTypePlain, + "high": contentTypePlain, + "href": contentTypeURL, + "hreflang": contentTypePlain, + "http-equiv": contentTypeUnsafe, + "icon": contentTypeURL, + "id": contentTypePlain, + "ismap": contentTypePlain, + "keytype": contentTypeUnsafe, + "kind": contentTypePlain, + "label": contentTypePlain, + "lang": contentTypePlain, + "language": contentTypeUnsafe, + "list": contentTypePlain, + "longdesc": contentTypeURL, + "loop": contentTypePlain, + "low": contentTypePlain, + "manifest": contentTypeURL, + "max": contentTypePlain, + "maxlength": contentTypePlain, + "media": contentTypePlain, + "mediagroup": contentTypePlain, + "method": contentTypeUnsafe, + "min": contentTypePlain, + "multiple": contentTypePlain, + "name": contentTypePlain, + "novalidate": contentTypeUnsafe, + // Skip handler names from + // https://www.w3.org/TR/html5/webappapis.html#event-handlers-on-elements,-document-objects,-and-window-objects + // since we have special handling in attrType. + "open": contentTypePlain, + "optimum": contentTypePlain, + "pattern": contentTypeUnsafe, + "placeholder": contentTypePlain, + "poster": contentTypeURL, + "profile": contentTypeURL, + "preload": contentTypePlain, + "pubdate": contentTypePlain, + "radiogroup": contentTypePlain, + "readonly": contentTypePlain, + "rel": contentTypeUnsafe, + "required": contentTypePlain, + "reversed": contentTypePlain, + "rows": contentTypePlain, + "rowspan": contentTypePlain, + "sandbox": contentTypeUnsafe, + "spellcheck": contentTypePlain, + "scope": contentTypePlain, + "scoped": contentTypePlain, + "seamless": contentTypePlain, + "selected": contentTypePlain, + "shape": contentTypePlain, + "size": contentTypePlain, + "sizes": contentTypePlain, + "span": contentTypePlain, + "src": contentTypeURL, + "srcdoc": contentTypeHTML, + "srclang": contentTypePlain, + "srcset": contentTypeSrcset, + "start": contentTypePlain, + "step": contentTypePlain, + "style": contentTypeCSS, + "tabindex": contentTypePlain, + "target": contentTypePlain, + "title": contentTypePlain, + "type": contentTypeUnsafe, + "usemap": contentTypeURL, + "value": contentTypeUnsafe, + "width": contentTypePlain, + "wrap": contentTypePlain, + "xmlns": contentTypeURL, +} + +// attrType returns a conservative (upper-bound on authority) guess at the +// type of the lowercase named attribute. +func attrType(name string) contentType { + if strings.HasPrefix(name, "data-") { + // Strip data- so that custom attribute heuristics below are + // widely applied. + // Treat data-action as URL below. + name = name[5:] + } else if prefix, short, ok := strings.Cut(name, ":"); ok { + if prefix == "xmlns" { + return contentTypeURL + } + // Treat svg:href and xlink:href as href below. + name = short + } + if t, ok := attrTypeMap[name]; ok { + return t + } + // Treat partial event handler names as script. + if strings.HasPrefix(name, "on") { + return contentTypeJS + } + + // Heuristics to prevent "javascript:..." injection in custom + // data attributes and custom attributes like g:tweetUrl. + // https://www.w3.org/TR/html5/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes + // "Custom data attributes are intended to store custom data + // private to the page or application, for which there are no + // more appropriate attributes or elements." + // Developers seem to store URL content in data URLs that start + // or end with "URI" or "URL". + if strings.Contains(name, "src") || + strings.Contains(name, "uri") || + strings.Contains(name, "url") { + return contentTypeURL + } + return contentTypePlain +} |