From 7b4377ad9d8a7205416df8d6217ef2b010f89481 Mon Sep 17 00:00:00 2001 From: Taras Madan Date: Wed, 22 Jan 2025 16:07:17 +0100 Subject: vendor: delete --- .../github.com/google/safehtml/template/context.go | 183 ----- .../google/safehtml/template/delim_string.go | 16 - vendor/github.com/google/safehtml/template/doc.go | 291 ------- .../github.com/google/safehtml/template/error.go | 280 ------- .../github.com/google/safehtml/template/escape.go | 884 --------------------- vendor/github.com/google/safehtml/template/init.go | 28 - .../google/safehtml/template/sanitize.go | 258 ------ .../google/safehtml/template/sanitizers.go | 599 -------------- .../google/safehtml/template/state_string.go | 16 - .../google/safehtml/template/template.go | 651 --------------- .../google/safehtml/template/transition.go | 312 -------- .../google/safehtml/template/trustedfs.go | 98 --- .../google/safehtml/template/trustedsource.go | 105 --- .../google/safehtml/template/trustedtemplate.go | 36 - vendor/github.com/google/safehtml/template/url.go | 122 --- 15 files changed, 3879 deletions(-) delete mode 100644 vendor/github.com/google/safehtml/template/context.go delete mode 100644 vendor/github.com/google/safehtml/template/delim_string.go delete mode 100644 vendor/github.com/google/safehtml/template/doc.go delete mode 100644 vendor/github.com/google/safehtml/template/error.go delete mode 100644 vendor/github.com/google/safehtml/template/escape.go delete mode 100644 vendor/github.com/google/safehtml/template/init.go delete mode 100644 vendor/github.com/google/safehtml/template/sanitize.go delete mode 100644 vendor/github.com/google/safehtml/template/sanitizers.go delete mode 100644 vendor/github.com/google/safehtml/template/state_string.go delete mode 100644 vendor/github.com/google/safehtml/template/template.go delete mode 100644 vendor/github.com/google/safehtml/template/transition.go delete mode 100644 vendor/github.com/google/safehtml/template/trustedfs.go delete mode 100644 vendor/github.com/google/safehtml/template/trustedsource.go delete mode 100644 vendor/github.com/google/safehtml/template/trustedtemplate.go delete mode 100644 vendor/github.com/google/safehtml/template/url.go (limited to 'vendor/github.com/google/safehtml/template') diff --git a/vendor/github.com/google/safehtml/template/context.go b/vendor/github.com/google/safehtml/template/context.go deleted file mode 100644 index dd7886dc6..000000000 --- a/vendor/github.com/google/safehtml/template/context.go +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright 2017 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" -) - -// context describes the state an HTML parser must be in when it reaches the -// portion of HTML produced by evaluating a particular template node. -// -// The zero value of type Context is the start context for a template that -// produces an HTML fragment as defined at -// http://www.w3.org/TR/html5/syntax.html#the-end -// where the context element is null. -type context struct { - state state - delim delim - element element - attr attr - err *Error - // scriptType is the lowercase value of the "type" attribute inside the current "script" - // element (see https://dev.w3.org/html5/spec-preview/the-script-element.html#attr-script-type). - // This field will be empty if the parser is currently not in a script element, - // the type attribute has not already been parsed in the current element, or if the - // value of the type attribute cannot be determined at parse time. - scriptType string - // linkRel is the value of the "rel" attribute inside the current "link" - // element (see https://html.spec.whatwg.org/multipage/semantics.html#attr-link-rel). - // This value has been normalized to lowercase with exactly one space between tokens - // and exactly one space at start and end, so that a lookup of any token foo can - // be performed by searching for the substring " foo ". - // This field will be empty if the parser is currently not in a link element, - // the rel attribute has not already been parsed in the current element, or if the - // value of the rel attribute cannot be determined at parse time. - linkRel string -} - -// eq returns whether Context c is equal to Context d. -func (c context) eq(d context) bool { - return c.state == d.state && - c.delim == d.delim && - c.element.eq(d.element) && - c.attr.eq(d.attr) && - c.err == d.err && - c.scriptType == d.scriptType && - c.linkRel == d.linkRel -} - -// state describes a high-level HTML parser state. -// -// It bounds the top of the element stack, and by extension the HTML insertion -// mode, but also contains state that does not correspond to anything in the -// HTML5 parsing algorithm because a single token production in the HTML -// grammar may contain embedded actions in a template. For instance, the quoted -// HTML attribute produced by -//
-// is a single token in HTML's grammar but in a template spans several nodes. -type state uint8 - -//go:generate stringer -type state - -const ( - // stateText is parsed character data. An HTML parser is in - // this state when its parse position is outside an HTML tag, - // directive, comment, and special element body. - stateText state = iota - // stateSpecialElementBody occurs inside a specal HTML element body. - stateSpecialElementBody - // stateTag occurs before an HTML attribute or the end of a tag. - stateTag - // stateAttrName occurs inside an attribute name. - // It occurs between the ^'s in ` ^name^ = value`. - stateAttrName - // stateAfterName occurs after an attr name has ended but before any - // equals sign. It occurs between the ^'s in ` name^ ^= value`. - stateAfterName - // stateBeforeValue occurs after the equals sign but before the value. - // It occurs between the ^'s in ` name =^ ^value`. - stateBeforeValue - // stateHTMLCmt occurs inside an . - stateHTMLCmt - // stateAttr occurs inside an HTML attribute whose content is text. - stateAttr - // stateError is an infectious error state outside any valid - // HTML/CSS/JS construct. - stateError -) - -// isComment reports whether a state contains content meant for template -// authors & maintainers, not for end-users or machines. -func isComment(s state) bool { - switch s { - case stateHTMLCmt: - return true - } - return false -} - -// isInTag reports whether s occurs solely inside an HTML tag. -func isInTag(s state) bool { - switch s { - case stateTag, stateAttrName, stateAfterName, stateBeforeValue, stateAttr: - return true - } - return false -} - -// delim is the delimiter that will end the current HTML attribute. -type delim uint8 - -//go:generate stringer -type delim - -const ( - // delimNone occurs outside any attribute. - delimNone delim = iota - // delimDoubleQuote occurs when a double quote (") closes the attribute. - delimDoubleQuote - // delimSingleQuote occurs when a single quote (') closes the attribute. - delimSingleQuote - // delimSpaceOrTagEnd occurs when a space or right angle bracket (>) - // closes the attribute. - delimSpaceOrTagEnd -) - -type element struct { - // name is the lowercase name of the element. If context joining has occurred, name - // will be arbitrarily assigned the element name from one of the joined contexts. - name string - // names contains all possible names the element could assume because of context joining. - // For example, after joining the contexts in the "if" and "else" branches of - // {{if .C}}`, - // names will contain "img" and "audio". - // names can also contain empty strings, which represent joined contexts with no element name. - // names will be empty if no context joining occurred. - names []string -} - -// eq reports whether a and b have the same name. All other fields are ignored. -func (e element) eq(d element) bool { - return e.name == d.name -} - -// String returns the string representation of the element. -func (e element) String() string { - return "element" + strings.Title(e.name) -} - -// attr represents the attribute that the parser is in, that is, -// starting from stateAttrName until stateTag/stateText (exclusive). -type attr struct { - // name is the lowercase name of the attribute. If context joining has occurred, name - // will be arbitrarily assigned the attribute name from one of the joined contexts. - name string - // value is the value of the attribute. If context joining has occurred, value - // will be arbitrarily assigned the attribute value from one of the joined contexts. - // If there are multiple actions in the attribute value, value will contain the - // concatenation of all values seen so far. For example, in - // - // value is "foo" at "{{.X}}" and "foobar" at "{{.Y}}". - value string - // ambiguousValue indicates whether value contains an ambiguous value due to context-joining. - ambiguousValue bool - // names contains all possible names the attribute could assume because of context joining. - // For example, after joining the contexts in the "if" and "else" branches of - // - // names will contain "title" and "name". - // names can also contain empty strings, which represent joined contexts with no attribute name. - // names will be empty if no context joining occurred. - names []string -} - -// eq reports whether a and b have the same name. All other fields are ignored. -func (a attr) eq(b attr) bool { - return a.name == b.name -} - -// String returns the string representation of the attr. -func (a attr) String() string { - return "attr" + strings.Title(a.name) -} diff --git a/vendor/github.com/google/safehtml/template/delim_string.go b/vendor/github.com/google/safehtml/template/delim_string.go deleted file mode 100644 index 0ef2c2510..000000000 --- a/vendor/github.com/google/safehtml/template/delim_string.go +++ /dev/null @@ -1,16 +0,0 @@ -// Code generated by "stringer -type Delim"; DO NOT EDIT - -package template - -import "fmt" - -const _Delim_name = "DelimNoneDelimDoubleQuoteDelimSingleQuoteDelimSpaceOrTagEnd" - -var _Delim_index = [...]uint8{0, 9, 25, 41, 59} - -func (i delim) String() string { - if i >= delim(len(_Delim_index)-1) { - return fmt.Sprintf("delim(%d)", i) - } - return _Delim_name[_Delim_index[i]:_Delim_index[i+1]] -} diff --git a/vendor/github.com/google/safehtml/template/doc.go b/vendor/github.com/google/safehtml/template/doc.go deleted file mode 100644 index fab552b25..000000000 --- a/vendor/github.com/google/safehtml/template/doc.go +++ /dev/null @@ -1,291 +0,0 @@ -// Copyright (c) 2017 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 or at -// https://developers.google.com/open-source/licenses/bsd - -/* -Package template (safehtml/template) implements data-driven templates for -generating HTML output safe against code injection. It provides an interface -similar to that of package html/template, but produces HTML output that is more -secure. Therefore, it should be used instead of html/template to render HTML. - -The documentation here focuses on the security features of the package. For -information about how to program the templates themselves, see the -documentation for text/template. - - -Basic usage - -This package provides an API almost identical to that of text/template and -html/template to parse and execute HTML templates safely. - - tmpl := template.Must(template.New("name").Parse(`
Hello {{.}}
`)) - err := tmpl.Execute(out, data) - -If successful, out will contain code-injection-safe HTML. Otherwise, err's -string representation will describe the error that occurred. - -Elements of data might be modified at run time before being included in out, or -rejected completely if such a conversion is not possible. Pass values of -appropriate types from package safehtml to ensure that they are included in the -template's HTML output in their expected form. More details are provided below -in "Contextual autosanitization" and "Sanitization contexts". - - -Security improvements - -safehtml/template produces HTML more resistant to code injection than -html/template because it: - * Allows values of types only from package safehtml to bypass run-time - sanitization. These types represent values that are known---by construction - or by run-time sanitization---to be safe for use in various HTML contexts - without being processed by certain sanitization functions. - * Does not attempt to escape CSS or JavaScript. Instead of attempting to - parse and escape these complex languages, safehtml/template allows values - of only the appropriate types from package safehtml (e.g. safehtml.Style, - safehtml.Script) to be used in these contexts, since they are already - guaranteed to be safe. - * Emits an error if user data is interpolated in unsafe contexts, such as - within disallowed elements or unquoted attribute values. - * Only loads templates from trusted sources. This ensures that the contents - of the template are always under programmer control. More details are - provided below in "Trusted template sources". - * Differentiates between URLs that load code and those that do not. URLs in - the former category must be supplied to the template as values of type - safehtml.TrustedResourceURL, whose type contract promises that the URL - identifies a trustworthy resource. URLs in the latter category can be - sanitized at run time. - - -Threat model - -safehtml/template assumes that programmers are trustworthy. Therefore, data -fully under programmer control, such as string literals, are considered safe. -The types from package safehtml are designed around this same assumption, so -their type contracts are trusted by this package. - -safehtml/template considers all other data values untrustworthy and -conservatively assumes that such values could result in a code-injection -vulnerability if included verbatim in HTML. - - -Trusted template sources - -safehtml/template loads templates only from trusted sources. Therefore, template -text, file paths, and file patterns passed to Parse* functions and methods must -be entirely under programmer control. - -This constraint is enforced by using unexported string types for the parameters -of Parse* functions and methods, such as trustedFilePattern for ParseGlob. -The only values that may be assigned to these types (and thus provided as -arguments) are untyped string constants such as string literals, which are -always under programmer control. - - -Contextual autosanitization - -Code injection vulnerabilities, such as cross-site scripting (XSS), occur when -untrusted data values are embedded in a HTML document. For example, - - import "text/template" - ... - var t = template.Must(template.New("foo").Parse(`
{{ .Y }}`)) - func renderHTML(x, y string) string { - var out bytes.Buffer - err := t.Execute(&out, struct{ X, Y string }{x, y}) - // Error checking elided - return out.String() - } - -If x and y originate from user-provided data, an attacker who controls these -strings could arrange for them to contain the following values: - - x = "javascript:evil()" - y = "" - -which will cause renderHTML to return the following unsafe HTML: - - - -To prevent such vulnerabilities, untrusted data must be sanitized before being -included in HTML. A sanitization function takes untrusted data and returns a -string that will not create a code-injection vulnerability in the destination -context. The function might return the input unchanged if it deems it safe, -escape special runes in the input's string representation to prevent them from -triggering undesired state changes in the HTML parser, or entirely replace the -input by an innocuous string (also known as "filtering"). If none of these -conversions are possible, the sanitization function aborts template processing. - -safehtml/template contextually autosanitizes untrusted data by adding -appropriate sanitization functions to template actions to ensure that the -action output is safe to include in the HTML context in which the action -appears. For example, in - - import "safehtml/template" - ... - var t = template.Must(template.New("foo").Parse(`{{ .Y }}`)) - func renderHTML(x, y string) string { - var out bytes.Buffer - err := t.Execute(&out, struct{ X, Y string }{x, y}) - // Error checking elided - return out.String() - } - -the contextual autosanitizer rewrites the template to - - {{ .Y | _sanitizeHTML }} - -so that the template produces the following safe, sanitized HTML output (split -across multiple lines for clarity): - - - </a><script>alert('pwned')</script><a> - - -Similar template systems such as html/template, Soy, and Angular, refer to this -functionality as "contextual autoescaping". safehtml/template uses the term -"autosanitization" instead of "autoescaping" since "sanitization" broadly -captures the operations of escaping and filtering. - - -Sanitization contexts - -The types of sanitization functions inserted into an action depend on the -action's sanitization context, which is determined by its surrounding text. -The following table describes these sanitization contexts. - - +--------------------+----------------------------------+------------------------------+-----------------------+ - | Context | Examples | Safe types | Run-time sanitizer | - |--------------------+----------------------------------+------------------------------+-----------------------+ - | HTMLContent | Hello {{.}} | safehtml.HTML | safehtml.HTMLEscaped | - | | {{.}} | | | - +--------------------------------------------------------------------------------------------------------------+ - | HTMLValOnly | | safehtml.HTML* | N/A | - +--------------------------------------------------------------------------------------------------------------+ - | URL | Cite | safehtml.URL | safehtml.URLSanitized | - +--------------------------------------------------------------------------------------------------------------+ - | URL or | Link | safehtml.URL | safehtml.URLSanitized | - | TrustedResourceURL | | safehtml.TrustedResourceURL | | - +--------------------------------------------------------------------------------------------------------------+ - | TrustedResourceURL | | safehtml.TrustedResourceURL† | N/A | - +--------------------------------------------------------------------------------------------------------------+ - | Script | | safehtml.Script* | N/A | - +--------------------------------------------------------------------------------------------------------------+ - | Style |

Paragraph

| safehtml.Style* | N/A | - +--------------------------------------------------------------------------------------------------------------+ - | Stylesheet | | safehtml.StyleSheet* | N/A | - +--------------------------------------------------------------------------------------------------------------+ - | Identifier |

Hello

| safehtml.Identifier* | N/A | - +--------------------------------------------------------------------------------------------------------------+ - | Enumerated value | Link | Allowed string values | N/A | - | | | ("_self" or "_blank" for | | - | | | the given example) | | - +--------------------------------------------------------------------------------------------------------------+ - | None |

Hello

| N/A (any type allowed) | N/A (any type | - | | | | allowed) | - +--------------------+----------------------------------+------------------------------+-----------------------+ - *: Values only of this type are allowed in this context. Other values will trigger a run-time error. - †: If the action is a prefix of the attribute value, values only of this type are allowed. - Otherwise, values of any type are allowed. See "Substitutions in URLs" for more details. - -For each context, the function named in "Run-time sanitizer" is called to -sanitize the output of the action. However, if the action outputs a value of -any of the types listed in "Safe types", the run-time sanitizer is not called. -For example, in - - {{ .X }} - -if X is a string value, a HTML sanitizer that calls safehtml.HTMLEscaped will be -added to the action to sanitize X. - - // _sanitizeHTML calls safehtml.HTMLEscaped. - {{ .X | _sanitizeHTML }} - -However, if X is a safehtml.HTML value, _sanitizeHTML will not change its -value, since safehtml.HTML values are already safe to use in HTML contexts. -Therefore, the string contents of X will bypass context-specific -sanitization (in this case, HTML escaping) and appear unchanged in the -template's HTML output. Note that in attribute value contexts, HTML escaping -will always take place, whether or not context-specific sanitization is -performed. More details can be found at the end of this section. - -In certain contexts, the autosanitizer allows values only of that context's -"Safe types". Any other values will trigger an error and abort template -processing. For example, the template - - - -triggers a run-time error if X is not a safehtml.StyleSheet. Otherwise, the -string form of X will appear unchanged in the output. The only exception to -this behavior is in TrustedResourceURL sanitization contexts, where actions may -output data of any type if the action occurs after a safe attribute value prefix. -More details can be found below in "Substitutions in URLs". - - -Unconditional sanitization - -In attribute value contexts, action outputs are always HTML-escaped after -context-specific sanitization to ensure that the attribute values cannot change -change the structure of the surrounding HTML tag. In URL or TrustedResourceURL -sanitization contexts, action outputs are additionally URL-normalized to reduce -the likelihood of downstream URL-parsing bugs. For example, the template - - Link -

Text

- -is rewritten by the autosanitizer into - - // _sanitizeHTML calls safehtml.HTMLEscaped. - Link -

Text

- -Even if X is a safehtml.URL or safehtml.TrustedResourceURL value, which -remains unchanged after _sanitizeTrustedResourceURLOrURL, X will still be -URL-normalized and HTML-escaped. Likewise, Y will still be HTML-escaped even if -its string form is left unchanged by _sanitizeIdentifier. - - -Substitutions in URLs - -Values of any type may be substituted into attribute values in URL and -TrustedResourceURL sanitization contexts only if the action is preceded by a -safe URL prefix. For example, in - - foo - -Since "http://www.foo.com/" is a safe URL prefix, PathComponent can safely be -interpolated into this URL sanitization context after URL normalization. -Similarly, in - - - -Since "https://www.bar.com/" is a safe TrustedResourceURL prefix, PathComponent -can safely be interpolated into this TrustedResourceURL sanitization context -after URL escaping. Substitutions after a safe TrustedResourceURL prefix are -escaped instead of normalized to prevent the injection of any new URL -components, including additional path components. URL escaping also takes place -in URL sanitization contexts where the substitutions occur in the query or -fragment part of the URL, such as in: - - Link - -A URL prefix is considered safe in a URL sanitization context if it does -not end in an incomplete HTML character reference (e.g. https) or incomplete -percent-encoding character triplet (e.g. /fo%6), does not contain whitespace or control -characters, and one of the following is true: - * The prefix has a safe scheme (i.e. http, https, mailto, or ftp). - * The prefix has the data scheme with base64 encoding and an allowed audio, image, - or video MIME type (e.g. data:img/jpeg;base64, data:video/mp4;base64). - * The prefix has no scheme at all, and cannot be interpreted as a scheme prefix (e.g. /path). - -A URL prefix is considered safe in a TrustedResourceURL sanitization context if it does -not end in an incomplete HTML character reference (e.g. https) or incomplete -percent-encoding character triplet (e.g. /fo%6), does not contain white space or control -characters, and one of the following is true: - * The prefix has the https scheme and contains a domain name (e.g. https://www.foo.com). - * The prefix is scheme-relative and contains a domain name (e.g. //www.foo.com/). - * The prefix is path-absolute and contains a path (e.g. /path). - * The prefix is "about:blank". -*/ -package template diff --git a/vendor/github.com/google/safehtml/template/error.go b/vendor/github.com/google/safehtml/template/error.go deleted file mode 100644 index fe7821433..000000000 --- a/vendor/github.com/google/safehtml/template/error.go +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright 2017 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 ( - "fmt" - "text/template/parse" -) - -// Error describes a problem encountered during template Escaping. -type Error struct { - // ErrorCode describes the kind of error. - ErrorCode ErrorCode - // Node is the node that caused the problem, if known. - // If not nil, it overrides Name and Line. - Node parse.Node - // Name is the name of the template in which the error was encountered. - Name string - // Line is the line number of the error in the template source or 0. - Line int - // Description is a human-readable description of the problem. - Description string -} - -// ErrorCode is a code for a kind of error. -type ErrorCode int - -// We define codes for each error that manifests while escaping templates, but -// escaped templates may also fail at runtime. -// -// Output: "ZgotmplZ" -// Example: -// -// where {{.X}} evaluates to `javascript:...` -// Discussion: -// "ZgotmplZ" is a special value that indicates that unsafe content reached a -// CSS or URL context at runtime. The output of the example will be -// -// If the data comes from a trusted source, use content types to exempt it -// from filtering: URL(`javascript:...`). -const ( - // OK indicates the lack of an error. - OK ErrorCode = iota - - // ErrAmbigContext: "... appears in an ambiguous context within a URL" - // Example: - // - // Discussion: - // {{.X}} is in an ambiguous URL context since, depending on {{.C}}, - // it may be either a URL suffix or a query parameter. - // Moving {{.X}} into the condition removes the ambiguity: - // - ErrAmbigContext - - // ErrBadHTML: "expected space, attr name, or end of tag, but got ...", - // "... in unquoted attr", "... in attribute name" - // Example: - // - // - //
- //
{{end}} - // {{define "attrs"}}href="{{.URL}}"{{end}} - // Discussion: - // Package html/template looks through template calls to compute the - // context. - // Here the {{.URL}} in "attrs" must be treated as a URL when called - // from "main", but you will get this error if "attrs" is not defined - // when "main" is parsed. - ErrNoSuchTemplate - - // ErrOutputContext: "cannot compute output context for template ..." - // Examples: - // {{define "t"}}{{if .T}}{{template "t" .T}}{{end}}{{.H}}",{{end}} - // Discussion: - // A recursive template does not end in the same context in which it - // starts, and a reliable output context cannot be computed. - // Look for typos in the named template. - // If the template should not be called in the named start context, - // look for calls to that template in unexpected contexts. - // Maybe refactor recursive templates to not be recursive. - ErrOutputContext - - // ErrPartialCharset: "unfinished JS regexp charset in ..." - // Example: - // - // Discussion: - // Package html/template does not support interpolation into regular - // expression literal character sets. - ErrPartialCharset - - // ErrPartialEscape: "unfinished escape sequence in ..." - // Example: - // - // Discussion: - // Package html/template does not support actions following a - // backslash. - // This is usually an error and there are better solutions; for - // example - // - // should work, and if {{.X}} is a partial escape sequence such as - // "xA0", mark the whole sequence as safe content: JSStr(`\xA0`) - ErrPartialEscape - - // ErrRangeLoopReentry: "on range loop re-entry: ..." - // Example: - // - // Discussion: - // If an iteration through a range would cause it to end in a - // different context than an earlier pass, there is no single context. - // In the example, there is missing a quote, so it is not clear - // whether {{.}} is meant to be inside a JS string or in a JS value - // context. The second iteration would produce something like - // - // - ErrRangeLoopReentry - - // ErrSlashAmbig: '/' could start a division or regexp. - // Example: - // - // Discussion: - // The example above could produce `var x = 1/-2/i.test(s)...` - // in which the first '/' is a mathematical division operator or it - // could produce `/-2/i.test(s)` in which the first '/' starts a - // regexp literal. - // Look for missing semicolons inside branches, and maybe add - // parentheses to make it clear which interpretation you intend. - ErrSlashAmbig - - // ErrPredefinedEscaper: "predefined escaper ... disallowed in template" - // Example: - //
Hello
- // Discussion: - // Package html/template already contextually escapes all pipelines to - // produce HTML output safe against code injection. Manually escaping - // pipeline output using the predefined escapers "html" or "urlquery" is - // unnecessary, and may affect the correctness or safety of the escaped - // pipeline output in Go 1.8 and earlier. - // - // In most cases, such as the given example, this error can be resolved by - // simply removing the predefined escaper from the pipeline and letting the - // contextual autoescaper handle the escaping of the pipeline. In other - // instances, where the predefined escaper occurs in the middle of a - // pipeline where subsequent commands expect escaped input, e.g. - // {{.X | html | makeALink}} - // where makeALink does - // return `link` - // consider refactoring the surrounding template to make use of the - // contextual autoescaper, i.e. - // link - // - // To ease migration to Go 1.9 and beyond, "html" and "urlquery" will - // continue to be allowed as the last command in a pipeline. However, if the - // pipeline occurs in an unquoted attribute value context, "html" is - // disallowed. Avoid using "html" and "urlquery" entirely in new templates. - ErrPredefinedEscaper - - // ErrEscapeAction: "cannot escape action ..." - // Discussion: - // Error returned while escaping an action using EscaperForContext. - // Refer to error message for more details. - // TODO: remove this error type and replace it with more informative sanitization errors. - ErrEscapeAction - - // ErrCSPCompatibility: `"javascript:" URI disallowed for CSP compatibility`, - // "inline event handler ... is disallowed for CSP compatibility - // Examples: - // A thing. - // foo - // Discussion: - // Inline event handlers (onclick="...", onerror="...") and - // links can be used to run scripts, - // so an attacker who finds an XSS bug could inject such HTML - // and execute malicious JavaScript. These patterns must be - // refactored into safer alternatives for compatibility with - // Content Security Policy (CSP). - // - // For example, the following HTML that contains an inline event handler: - // - // A thing. - // can be refactored into: - // A thing. - // - // - // Likewise, the following HTML containng a javascript: URI: - // foo - // can be refactored into: - // foo - // - ErrCSPCompatibility - // All JS templates inside script literals have to be balanced; otherwise a concatenation such as - // can contain XSS if data contains user-controlled escaped strings (e.g. as JSON). - ErrUnbalancedJsTemplate -) - -func (e *Error) Error() string { - switch { - case e.Node != nil: - loc, _ := (*parse.Tree)(nil).ErrorContext(e.Node) - return fmt.Sprintf("html/template:%s: %s", loc, e.Description) - case e.Line != 0: - return fmt.Sprintf("html/template:%s:%d: %s", e.Name, e.Line, e.Description) - case e.Name != "": - return fmt.Sprintf("html/template:%s: %s", e.Name, e.Description) - } - return "html/template: " + e.Description -} - -// errorf creates an error given a format string f and args. -// The template Name still needs to be supplied. -func errorf(k ErrorCode, node parse.Node, line int, f string, args ...interface{}) *Error { - return &Error{k, node, "", line, fmt.Sprintf(f, args...)} -} diff --git a/vendor/github.com/google/safehtml/template/escape.go b/vendor/github.com/google/safehtml/template/escape.go deleted file mode 100644 index 8a9d53dd5..000000000 --- a/vendor/github.com/google/safehtml/template/escape.go +++ /dev/null @@ -1,884 +0,0 @@ -// 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 ( - "bytes" - "fmt" - "html" - "reflect" - "strings" - "text/template" - "text/template/parse" -) - -// TODO: remove all unused escaping logic inherited from html/template. -// TODO: replace "escape" with "sanitize" in file names and contents to maintain consistency with safehtml/template docs. - -// escapeTemplate rewrites the named template, which must be -// associated with t, to guarantee that the output of any of the named -// templates is properly escaped. If no error is returned, then the named templates have -// been modified. Otherwise the named templates have been rendered -// unusable. -func escapeTemplate(tmpl *Template, node parse.Node, name string) error { - c, _ := tmpl.esc.escapeTree(context{}, node, name, 0) - var err error - if c.err != nil { - err, c.err.Name = c.err, name - } else if c.state != stateText { - err = &Error{ErrEndContext, nil, name, 0, fmt.Sprintf("ends in a non-text context: %+v", c)} - } - if err != nil { - // Prevent execution of unsafe templates. - if t := tmpl.set[name]; t != nil { - t.escapeErr = err - t.text.Tree = nil - t.Tree = nil - } - return err - } - tmpl.esc.commit() - if t := tmpl.set[name]; t != nil { - t.escapeErr = errEscapeOK - t.Tree = t.text.Tree - } - return nil -} - -// evalArgs formats the list of arguments into a string. It is equivalent to -// fmt.Sprint(args...), except that it deferences all pointers. -func evalArgs(args ...interface{}) string { - // Optimization for simple common case of a single string argument. - if len(args) == 1 { - if s, ok := args[0].(string); ok { - return s - } - } - for i, arg := range args { - args[i] = indirectToStringerOrError(arg) - } - return fmt.Sprint(args...) -} - -// escaper collects type inferences about templates and changes needed to make -// templates injection safe. -type escaper struct { - // ns is the nameSpace that this escaper is associated with. - ns *nameSpace - // output[templateName] is the output context for a templateName that - // has been mangled to include its input context. - output map[string]context - // derived[c.mangle(name)] maps to a template derived from the template - // named name templateName for the start context c. - derived map[string]*template.Template - // called[templateName] is a set of called mangled template names. - called map[string]bool - // xxxNodeEdits are the accumulated edits to apply during commit. - // Such edits are not applied immediately in case a template set - // executes a given template in different escaping contexts. - actionNodeEdits map[*parse.ActionNode][]string - templateNodeEdits map[*parse.TemplateNode]string - textNodeEdits map[*parse.TextNode][]byte -} - -// makeEscaper creates a blank escaper for the given set. -func makeEscaper(n *nameSpace) escaper { - return escaper{ - n, - map[string]context{}, - map[string]*template.Template{}, - map[string]bool{}, - map[*parse.ActionNode][]string{}, - map[*parse.TemplateNode]string{}, - map[*parse.TextNode][]byte{}, - } -} - -// escape escapes a template node. -func (e *escaper) escape(c context, n parse.Node) context { - switch n := n.(type) { - case *parse.ActionNode: - return e.escapeAction(c, n) - case *parse.IfNode: - return e.escapeBranch(c, &n.BranchNode, "if") - case *parse.ListNode: - return e.escapeList(c, n) - case *parse.RangeNode: - return e.escapeBranch(c, &n.BranchNode, "range") - case *parse.TemplateNode: - return e.escapeTemplate(c, n) - case *parse.TextNode: - return e.escapeText(c, n) - case *parse.WithNode: - return e.escapeBranch(c, &n.BranchNode, "with") - } - panic("escaping " + n.String() + " is unimplemented") -} - -// escapeAction escapes an action template node. -func (e *escaper) escapeAction(c context, n *parse.ActionNode) context { - if len(n.Pipe.Decl) != 0 { - // A local variable assignment, not an interpolation. - return c - } - c = nudge(c) - // Check for disallowed use of predefined escapers in the pipeline. - for pos, idNode := range n.Pipe.Cmds { - node, ok := idNode.Args[0].(*parse.IdentifierNode) - if !ok { - // A predefined escaper "esc" will never be found as an identifier in a - // Chain or Field node, since: - // - "esc.x ..." is invalid, since predefined escapers return strings, and - // strings do not have methods, keys or fields. - // - "... .esc" is invalid, since predefined escapers are global functions, - // not methods or fields of any types. - // Therefore, it is safe to ignore these two node types. - continue - } - ident := node.Ident - if _, ok := predefinedEscapers[ident]; ok { - if pos < len(n.Pipe.Cmds)-1 || - c.state == stateAttr && c.delim == delimSpaceOrTagEnd && ident == "html" { - return context{ - state: stateError, - err: errorf(ErrPredefinedEscaper, n, n.Line, "predefined escaper %q disallowed in template", ident), - } - } - } - } - switch c.state { - case stateError: - return c - case stateAttrName, stateTag: - c.state = stateAttrName - } - // TODO: integrate sanitizerForContext into escapeAction. - s, err := sanitizerForContext(c) - if err != nil { - return context{ - state: stateError, - // TODO: return sanitization-specific errors. - err: errorf(ErrEscapeAction, n, n.Line, "cannot escape action %v: %s", n, err), - } - } - e.editActionNode(n, s) - return c -} - -// ensurePipelineContains ensures that the pipeline ends with the commands with -// the identifiers in s in order. If the pipeline ends with a predefined escaper -// (i.e. "html" or "urlquery"), merge it with the identifiers in s.c -func ensurePipelineContains(p *parse.PipeNode, s []string) { - if len(s) == 0 { - // Do not rewrite pipeline if we have no escapers to insert. - return - } - // Precondition: p.Cmds contains at most one predefined escaper and the - // escaper will be present at p.Cmds[len(p.Cmds)-1]. This precondition is - // always true because of the checks in escapeAction. - pipelineLen := len(p.Cmds) - if pipelineLen > 0 { - lastCmd := p.Cmds[pipelineLen-1] - if idNode, ok := lastCmd.Args[0].(*parse.IdentifierNode); ok { - if esc := idNode.Ident; predefinedEscapers[esc] { - // Pipeline ends with a predefined escaper. - if len(p.Cmds) == 1 && len(lastCmd.Args) > 1 { - // Special case: pipeline is of the form {{ esc arg1 arg2 ... argN }}, - // where esc is the predefined escaper, and arg1...argN are its arguments. - // Convert this into the equivalent form - // {{ _eval_args_ arg1 arg2 ... argN | esc }}, so that esc can be easily - // merged with the escapers in s. - lastCmd.Args[0] = parse.NewIdentifier(evalArgsFuncName).SetTree(nil).SetPos(lastCmd.Args[0].Position()) - p.Cmds = append(p.Cmds, newIdentCmd(esc, p.Position())) - pipelineLen++ - } - // If any of the commands in s that we are about to insert is equivalent - // to the predefined escaper, use the predefined escaper instead. - dup := false - for i, escaper := range s { - if escFnsEq(esc, escaper) { - s[i] = idNode.Ident - dup = true - } - } - if dup { - // The predefined escaper will already be inserted along with the - // escapers in s, so do not copy it to the rewritten pipeline. - pipelineLen-- - } - } - } - } - // Rewrite the pipeline, creating the escapers in s at the end of the pipeline. - newCmds := make([]*parse.CommandNode, pipelineLen, pipelineLen+len(s)) - copy(newCmds, p.Cmds) - for _, name := range s { - newCmds = append(newCmds, newIdentCmd(name, p.Position())) - } - p.Cmds = newCmds -} - -// predefinedEscapers contains template predefined escapers that are equivalent -// to some contextual escapers. Keep in sync with equivEscapers. -var predefinedEscapers = map[string]bool{ - "html": true, - "urlquery": true, -} - -// equivEscapers matches contextual escapers to equivalent predefined -// template escapers. -var equivEscapers = map[string]string{ - // The following pairs of HTML escapers provide equivalent security - // guarantees, since they all escape '\000', '\'', '"', '&', '<', and '>'. - sanitizeHTMLFuncName: "html", - sanitizeRCDATAFuncName: "html", - // These two URL escapers produce URLs safe for embedding in a URL query by - // percent-encoding all the reserved characters specified in RFC 3986 Section - // 2.2 - queryEscapeURLFuncName: "urlquery", - // The normalizer function is not actually equivalent to urlquery; urlquery is - // stricter as it escapes reserved characters (e.g. '#'), while the normalizer - // function does not. It is therefore only safe to replace the normalizer with - // with urlquery (this happens in ensurePipelineContains), but not the other - // way around. We keep this entry around to preserve the behavior of templates - // written before Go 1.9, which might depend on this substitution taking place. - normalizeURLFuncName: "urlquery", -} - -// escFnsEq reports whether the two escaping functions are equivalent. -func escFnsEq(a, b string) bool { - return normalizeEscFn(a) == normalizeEscFn(b) -} - -// normalizeEscFn(a) is equal to normalizeEscFn(b) for any pair of names of -// escaper functions a and b that are equivalent. -func normalizeEscFn(e string) string { - if norm := equivEscapers[e]; norm != "" { - return norm - } - return e -} - -// newIdentCmd produces a command containing a single identifier node. -func newIdentCmd(identifier string, pos parse.Pos) *parse.CommandNode { - return &parse.CommandNode{ - NodeType: parse.NodeCommand, - Args: []parse.Node{parse.NewIdentifier(identifier).SetTree(nil).SetPos(pos)}, // TODO: SetTree. - Pos: pos, - } -} - -// nudge returns the context that would result from following empty string -// transitions from the input context. -// For example, parsing: -// `90% of the time. - e.output[t.Name()] = c - return e.escapeListConditionally(c, t.Tree.Root, filter) -} - -// delimEnds maps each delim to a string of characters that terminate it. -var delimEnds = [...]string{ - delimDoubleQuote: `"`, - delimSingleQuote: "'", - // Determined empirically by running the below in various browsers. - // var div = document.createElement("DIV"); - // for (var i = 0; i < 0x10000; ++i) { - // div.innerHTML = ""; - // if (div.getElementsByTagName("SPAN")[0].title.indexOf("bar") < 0) - // document.write("

