Skip to content

Express State v1.0.1 — XSS Protection

Compare
Choose a tag to compare
@ericf ericf released this 05 Nov 05:43
· 78 commits to master since this release

This patch release adds XSS protection, everyone using Express State v1.0.0 should upgrade to v1.0.1.

The focus of this patch release was to add a basic level of XSS protection to prevent string values exposed through Express State's expose() method from being able to close and re-open <script> elements.

Attack Vector

The main way Express State is used is to embed the JavaScript it produces during serialization inside of an HTML <script> element; e.g., using Express State with Handlebars templates:

<script>{{{state}}}</script>

Triple-mustaches are used so that Handlebars does not HTML-escape the JavaScript code that Express State's serialization process creates, if this code was HTML-escaped it would be invalid JavaScript and fail to run in the browser.

This left open a possible XSS attack vector where exposed string values could close and re-open a <script> element and therefore gain an execution context. The following shows how this could be done in versions of Express State prior to v1.0.1:

res.expose('";</script><script>alert("hey!");</script>', 'foo');

It's not likely that a developer would purposely want to expose the "</script><script>" character sequence, but this attack vector could have been exploited by exposing untrusted user input which was not first HTML-escaped.

Note: We are not aware of any developers using Express State who've been exploited this way, we are taking a proactive approach to adding a basic level of XSS protected to Express State in the cases where untrusted user input is not properly HTML-escaped before it is exposed.

Change that Added XSS Protection

String values exposed via Express State's expose() method will now have their unsafe HTML characters: '<', '>', and '/' encoded to their Unicode values during the serialization process. The encoded characters will === the non-encoded characters so there's no worry of this messing up application code.

This provides a basic level of protection against XSS attacks by not allowing the "</script><script>" character sequence within an exposed string value to be interpreted and cause the browser prematurely close a script element and reopen a new one.

Even with this basic XSS protection, it's still important to always escape untrusted user input.

Untrusted User Input

Always escape untrusted user input to protected against XSS attacks!

Express State provides a mechanism to expose configuration and state data as first-party JavaScript, which means any untrusted user input should be properly escaped before it's passed to Express State's expose() method. See the OWASP HTML escaping recommendations.


View 1.0.1 Changelog