Search code examples
htmlattributesescapinghandlebars.jsesapi

Is handlebars' default escaping safe for use in HTML attributes


I'm doing some contract work on a project that has a variety of HTML escaping methods. Some properties are escaped in the back-end and rendered as raw strings using triple handlebars {{{escaped-in-backend}}}, others are passed from the back-end raw and escaped using double handlebars {{unsafe}}.

The JS back-end encoding is done using the (legacy?) ESAPI library, and uses a mixture of encodeForHtml() and encodeForHtmlAttribute(). I couldn't find a whole lot of info on this, but this post suggests that the attribute encoding also escapes spaces as   in order to be considered safe from XSS attacks. This may be what prompted the previous developer to do the escaping in the back-end.

Back-end escaping is nasty and I'd like to get rid of it and rely on handlebars. I haven't done F/E work in years so I just wanted to double-check that handlebars' escaping strategy is safe for attribute values, for example: <input type="text" value="{{unsafe-value}}"/>.

I'm leaning towards 'yes', as handlebars is pretty widespread, and this would be a pretty glaring security hole, but I couldn't find any explicit documentation saying as such.


Solution

  • You have a programmer reverse-engineering problem. You're reversing decisions made by prior programmers!

    The issue you're up against, is that escaping rules in HTML attributes are different than escaping in-between tags, so we separate those escaping functions because they're not 1:1. I.E.

    <textarea>{{HTMLEscapingIsDoneHere}}</textarea>
    
    <span background="[HTMLAttributeEscapingIsHere]"> ...
    

    HTML escaping covers many more characters than HTML Attribute Encoding. The danger is that you could be escaping quite a bit more than you'd intend, thus breaking some other feature like css or jquery selectors that might be trying to key in on those attribute values and will now fail because you've escaped too much and those functions were expecting plaintext and not HTML Attributes. Handlebars itself might have some functionality that keys on attribute values that will break if you HTML-Escape them. [I don't know, I've never used it..]

    If you pay attention to what gets escaped up front and what gets escaped on the back, and the prior developers were consistent in that the only things getting escaped were your HTML Attributes... then I'd bet $50 that they tried escaping everything as full HTML, broke something, and then came up with backend escaping as the easiest solution at the time. If they were inconsistent, well, all bets are off.

    In your case, maybe experiment escaping everything as HTML to see if you break anything, but especially if it works you'll want to clearly document your approach that you could create future incompatibilities with other dynamic frameworks. If you can't tell, I've run into this before. It's the business's job to accept or reject that risk.

    My first suggestion, is that if you're working with handlebars IN JSPs, then just import the ESAPI taglibs and utilize the encoding functions there. Ugly? Sure. You're using more than one FE framework.

    My second suggestion since you're probably married to handlebars is to wrap the esapi encoding functions you want to use here and introduce them into handlebars. For example, in JSP you have taglibs that allow you to either use ESAPI's or write custom wrappers. Since I know ESAPI was never coded with handlebars in mind, I'd write wrapper functions and explicitly escape HTML using handlebars, and HTML attributes with your inserted handlebars functions. If handlebars doesn't have a capability to allow you to insert your own escaping functions, then I'm afraid backend escaping is the next best alternative. The prior developers saw value in separating these escaping functions, but were unable to do so in FE code.

    As to the broader question, "Is it safe to escape attributes as HTML instead of HTML Attributes" it's one of those "yes, but..." answers where I've already gone over the pitfalls. Most of those pitfalls go away when using a Single Page Web Application framework but that's because you've normalized all client/server communication to Javascript. That's also off-topic, but an arrow you should have in your contractor's quiver.