U+" + i.toString(16)); - // } - delimSpaceOrTagEnd: " \t\n\f\r>", -} - -var doctypeBytes = []byte("= i; j-- { - if s[j] == '<' { - end = j - break - } - } - } - for j := i; j < end; j++ { - if s[j] == '<' && !bytes.HasPrefix(bytes.ToUpper(s[j:]), doctypeBytes) { - b.Write(s[written:j]) - b.WriteString("<") - written = j + 1 - } - } - } else if isComment(c.state) && c.delim == delimNone { - written = i1 - } - if c.state == stateSpecialElementBody && c.element.name == "script" { - if err := isJsTemplateBalanced(bytes.NewBuffer(s)); err != nil { - return context{ - state: stateError, - err: errorf(ErrUnbalancedJsTemplate, n, 0, "Mixing template systems can cause security vulnerabilites. Therefore, there can be no safehtml/template insertion points or actions inside an ES6 template, and all ES6 templates must be closed: %v", err.Error()), - } - } - } - - if c.state != c1.state && isComment(c1.state) && c1.delim == delimNone { - // Preserve the portion between written and the comment start. - cs := i1 - 2 - if c1.state == stateHTMLCmt { - // "") - -// tText is the context transition function for the text state. -func tText(c context, s []byte) (context, int) { - k := 0 - for { - i := k + bytes.IndexByte(s[k:], '<') - if i < k || i+1 == len(s) { - return c, len(s) - } else if i+4 <= len(s) && bytes.Equal(commentStart, s[i:i+4]) { - return context{state: stateHTMLCmt}, i + 4 - } - i++ - end := false - if s[i] == '/' { - if i+1 == len(s) { - return c, len(s) - } - end, i = true, i+1 - } - j, e := eatTagName(s, i) - if j != i { - // We've found an HTML tag. - ret := context{state: stateTag} - // Element name not needed if we are at the end of the element. - if !end { - ret.element = e - } - return ret, j - } - k = j - } -} - -// specialElements contains the names of elements whose bodies are treated -// differently by the parser and escaper from stateText. -var specialElements = map[string]bool{ - "script": true, - "style": true, - "textarea": true, - "title": true, -} - -// voidElements contains the names of all void elements. -// https://www.w3.org/TR/html5/syntax.html#void-elements -var voidElements = map[string]bool{ - "area": true, - "base": true, - "br": true, - "col": true, - "embed": true, - "hr": true, - "img": true, - "input": true, - "keygen": true, - "link": true, - "meta": true, - "param": true, - "source": true, - "track": true, - "wbr": true, -} - -// tTag is the context transition function for the tag state. -func tTag(c context, s []byte) (context, int) { - // Find the attribute name. - i := eatWhiteSpace(s, 0) - if i == len(s) { - return c, len(s) - } - if s[i] == '>' { - ret := context{ - state: stateText, - element: c.element, - scriptType: c.scriptType, - linkRel: c.linkRel, - } - if specialElements[c.element.name] { - ret.state = stateSpecialElementBody - } - if c.element.name != "" && voidElements[c.element.name] { - // Special case: end of start tag of a void element. - // Discard unnecessary state, since this element have no content. - ret.element = element{} - ret.scriptType = "" - ret.linkRel = "" - } - return ret, i + 1 - } - j, err := eatAttrName(s, i) - if err != nil { - return context{state: stateError, err: err}, len(s) - } - state := stateTag - if i == j { - return context{ - state: stateError, - err: errorf(ErrBadHTML, nil, 0, "expected space, attr name, or end of tag, but got %q", s[i:]), - }, len(s) - } - - if j == len(s) { - state = stateAttrName - } else { - state = stateAfterName - } - return context{ - state: state, - element: c.element, - attr: attr{name: strings.ToLower(string(s[i:j]))}, - linkRel: c.linkRel, - }, j -} - -// tAttrName is the context transition function for stateAttrName. -func tAttrName(c context, s []byte) (context, int) { - i, err := eatAttrName(s, 0) - if err != nil { - return context{state: stateError, err: err}, len(s) - } else if i != len(s) { - c.state = stateAfterName - } - return c, i -} - -// tAfterName is the context transition function for stateAfterName. -func tAfterName(c context, s []byte) (context, int) { - // Look for the start of the value. - i := eatWhiteSpace(s, 0) - if i == len(s) { - return c, len(s) - } else if s[i] != '=' { - // Occurs due to tag ending '>', and valueless attribute. - c.state = stateTag - return c, i - } - c.state = stateBeforeValue - // Consume the "=". - return c, i + 1 -} - -// tBeforeValue is the context transition function for stateBeforeValue. -func tBeforeValue(c context, s []byte) (context, int) { - i := eatWhiteSpace(s, 0) - if i == len(s) { - return c, len(s) - } - // Find the attribute delimiter. - // TODO: consider disallowing single-quoted or unquoted attribute values completely, even in hardcoded template text. - delim := delimSpaceOrTagEnd - switch s[i] { - case '\'': - delim, i = delimSingleQuote, i+1 - case '"': - delim, i = delimDoubleQuote, i+1 - } - c.state, c.delim = stateAttr, delim - return c, i -} - -// tHTMLCmt is the context transition function for stateHTMLCmt. -func tHTMLCmt(c context, s []byte) (context, int) { - if i := bytes.Index(s, commentEnd); i != -1 { - return context{}, i + 3 - } - return c, len(s) -} - -var ( - specialTagEndPrefix = []byte(" \t\n\f/") -) - -// tSpecialTagEnd is the context transition function for raw text, RCDATA -// script data, and stylesheet element states. -func tSpecialTagEnd(c context, s []byte) (context, int) { - if specialElements[c.element.name] { - if i := indexTagEnd(s, []byte(c.element.name)); i != -1 { - return context{}, i - } - } - return c, len(s) -} - -// indexTagEnd finds the index of a special tag end in a case insensitive way, or returns -1 -func indexTagEnd(s []byte, tag []byte) int { - res := 0 - plen := len(specialTagEndPrefix) - for len(s) > 0 { - // Try to find the tag end prefix first - i := bytes.Index(s, specialTagEndPrefix) - if i == -1 { - return i - } - s = s[i+plen:] - // Try to match the actual tag if there is still space for it - if len(tag) <= len(s) && bytes.EqualFold(tag, s[:len(tag)]) { - s = s[len(tag):] - // Check the tag is followed by a proper separator - if len(s) > 0 && bytes.IndexByte(tagEndSeparators, s[0]) != -1 { - return res + i - } - res += len(tag) - } - res += i + plen - } - return -1 -} - -// tAttr is the context transition function for the attribute state. -func tAttr(c context, s []byte) (context, int) { - return c, len(s) -} - -// tError is the context transition function for the error state. -func tError(c context, s []byte) (context, int) { - return c, len(s) -} - -// eatAttrName returns the largest j such that s[i:j] is an attribute name. -// It returns an error if s[i:] does not look like it begins with an -// attribute name, such as encountering a quote mark without a preceding -// equals sign. -func eatAttrName(s []byte, i int) (int, *Error) { - for j := i; j < len(s); j++ { - switch s[j] { - case ' ', '\t', '\n', '\f', '\r', '=', '>': - return j, nil - case '\'', '"', '<': - // These result in a parse warning in HTML5 and are - // indicative of serious problems if seen in an attr - // name in a template. - return -1, errorf(ErrBadHTML, nil, 0, "%q in attribute name: %.32q", s[j:j+1], s) - default: - // No-op. - } - } - return len(s), nil -} - -// asciiAlpha reports whether c is an ASCII letter. -func asciiAlpha(c byte) bool { - return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' -} - -// asciiAlphaNum reports whether c is an ASCII letter or digit. -func asciiAlphaNum(c byte) bool { - return asciiAlpha(c) || '0' <= c && c <= '9' -} - -// eatTagName returns the largest j such that s[i:j] is a tag name and the tag name. -func eatTagName(s []byte, i int) (int, element) { - if i == len(s) || !asciiAlpha(s[i]) { - return i, element{} - } - j := i + 1 - for j < len(s) { - x := s[j] - if asciiAlphaNum(x) { - j++ - continue - } - // Allow "x-y" or "x:y" but not "x-", "-y", or "x--y". - if (x == ':' || x == '-') && j+1 < len(s) && asciiAlphaNum(s[j+1]) { - j += 2 - continue - } - break - } - return j, element{name: strings.ToLower(string(s[i:j]))} -} - -// eatWhiteSpace returns the largest j such that s[i:j] is white space. -func eatWhiteSpace(s []byte, i int) int { - for j := i; j < len(s); j++ { - switch s[j] { - case ' ', '\t', '\n', '\f', '\r': - // No-op. - default: - return j - } - } - return len(s) -} diff --git a/vendor/github.com/google/safehtml/template/trustedfs.go b/vendor/github.com/google/safehtml/template/trustedfs.go deleted file mode 100644 index 80db11824..000000000 --- a/vendor/github.com/google/safehtml/template/trustedfs.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) 2021 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 or at -// https://developers.google.com/open-source/licenses/bsd - -//go:build go1.16 -// +build go1.16 - -package template - -import ( - "embed" - "fmt" - "io/fs" - "os" - "path" -) - -// A TrustedFS is an immutable type referencing a filesystem (fs.FS) -// under application control. -// -// In order to ensure that an attacker cannot influence the TrustedFS value, a -// TrustedFS can be instantiated in only two ways. One way is from an embed.FS -// with TrustedFSFromEmbed. It is assumed that embedded filesystems are under -// the programmer's control. The other way is from a TrustedSource using -// TrustedFSFromTrustedSource, in which case the guarantees and caveats of -// TrustedSource apply. -type TrustedFS struct { - fsys fs.FS -} - -// TrustedFSFromEmbed constructs a TrustedFS from an embed.FS. -func TrustedFSFromEmbed(fsys embed.FS) TrustedFS { - return TrustedFS{fsys: fsys} -} - -// TrustedFSFromTrustedSource constructs a TrustedFS from the string in the -// TrustedSource, which should refer to a directory. -func TrustedFSFromTrustedSource(ts TrustedSource) TrustedFS { - return TrustedFS{fsys: os.DirFS(ts.src)} -} - -// Sub returns a TrustedFS at a subdirectory of the receiver. -// It works by calling fs.Sub on the receiver's fs.FS. -func (tf TrustedFS) Sub(dir TrustedSource) (TrustedFS, error) { - subfs, err := fs.Sub(tf.fsys, dir.String()) - return TrustedFS{fsys: subfs}, err -} - -// ParseFS is like ParseFiles or ParseGlob but reads from the TrustedFS -// instead of the host operating system's file system. -// It accepts a list of glob patterns. -// (Note that most file names serve as glob patterns matching only themselves.) -// -// The same behaviors listed for ParseFiles() apply to ParseFS too (e.g. using the base name -// of the file as the template name). -func ParseFS(tfs TrustedFS, patterns ...string) (*Template, error) { - return parseFS(nil, tfs.fsys, patterns) -} - -// ParseFS is like ParseFiles or ParseGlob but reads from the TrustedFS -// instead of the host operating system's file system. -// It accepts a list of glob patterns. -// (Note that most file names serve as glob patterns matching only themselves.) -// -// The same behaviors listed for ParseFiles() apply to ParseFS too (e.g. using the base name -// of the file as the template name). -func (t *Template) ParseFS(tfs TrustedFS, patterns ...string) (*Template, error) { - return parseFS(t, tfs.fsys, patterns) -} - -// Copied from -// https://go.googlesource.com/go/+/refs/tags/go1.17.1/src/text/template/helper.go. -func parseFS(t *Template, fsys fs.FS, patterns []string) (*Template, error) { - var filenames []string - for _, pattern := range patterns { - list, err := fs.Glob(fsys, pattern) - if err != nil { - return nil, err - } - if len(list) == 0 { - return nil, fmt.Errorf("template: pattern matches no files: %#q", pattern) - } - filenames = append(filenames, list...) - } - return parseFiles(t, readFileFS(fsys), filenames...) -} - -// Copied with minor changes from -// https://go.googlesource.com/go/+/refs/tags/go1.17.1/src/text/template/helper.go. -func readFileFS(fsys fs.FS) func(string) (string, []byte, error) { - return func(file string) (string, []byte, error) { - name := path.Base(file) - b, err := fs.ReadFile(fsys, file) - return name, b, err - } -} diff --git a/vendor/github.com/google/safehtml/template/trustedsource.go b/vendor/github.com/google/safehtml/template/trustedsource.go deleted file mode 100644 index f64263948..000000000 --- a/vendor/github.com/google/safehtml/template/trustedsource.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) 2017 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 or at -// https://developers.google.com/open-source/licenses/bsd - -package template - -import ( - "fmt" - "os" - "path/filepath" - "strings" - - "flag" -) - -// A TrustedSource is an immutable string-like type referencing -// trusted template files under application control. It can be passed to -// template-parsing functions and methods to safely load templates -// without the risk of untrusted template execution. -// -// In order to ensure that an attacker cannot influence the TrustedSource -// value, a TrustedSource can be instantiated only from untyped string -// constants, command-line flags, and other application-controlled strings, but -// never from arbitrary string values potentially representing untrusted user input. -// -// Note that TrustedSource's constructors cannot truly guarantee that the -// templates it references are not attacker-controlled; it can guarantee only that -// the path to the template itself is under application control. Users of these -// constructors must ensure themselves that TrustedSource never references -// attacker-controlled files or directories that contain such files. -type TrustedSource struct { - // We declare a TrustedSource not as a string but as a struct wrapping a string - // to prevent construction of TrustedSource values through string conversion. - src string -} - -// TrustedSourceFromConstant constructs a TrustedSource with its underlying -// src set to the given src, which must be an untyped string constant. -// -// No runtime validation or sanitization is performed on src; being under -// application control, it is simply assumed to comply with the TrustedSource type -// contract. -func TrustedSourceFromConstant(src stringConstant) TrustedSource { - return TrustedSource{string(src)} -} - -// TrustedSourceFromConstantDir constructs a TrustedSource calling path/filepath.Join on -// an application-controlled directory path, which must be an untyped string constant, -// a TrustedSource, and a dynamic filename. It returns an error if filename contains -// filepath or list separators, since this might cause the resulting path to reference a -// file outside of the given directory. -// -// dir or src may be empty if either of these path segments are not required. -func TrustedSourceFromConstantDir(dir stringConstant, src TrustedSource, filename string) (TrustedSource, error) { - if i := strings.IndexAny(filename, string([]rune{filepath.Separator, filepath.ListSeparator})); i != -1 { - return TrustedSource{}, fmt.Errorf("filename %q must not contain the separator %q", filename, filename[i]) - } - if filename == ".." { - return TrustedSource{}, fmt.Errorf("filename must not be the special name %q", filename) - } - return TrustedSource{filepath.Join(string(dir), src.String(), filename)}, nil -} - -// TrustedSourceJoin is a wrapper around path/filepath.Join that returns a -// TrustedSource formed by joining the given path elements into a single path, -// adding an OS-specific path separator if necessary. -func TrustedSourceJoin(elem ...TrustedSource) TrustedSource { - return TrustedSource{filepath.Join(trustedSourcesToStrings(elem)...)} -} - -// TrustedSourceFromFlag returns a TrustedSource containing the string -// representation of the retrieved value of the flag. -// -// In a server setting, flags are part of the application's deployment -// configuration and are hence considered application-controlled. -func TrustedSourceFromFlag(value flag.Value) TrustedSource { - return TrustedSource{fmt.Sprint(value.String())} -} - -// TrustedSourceFromEnvVar is a wrapper around os.Getenv that -// returns a TrustedSource containing the value of the environment variable -// named by the key. It returns the value, which will be empty if the variable -// is not present. To distinguish between an empty value and an unset value, -// use os.LookupEnv. -// -// In a server setting, environment variables are part of the application's -// deployment configuration and are hence considered application-controlled. -func TrustedSourceFromEnvVar(key stringConstant) TrustedSource { - return TrustedSource{os.Getenv(string(key))} -} - -// String returns the string form of the TrustedSource. -func (t TrustedSource) String() string { - return t.src -} - -func trustedSourcesToStrings(paths []TrustedSource) []string { - ret := make([]string, 0, len(paths)) - for _, p := range paths { - ret = append(ret, p.String()) - } - return ret -} diff --git a/vendor/github.com/google/safehtml/template/trustedtemplate.go b/vendor/github.com/google/safehtml/template/trustedtemplate.go deleted file mode 100644 index bd3b1b46a..000000000 --- a/vendor/github.com/google/safehtml/template/trustedtemplate.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2017 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 or at -// https://developers.google.com/open-source/licenses/bsd - -package template - -// A TrustedTemplate is an immutable string-like type containing a -// safehtml/template template body. It can be safely loaded as template -// text without the risk of untrusted template execution. -// -// In order to ensure that an attacker cannot influence the TrustedTemplate -// value, a TrustedTemplate can be instantiated only from untyped string constants, -// and never from arbitrary string values potentially representing untrusted user input. -// -type TrustedTemplate struct { - // We declare a TrustedTemplate not as a string but as a struct wrapping a string - // to prevent construction of TrustedTemplate values through string conversion. - tmpl string -} - -// MakeTrustedTemplate constructs a TrustedTemplate with its underlying -// tmpl set to the given tmpl, which must be an untyped string constant. -// -// No runtime validation or sanitization is performed on tmpl; being under -// application control, it is simply assumed to comply with the TrustedTemplate type -// contract. -func MakeTrustedTemplate(tmpl stringConstant) TrustedTemplate { - return TrustedTemplate{string(tmpl)} -} - -// String returns the string form of the TrustedTemplate. -func (t TrustedTemplate) String() string { - return t.tmpl -} diff --git a/vendor/github.com/google/safehtml/template/url.go b/vendor/github.com/google/safehtml/template/url.go deleted file mode 100644 index f63475fcf..000000000 --- a/vendor/github.com/google/safehtml/template/url.go +++ /dev/null @@ -1,122 +0,0 @@ -// 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 ( - "fmt" - "html" - "regexp" - "strings" - - "github.com/google/safehtml/internal/safehtmlutil" - "github.com/google/safehtml" -) - -// urlPrefixValidators maps URL and TrustedResourceURL sanitization contexts to functions return an error -// if the given string is unsafe to use as a URL prefix in that sanitization context. -var urlPrefixValidators = map[sanitizationContext]func(string) error{ - sanitizationContextURL: validateURLPrefix, - sanitizationContextTrustedResourceURLOrURL: validateURLPrefix, - sanitizationContextTrustedResourceURL: validateTrustedResourceURLPrefix, -} - -// startsWithFullySpecifiedSchemePattern matches strings that have a fully-specified scheme component. -// See RFC 3986 Section 3. -var startsWithFullySpecifiedSchemePattern = regexp.MustCompile( - `^[[:alpha:]](?:[[:alnum:]]|[+.-])*:`) - -// validateURLPrefix validates if the given non-empty prefix is a safe safehtml.URL prefix. -// -// Prefixes are considered unsafe if they end in an incomplete HTML character reference -// or percent-encoding character triplet. -// -// If the prefix contains a fully-specified scheme component, it is considered safe only if -// it starts with an allowed scheme. See safehtml.URLSanitized for more details. -// -// Otherwise, the prefix is safe only if it contains '/', '?', or '#', since the presence of any -// of these runes ensures that this prefix, when combined with some arbitrary suffix, cannot be -// interpreted as a part of a scheme. -func validateURLPrefix(prefix string) error { - decoded, err := decodeURLPrefix(prefix) - if err != nil { - return err - } - switch { - case startsWithFullySpecifiedSchemePattern.MatchString(decoded): - if safehtml.URLSanitized(decoded).String() != decoded { - return fmt.Errorf("URL prefix %q contains an unsafe scheme", prefix) - } - case !strings.ContainsAny(decoded, "/?#"): - // If the URL prefix does not already have a ':' scheme delimiter, and does not contain - // '/', '?', or '#', any ':' following this prefix will be intepreted as a scheme - // delimiter, causing this URL prefix to be interpreted as being part of a scheme. - // e.g. `` - return fmt.Errorf("URL prefix %q is unsafe; it might be interpreted as part of a scheme", prefix) - } - return nil -} - -// validateTrustedResourceURLPrefix validates if the given non-empty prefix is a safe -// safehtml.TrustedResourceURL prefix. -// -// Prefixes are considered unsafe if they end in an incomplete HTML character reference -// or percent-encoding character triplet. -// -// See safehtmlutil.IsSafeTrustedResourceURLPrefix for details on how the prefix is validated. -func validateTrustedResourceURLPrefix(prefix string) error { - decoded, err := decodeURLPrefix(prefix) - if err != nil { - return err - } - if !safehtmlutil.IsSafeTrustedResourceURLPrefix(decoded) { - return fmt.Errorf("%q is a disallowed TrustedResourceURL prefix", prefix) - } - return nil -} - -// endsWithPercentEncodingPrefixPattern matches strings that end in an incomplete -// URL percent encoding triplet. -// -// See https://tools.ietf.org/html/rfc3986#section-2.1. -var endsWithPercentEncodingPrefixPattern = regexp.MustCompile( - `%[[:xdigit:]]?$`) - -// containsWhitespaceOrControlPattern matches strings that contain ASCII whitespace -// or control characters. -var containsWhitespaceOrControlPattern = regexp.MustCompile(`[[:space:]]|[[:cntrl:]]`) - -// decodeURLPrefix returns the given prefix after it has been HTML-unescaped. -// It returns an error if the prefix: -// * ends in an incomplete HTML character reference before HTML-unescaping, -// * ends in an incomplete percent-encoding character triplet after HTML-unescaping, or -// * contains whitespace before or after HTML-unescaping. -func decodeURLPrefix(prefix string) (string, error) { - if containsWhitespaceOrControlPattern.MatchString(prefix) { - return "", fmt.Errorf("URL prefix %q contains whitespace or control characters", prefix) - } - if err := validateDoesNotEndsWithCharRefPrefix(prefix); err != nil { - return "", fmt.Errorf("URL %s", err) - } - decoded := html.UnescapeString(prefix) - // Check again for whitespace that might have previously been masked by a HTML reference, - // such as in "javascript ". - if containsWhitespaceOrControlPattern.MatchString(decoded) { - return "", fmt.Errorf("URL prefix %q contains whitespace or control characters", prefix) - } - if endsWithPercentEncodingPrefixPattern.MatchString(decoded) { - return "", fmt.Errorf("URL prefix %q ends with an incomplete percent-encoding character triplet", prefix) - } - return decoded, nil -} - -func validateTrustedResourceURLSubstitution(args ...interface{}) (string, error) { - input := safehtmlutil.Stringify(args...) - if safehtmlutil.URLContainsDoubleDotSegment(input) { - // Reject substitutions containing the ".." dot-segment to prevent the final TrustedResourceURL from referencing - // a resource higher up in the path name hierarchy than the path specified in the prefix. - return "", fmt.Errorf(`cannot substitute %q after TrustedResourceURL prefix: ".." is disallowed`, input) - } - return input, nil -} -- cgit mrf-deployment