May 2, 2023·5 min read·engineeringgosecuritytemplates

Go 1.20.4 repairs three contextual escaping failures

Three html/template fixes address CSS delimiters, JavaScript whitespace and empty unquoted attributes. Each concerns the browser interpreting a boundary differently from the template engine.

Automatic escaping depends on knowing which language will interpret the next byte. A value inside HTML text needs different treatment from a value inside JavaScript or CSS. Go's May security release repairs three cases where html/template did not preserve that relationship. The Go 1.20.4 release record identifies three security fixes in the package, alongside other maintenance changes.

The May 2 announcement also releases Go 1.19.9 with the security corrections. Its descriptions concern specific template contexts and inputs. They do not say that every use of html/template allows injection, or that an attacker must control the template source itself.

I prefer contextual escaping because it lets a template express a document while the library handles the encoding obligations of each insertion. That preference makes defects in the context model particularly important. Application code can follow the intended API and still depend on the library recognizing the same boundaries as the browser.

The template source and its data have different authority

The package documentation at the release tag states the security model explicitly. Template authors are trusted. Data supplied when executing a template is untrusted. The package seeks to keep that data from changing the document's structure or introducing executable code beyond what the author specified.

To do this, the package analyzes where actions occur and adds the necessary escaping operations. An action in a URL query has obligations different from an action in visible text. The surrounding attribute adds another layer of interpretation. Escaping is therefore a relationship between the inserted value and the syntax that surrounds it.

This model also explains why escaping a string once is not a universal solution. A representation safe for one context can be wrong for another. The library's value comes from following context through the template, including the transitions between HTML and embedded languages. The three fixes all concern details that affect those transitions.

CSS values could terminate their context

CVE-2023-24539 concerns angle brackets in CSS values. According to the announcement, the sanitizer did not consider those characters dangerous in that context. Templates with multiple actions separated by a slash could unexpectedly close the CSS context when executed with untrusted input, allowing unexpected HTML into the result.

The combination of actions matters. Reviewing one value in isolation can miss an interaction with literal syntax and another inserted value. The safety claim applies to the final document that the browser parses, including the characters that separate the actions. A filter that looks adequate for an isolated CSS fragment may fail to preserve the surrounding HTML boundary.

That is why the announcement's conditions are more useful than a general statement that CSS escaping was broken. They identify a template shape and an interpretation change. An exposure review can look for those shapes while keeping the underlying cause clear. The library must prevent untrusted data from ending the intended context.

The correction belongs in contextual sanitization. Asking every template author to remember an extra rule for the interaction between slash-separated actions would weaken the API's central guarantee. Application-specific restrictions can reduce exposure, but the package still needs to model the relevant syntax correctly.

JavaScript whitespace changed the parser's state

CVE-2023-24540 concerns valid JavaScript whitespace that the template engine did not recognize as whitespace. The announcement identifies templates containing such characters in JavaScript contexts that also contain actions. The incomplete character classification could cause improper sanitization during execution.

Whitespace can affect how a parser classifies what follows it. Treating a character as ordinary data when JavaScript treats it as whitespace can leave the template engine and browser with different interpretations of the same output. The security consequence comes from that disagreement, even though the relevant character may look unremarkable in a source review.

The stated conditions also distinguish this defect from a general objection to embedding data in JavaScript. The package is designed to understand JavaScript contexts. This fix repairs a case within that support. The exact character rules are part of implementing the advertised behavior, rather than an optional refinement for unusually elaborate templates.

I value a standard library that takes responsibility for these details because a local escaping helper is unlikely to have a better language model. The useful response to this kind of defect is to correct the shared implementation and preserve the trust boundary it documents.

Empty attributes can change the surrounding HTML

CVE-2023-29400 concerns an action in an unquoted HTML attribute, such as attr={{.}}, when the supplied input is empty. The announcement says HTML normalization rules could produce unexpected parsing and allow arbitrary attributes to be injected into a tag.

The empty input is the important detail. Injection analysis often concentrates on dangerous nonempty strings. Here, removing the inserted bytes changes how the remaining template syntax relates to the attribute. The browser interprets the combined output, so an action that emits nothing can still affect structure through its surroundings.

This case reinforces the package documentation's structure-preservation requirement. Trusted template syntax should retain its intended role regardless of untrusted data. The relevant question is whether an attribute boundary remains an attribute boundary after execution, including when the inserted value has zero length.

The correction ships in the toolchain used to build the application

These fixes affect Go's standard library implementation. Selecting a patched compiler distribution for subsequent application builds is therefore part of adopting the correction. Merely changing template data does not replace the faulty implementation that produced the output.

The versioned documentation also describes typed strings such as HTML, JS and URL that can exempt content from ordinary escaping. Those types express a separate trust decision. A corrected contextual escaper does not make arbitrary untrusted content appropriate for a type that declares it safe. The documented model continues to depend on trusted template authors and honest use of those escape exemptions.

For an application using ordinary data values, the release restores intended behavior in the identified CSS, JavaScript and HTML cases. Each repair concerns the complete output seen by the browser. That is the level at which a template engine must preserve structure, including interactions between adjacent actions and the absence of inserted text.