Not how it works: on JS-based “form security”

JavaScript is indisputably the world's most popular language, if you go by the lines of code generated each day.

Pretty sure it's the world leader in completely useless lines of code, too.

Tooling around a Community user's site the other day (I fixed their Forms 2.0 issue, so allow me a rant!) I saw this:


“Checks form fields for security risks and eliminates them”! I actually L'ed-O-L. The comment might as well say /* solves the Israeli–Palestinian conflict */ or /* ends sitcom reboots */!

Maybe the person who wrote that comment laughed, too. But clearly someone was meant to take it seriously, probably their boss, and that's bad. Because even if you know how ridiculous something is, that won't stop you from getting thrown under the bus when it proves its ridiculousness.

Or could the developer have been serious? Unfortunately, yes. I often think this is common knowledge, but there are new developers born every day who haven't heard it: You cannot use code in the browser to stop people from submitting whatever they want to your server. Malicious people will just skip your JavaScript rules. More to the point, they don't use browsers.

Hackers/spammers use command-line tools[1] (like cURL or wget) or they use one of the HTTP libraries available for any programming language. Their goal is to talk directly to your server. While they'll probably use a browser at the beginning to suss out your form fields, after that, the browser is closed for good.

So when we talk about form validation, we mean encouraging honest people to enter properly formatted & complete information. We're not — and I say this as someone who built a pretty cool email verification tool that integrates with Marketo forms — stopping hackers from sending unwanted data.

JavaScript/HTML-based validation works if people are either:

  1. basically honest (trying to sneak in fake or partial info at first, but they'll back off and enter good info if you respond gently but firmly); or
  2. dishonest, but completely technically unskilled, so they just close the tab if they can't fool the form

On the other hand, if they're malicious and have a middling amount of technical skillz, say bye-bye to your validation rules. (Even a reCAPTCHA, while powerful and recommended, can't stop a targeted, one-off attack on your forms; reCAPTCHA protects against bots, not real people with grudges.)

This is not a Marketo-specific thing. It's true of all forms, whether they use true HTML <form> inputs (like Marketo does, which I think is great), custom form-lookalike things using <div>s and <svg>s and whatever, or Flash, Java, or Silverlight forms from the old days. Any data that can be sent with a browser can also be sent without a browser.

So it should be clear now that no JavaScript can “check form fields for security risks and eliminate them.” At best, a JS solution can discourage non-technical folks from sending unwanted data.

It gets worse

But does the code above even stop non-technical people from smuggling data? Nope!

See, the problem the code claims to solve is link spam, in particular auto-responder-based link spam.

Link spam is when somebody stuffs clickable links into a form post in hopes the links will then be output as-is for others to click, for example in the comments on a blog or news site.

The auto-responder variant is even more crafty, the objective being to forge a form post using a victim's email address and then have the clickable link sent to that other person as part of a “Thanks for your inquiry” email.

The JS above just looks for the string “http://” or “https://” in all form fields[2] and strips it out if found.

But as we learned before even a faintly URL-like dotted.sequence.of.words (without http://!) can be clickable in Gmail.

So the code above doesn't even protect you against an attacker who, just for fun, decides to go through JS validation. It's a failure on all counts, falling into the unfortunate category of code that merely exists: it does nothing at all except provide false assurance, which could cost someone their job.


[1] Remember, the fact that your site doesn't work in the “primitive” IE 8-10 doesn't mean that seemingly primitive tools can't post to the forms server. cURL may be a command-line app that can't draw your fancy image slider, but it doesn't care about that, it cares about sending data over the network using HTTP, just like your browser does when it finally puts a form post on the wire.
[2] And does that task with comical inefficiency, but you probably expected that!