diff --git a/content/en/functions/_common/go-html-template-package.md b/content/en/functions/_common/go-html-template-package.md new file mode 100644 index 0000000000..b622f2b76e --- /dev/null +++ b/content/en/functions/_common/go-html-template-package.md @@ -0,0 +1,14 @@ +--- +# Do not remove front matter. +--- + +Hugo uses Go's [text/template] and [html/template] packages. + +The text/template package implements data-driven templates for generating textual output, while the html/template package implements data-driven templates for generating HTML output safe against code injection. + +By default, Hugo uses the html/template package when rendering HTML files. + +To generate HTML output that is safe against code injection, the html/template package escapes strings in certain contexts. + +[text/template]: https://pkg.go.dev/text/template +[html/template]: https://pkg.go.dev/html/template diff --git a/content/en/functions/safe/CSS.md b/content/en/functions/safe/CSS.md index 08307fb159..05ca25e110 100644 --- a/content/en/functions/safe/CSS.md +++ b/content/en/functions/safe/CSS.md @@ -1,6 +1,6 @@ --- title: safe.CSS -description: Declares the given string as safe CSS string. +description: Declares the given string as a safe CSS string. categories: [] keywords: [] action: @@ -13,21 +13,57 @@ action: - functions/safe/URL returnType: template.CSS signatures: [safe.CSS INPUT] +toc: true aliases: [/functions/safecss] --- -In this context, *safe* means CSS content that matches any of the following: +## Introduction + +{{% include "functions/_common/go-html-template-package.md" %}} + +## Usage + +Use the `safe.CSS` function to encapsulate known safe content that matches any of: 1. The CSS3 stylesheet production, such as `p { color: purple }`. 2. The CSS3 rule production, such as `a[href=~"https:"].foo#bar`. 3. CSS3 declaration productions, such as `color: red; margin: 2px`. 4. The CSS3 value production, such as `rgba(0, 0, 255, 127)`. -Example: Given `style = "color: red;"` defined in the front matter of your `.md` file: +Use of this type presents a security risk: the encapsulated content should come from a trusted source, as it will be included verbatim in the template output. + +See the [Go documentation] for details. + +[Go documentation]: https://pkg.go.dev/html/template#CSS + +## Example + +Without a safe declaration: -* `
…
` → `…
` -* `…
` → `…
` +```go-html-template +{{ $style := "color: red;" }} +foo
+``` + +Hugo renders the above to: + +```html +foo
+``` {{% note %}} -`ZgotmplZ` is a special value that indicates that unsafe content reached a CSS or URL context. +`ZgotmplZ` is a special value that indicates that unsafe content reached a CSS or URL context at runtime. {{% /note %}} + +To declare the string as safe: + +```go-html-template +{{ $style := "color: red;" }} +foo
+``` + +Hugo renders the above to: + +```html +foo
+``` diff --git a/content/en/functions/safe/HTML.md b/content/en/functions/safe/HTML.md index ecc4f1346c..ad1b3a6816 100644 --- a/content/en/functions/safe/HTML.md +++ b/content/en/functions/safe/HTML.md @@ -13,27 +13,48 @@ action: - functions/safe/URL returnType: template.HTML signatures: [safe.HTML INPUT] +toc: true aliases: [/functions/safehtml] --- -It should not be used for HTML from a third-party, or HTML with unclosed tags or comments. +## Introduction -Given a site-wide [`hugo.toml`][config] with the following `copyright` value: +{{% include "functions/_common/go-html-template-package.md" %}} -{{< code-toggle file=hugo >}} -copyright = "© 2015 Jane Doe. Some rights reserved." -{{< /code-toggle >}} +## Usage -`{{ .Site.Copyright | safeHTML }}` in a template would then output: +Use the `safe.HTML` function to encapsulate a known safe HTML document fragment. It should not be used for HTML from a third-party, or HTML with unclosed tags or comments. -```html -© 2015 Jane Doe. Some rights reserved. +Use of this type presents a security risk: the encapsulated content should come from a trusted source, as it will be included verbatim in the template output. + +See the [Go documentation] for details. + +[Go documentation]: https://pkg.go.dev/html/template#HTML + +## Example + +Without a safe declaration: + +```go-html-template +{{ $html := "emphasized" }} +{{ $html }} ``` -However, without the `safeHTML` function, html/template assumes `.Site.Copyright` to be unsafe and therefore escapes all HTML tags and renders the whole string as plain text: +Hugo renders the above to: ```html -© 2015 Jane Doe. <a href="https://creativecommons.org/licenses by/4.0/">Some rights reserved</a>.
+<em>emphasized</em> ``` -[config]: /getting-started/configuration/ +To declare the string as safe: + +```go-html-template +{{ $html := "emphasized" }} +{{ $html | safeHTML }} +``` + +Hugo renders the above to: + +```html +emphasized +``` diff --git a/content/en/functions/safe/HTMLAttr.md b/content/en/functions/safe/HTMLAttr.md index d827b603ac..d01a3908aa 100644 --- a/content/en/functions/safe/HTMLAttr.md +++ b/content/en/functions/safe/HTMLAttr.md @@ -13,43 +13,54 @@ action: - functions/safe/URL returnType: template.HTMLAttr signatures: [safe.HTMLAttr INPUT] +toc: true aliases: [/functions/safehtmlattr] --- -Given a site configuration that contains this menu entry: +## Introduction -{{< code-toggle file=hugo >}} -[[menus.main]] - name = "IRC" - url = "irc://irc.freenode.net/#golang" -{{< /code-toggle >}} +{{% include "functions/_common/go-html-template-package.md" %}} -Attempting to use the `url` value directly in an attribute: +## Usage + +Use the `safe.HTMLAttr` function to encapsulate an HTML attribute from a trusted source. + +Use of this type presents a security risk: the encapsulated content should come from a trusted source, as it will be included verbatim in the template output. + +See the [Go documentation] for details. + +[Go documentation]: https://pkg.go.dev/html/template#HTMLAttr + +## Example + +Without a safe declaration: ```go-html-template -{{ range site.Menus.main }} - {{ .Name }} +{{ with .Date }} + {{ $humanDate := time.Format "2 Jan 2006" . }} + {{ $machineDate := time.Format "2006-01-02T15:04:05-07:00" . }} + {{ end }} ``` -Will produce: +Hugo renders the above to: ```html -IRC + ``` -`ZgotmplZ` is a special value, inserted by Go's [template/html] package, that indicates that unsafe content reached a CSS or URL context. - -To indicate that the HTML attribute is safe: +To declare the key-value pair as safe: ```go-html-template -{{ range site.Menus.main }} - {{ .Name }} +{{ with .Date }} + {{ $humanDate := time.Format "2 Jan 2006" . }} + {{ $machineDate := time.Format "2006-01-02T15:04:05-07:00" . }} + {{ end }} ``` -{{% note %}} -As demonstrated above, you must pass the HTML attribute name _and_ value through the function. Applying `safeHTMLAttr` to the attribute value has no effect. -{{% /note %}} +Hugo renders the above to: -[template/html]: https://pkg.go.dev/html/template +```html + +``` diff --git a/content/en/functions/safe/JS.md b/content/en/functions/safe/JS.md index 65279b89be..d0d3a227af 100644 --- a/content/en/functions/safe/JS.md +++ b/content/en/functions/safe/JS.md @@ -13,14 +13,54 @@ action: - functions/safe/URL returnType: template.JS signatures: [safe.JS INPUT] +toc: true aliases: [/functions/safejs] --- -In this context, *safe* means the string encapsulates a known safe EcmaScript5 Expression (e.g., `(x + y * z())`). +## Introduction -Template authors are responsible for ensuring that typed expressions do not break the intended precedence and that there is no statement/expression ambiguity as when passing an expression like `{ foo:bar() }\n['foo']()`, which is both a valid expression and a valid program with a very different meaning. +{{% include "functions/_common/go-html-template-package.md" %}} -Example: Given `hash = "619c16f"` defined in the front matter of your `.md` file: +## Usage -* `` → `` -* `` → `` +Use the `safe.JS` function to encapsulate a known safe EcmaScript5 Expression. + +Template authors are responsible for ensuring that typed expressions do not break the intended precedence and that there is no statement/expression ambiguity as when passing an expression like `{ foo: bar() }\n['foo']()`, which is both a valid Expression and a valid Program with a very different meaning. + +Use of this type presents a security risk: the encapsulated content should come from a trusted source, as it will be included verbatim in the template output. + +Using the `safe.JS` function to include valid but untrusted JSON is not safe. A safe alternative is to parse the JSON with the [`transform.Unmarshal`] function and then pass the resultant object into the template, where it will be converted to sanitized JSON when presented in a JavaScript context. + +[`transform.Unmarshal`]: /functions/transform/unmarshal/ + +See the [Go documentation] for details. + +[Go documentation]: https://pkg.go.dev/html/template#JS + +## Example + +Without a safe declaration: + +```go-html-template +{{ $js := "x + y" }} + +``` + +Hugo renders the above to: + +```html + +``` + +To declare the string as safe: + +```go-html-template +{{ $js := "x + y" }} + +``` + +Hugo renders the above to: + +```html + +``` diff --git a/content/en/functions/safe/JSStr.md b/content/en/functions/safe/JSStr.md index 36d2b36fa8..e7e232d1be 100644 --- a/content/en/functions/safe/JSStr.md +++ b/content/en/functions/safe/JSStr.md @@ -13,12 +13,27 @@ action: - functions/safe/URL returnType: template.JSStr signatures: [safe.JSStr INPUT] +toc: true aliases: [/functions/safejsstr] --- -Encapsulates a sequence of characters meant to be embedded between quotes in a JavaScript expression. Use of this type presents a security risk: the encapsulated content should come from a trusted source, as it will be included verbatim in the template output. - -Without declaring a variable to be a safe JavaScript string: +## Introduction + +{{% include "functions/_common/go-html-template-package.md" %}} + +## Usage + +Use the `safe.JSStr` function to encapsulate a sequence of characters meant to be embedded between quotes in a JavaScript expression. + +Use of this type presents a security risk: the encapsulated content should come from a trusted source, as it will be included verbatim in the template output. + +See the [Go documentation] for details. + +[Go documentation]: https://pkg.go.dev/html/template#JSStr + +## Example + +Without a safe declaration: ```go-html-template {{ $title := "Lilo & Stitch" }} @@ -27,7 +42,7 @@ Without declaring a variable to be a safe JavaScript string: ``` -Rendered: +Hugo renders the above to: ```html ``` -To avoid escaping by Go's [html/template] package: +To declare the string as safe: ```go-html-template {{ $title := "Lilo & Stitch" }} @@ -44,12 +59,10 @@ To avoid escaping by Go's [html/template] package: ``` -Rendered: +Hugo renders the above to: ```html ``` - -[html/template]: https://pkg.go.dev/html/template diff --git a/content/en/functions/safe/URL.md b/content/en/functions/safe/URL.md index 2da6895e53..e4b3224dac 100644 --- a/content/en/functions/safe/URL.md +++ b/content/en/functions/safe/URL.md @@ -13,58 +13,56 @@ action: - functions/safe/JSStr returnType: template.URL signatures: [safe.URL INPUT] +toc: true aliases: [/functions/safeurl] --- -`safeURL` declares the provided string as a "safe" URL or URL substring (see [RFC 3986]). A URL like `javascript:checkThatFormNotEditedBeforeLeavingPage()` from a trusted source should go in the page, but by default dynamic `javascript:` URLs are filtered out since they are a frequently exploited injection vector. +## Introduction -Without `safeURL`, only the URI schemes `http:`, `https:` and `mailto:` are considered safe by Go templates. If any other URI schemes (e.g., `irc:` and `javascript:`) are detected, the whole URL will be replaced with `#ZgotmplZ`. This is to "defang" any potential attack in the URL by rendering it useless. +{{% include "functions/_common/go-html-template-package.md" %}} -The following examples use a [site `hugo.toml`][configuration] with the following [menu entry][menus]: +## Usage -{{< code-toggle file=hugo >}} -[[menus.main]] -name = "IRC: #golang at freenode" -url = "irc://irc.freenode.net/#golang" -{{< /code-toggle >}} +Use the `safe.URL` function to encapsulate a known safe URL or URL substring. Schemes other than the following are considered unsafe: -The following is an example of a sidebar partial that may be used in conjunction with the preceding front matter example: +- `http:` +- `https:` +- `mailto:` -{{< code file=layouts/partials/bad-url-sidebar-menu.html >}} - -