Is HTMLEditFormat enough?

This post is more than 2 years old.

Patrick asks:

You schooled me on using vars in my cfc to help ratchet up the security. If I used the following code in my cfc that processes my contact form, do you feel like the data would be cleansed and relatively benign? I'm also using cfparams in the page with the form and validating it with jQuery and/or CF server side code (for non Java visitors) as well.

<cfargument name="email" type="string" required="yes">
<cfargument name="fullname" type="string" required="yes">

<cfset var elements = structNew()>
<cfset elements.email = htmlEditFormat(trim(arguments.email))>
<cfset elements.fullname = htmlEditFormat(trim(arguments.fullname))>
Awesome question - and to be honest - my initial response going to be sure - that's good enough. But I knew there was a bit more to it. I decided to hit up Pete Freitag. As far as I'm concerned Pete is the leading expert in the area of ColdFusion and security. He had a great response to this that I think makes it very clear that htmlEditFormat may not be enough.
The answer is, it depends. It depends on where the variables are outputted. There are 5 different places the variable could be output on a web page, and each has different encoding methods that are required.

HTML Body: <p>#elements.email#</p>
HTML Attribute <a href="mailto:#elements.email#">...</a>
JavaScript: <a onclick="doIt(#elements.email#);">.../a> or <script>var email = #elements.email#</script>
CSS: <div style="color:#url.color#" />
URL: <a href="page.cfm?email=#elements.email#">...</a>


See Slides 56-61 in my presentation Writing Secure CFML: http://www.petefreitag.com/item/759.cfm

So HTMLEditFormat is only considered safe in the HTML Body, in other contexts such as the HTML Attribute it may allow for XSS (depending on the quotes of the attribute, and how strict the browser is about quotes), keep in mind the HTMLEditFormat doesn't escape single quotes so if you have <div id='#HTMLEditFormat(url.id)#'> you can simply pass in ?id=1'+onmouseover='badStuff();'

The ESAPI is a really good way to encode variables to handle all the contexts (mentioned in my slides).

Excellent response, Pete. As I said, I had an inkling to what the issue was but he spelled it out perfectly. I think most of us consider the HTML Body context, but not the other ones. Handling this then requires a very firm understanding of how your data is actually used.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Ed posted on 8/26/2010 at 11:57 PM

Thanks, I am going to have to dig into this more. My client just got the report back from their annual penitration test, and while we thought we had XSS issues pretty well in hand, we got nailed on a number. Thankfully you have to be an authenticated user before you get to do anything dangerious and our login secrity came back great. But still need to tighten stuff up.

Comment 2 by JC posted on 8/27/2010 at 12:23 AM

function globalAntiXSS() {
formKeys = structkeylist(form);
for(i = 1; i lte listlen(formKeys); i = i + 1)
{
form[listgetat(formKeys,i)] = htmleditformat(structfind(form,listgetat(formKeys,i)));
form[listgetat(formKeys,i)] = replace(structfind(form,listgetat(formKeys,i)),"'","&##39;",'ALL');

}

urlKeys = structkeylist(url);
for(i = 1; i lte listlen(urlKeys); i = i + 1)
{
url[listgetat(urlKeys,i)] = replace(replace(structfind(url,listgetat(urlKeys,i)),'<','&lt;','ALL'),'>','&gt;','ALL');
}

Comment 3 by JC posted on 8/27/2010 at 12:25 AM

The addition of single quotes seems to make it pretty much foolproof.

Without those, you can run into problems when you do something like a form submission preview page with hidden inputs.

Comment 4 by Gordon Frobenius posted on 8/14/2015 at 3:38 PM

Want to hear something crazy? I just verified that VERACODE still only checks for HTMLCodeFormat(), HTMLEditFormat(), URLEncodedFormat(). They should be embarrassed. We are forced by a third party to use VERACODE and our application is MASSIVE. So we literally have to sift through tens of thousands of false positives every time we do a scan. They
do not recognize custom protection functions even if those functions follow OWASP's recommendations. They do not recognize ESAPI or the newer built-in CF functions based off of ESAPI which take into the other contexts like JavaScript and attribute. It is old news that HTMLEditFormat() isn't sufficient, VERACODE themselves even say so in their own presentation! (slide 24) https://www.owasp.org/image...