You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.
CDATA sections are only valid in foreign content (i.e. <math> or <svg>), and have various different meanings within that content (love to mix XML and HTML).
In the first fragment the first </script> tag terminates the script section, but in the second fragment, since the first </script> tag is inside of a CDATA section, it is treated as plaintext and doesn't terminate the script block.
This can cause some strange interactions, since there are ways to structure something that looks like an end tag, but is valid JS (i.e. depending on the context, </script/> may be interpreted as a regex literal, while being interpreted by an HTML parser as an ending tag).
In an extremely cursed template, this can cause html/template to improperly derive the correct context for contextual auto-escaping, leading to (extremely unlikely) XSS.
The following template illustrates this; since the parser does not believe the action is within the JS context (since it thinks </script/> terminated the script block), it will allow JS to be inserted unescaped.
(For those interested, this works because the JS interpreter treats this as an inequality 1 < /regex lit/ > "string" which is obviously majorly broken, but will be happily executed. You can then use the JS template literal syntax to inject code using string interpolation syntax, i.e. ${alert(1)}.)
This is obviously an incredibly contrived example, and is unlikely to ever actually impact any real world implementations, but should probably still be fixed. How to fix it is not immediately obvious, other than increasing the complexity of the parser to understand (a) foreign content sections and (b) CDATA (but only for the purposes of HTML parsing semantics).
golang.org/x/net/html handles this correctly, since it applies the proper CDATA rules (and it doesn't need to understand JS semantics).
CDATA sections are only valid in foreign content (i.e. <math> or <svg>), and have various different meanings within that content (love to mix XML and HTML).
Per the HMTL specification (https://html.spec.whatwg.org/#cdata-sections and https://html.spec.whatwg.org/#cdata-section-state) the contents of CDATA sections are considered plaintext for the purposes of parsing, as such the two following fragments are treated differently:
In the first fragment the first
</script>
tag terminates the script section, but in the second fragment, since the first</script>
tag is inside of a CDATA section, it is treated as plaintext and doesn't terminate the script block.This can cause some strange interactions, since there are ways to structure something that looks like an end tag, but is valid JS (i.e. depending on the context,
</script/>
may be interpreted as a regex literal, while being interpreted by an HTML parser as an ending tag).In an extremely cursed template, this can cause html/template to improperly derive the correct context for contextual auto-escaping, leading to (extremely unlikely) XSS.
The following template illustrates this; since the parser does not believe the action is within the JS context (since it thinks
</script/>
terminated the script block), it will allow JS to be inserted unescaped.(For those interested, this works because the JS interpreter treats this as an inequality
1 < /regex lit/ > "string"
which is obviously majorly broken, but will be happily executed. You can then use the JS template literal syntax to inject code using string interpolation syntax, i.e.${alert(1)}
.)This is obviously an incredibly contrived example, and is unlikely to ever actually impact any real world implementations, but should probably still be fixed. How to fix it is not immediately obvious, other than increasing the complexity of the parser to understand (a) foreign content sections and (b) CDATA (but only for the purposes of HTML parsing semantics).
golang.org/x/net/html handles this correctly, since it applies the proper CDATA rules (and it doesn't need to understand JS semantics).
Thanks to @arkark for reporting this issue.
cc @golang/security @nigeltao
The text was updated successfully, but these errors were encountered: