Is JavaScript Client-Side Secure? What Are The Vulnerabilities?

Software Development has evolved dramatically over the last 10+ years. Prior to the development of Frontend JavaScript frameworks, multiple projects relied on the backend, including its security. With more advances on the client-side, the level of responsibility has increased equally on both ends. However, is the JavaScript Client-Side Secure?

In short, JavaScript client-side applications are not 100% safe. The main reason is that there is no full control of the client-side as it is executed in the browser. Those with advanced skills can have access to critical information on the frontend and expose vulnerabilities.

Although it is not possible to achieve 100% protection, some applications are more secure than others. The main reason is that the security is dependent on the developer’s expertise in security. Therefore, if the developer is experienced and constantly introducing best practices to make an application more secure on the client side, the likelihood of suffering from attacks will be reduced.

On the other hand, if developers lack the knowledge and skills to prevent vulnerabilities, the possibilities of having a hackable frontend system increase exponentially. It is important to understand how software development works and have a basic understanding of the risks involved not only on the client-side but also on the server-side.

What Is A JavaScript Vulnerability?

Regardless of whether it is JavaScript, Python, C#, Ruby on Rails, or any other programming language, a vulnerability is the state of an application being exposed to attacks that could lead to harmful consequences such as unauthorized access, stolen data, or complete deletion of data.

What Are Some JavaScript Client-Side Vulnerabilities Examples?

Some of the most common client side vulnerabilities are:

  • SQL or NoSQL Injection
  • Security Misconfiguration
  • Broken Access Control
  • Cross Site Scripting (XSS)
  • Cross Site Request Forgery (CSRF)
  • Using Third-Party Libraries and/or Components with Existing Vulnerabilities
  • Bad Deserialization Practices
  • Sensitive Data Exposure
  • XML External Entities (XXE) Injection

For an in depth explanation on any of these vulnerabilities, I recommend visiting this article.

How Do You Make the Client-Side Safer?

There are several techniques you can use to make your client-side more secure. One of the most popular is Obfuscation.

JavaScript Obfuscation

Obfuscation is the process of transforming your code which makes it hard for people to read and understand. For example, we have a simple JavaScript code below:

function buyFood() {
  console.log("Food purchased!");
}
buyFood();

If we decide to make changes on the code to make it virtually impossible to read, we could do something like this:

 var _0x458b=['538646gopomJ','25BqksCQ','Food\x20purchased!','1mUfMcU','2391QzfyJC','241qJuyFw','202607eXJeSc','5417sdkWwj','767678sNJrpT','824751UwpeHE','747317UIaClF'];var _0x9cfe=function(_0x1a0bc5,_0x3f02bc){_0x1a0bc5=_0x1a0bc5-0x111;var _0x458b51=_0x458b[_0x1a0bc5];return _0x458b51;};(function(_0x3a5071,_0x3e25e5){var _0x1c8a8b=_0x9cfe;while(!![]){try{var _0x1e67de=parseInt(_0x1c8a8b(0x117))+-parseInt(_0x1c8a8b(0x119))+-parseInt(_0x1c8a8b(0x116))*-parseInt(_0x1c8a8b(0x115))+-parseInt(_0x1c8a8b(0x118))*parseInt(_0x1c8a8b(0x112))+parseInt(_0x1c8a8b(0x111))+-parseInt(_0x1c8a8b(0x11a))*-parseInt(_0x1c8a8b(0x114))+-parseInt(_0x1c8a8b(0x11b));if(_0x1e67de===_0x3e25e5)break;else _0x3a5071['push'](_0x3a5071['shift']());}catch(_0x5b1b4b){_0x3a5071['push'](_0x3a5071['shift']());}}}(_0x458b,0x78127));function buyFood(){var _0x5333e2=_0x9cfe;console['log'](_0x5333e2(0x113));}buyFood();

However, putting in practice Obfuscation can be complex for developers to implement as it will slow down the development process due to the fact that it takes longer to write code that only machines can easily understand. Fortunately, there are tools available that will simplify this process such as this JavaScript Obfuscator Tool. Give it a try!

JavaScript Minification

Minification or to minify is the process of removing extra spaces, new lines, or any other unnecessary characters from the code source without impacting the coding process. This could also involve converting variable names and/or function names allowing to reduce the code size and making applications lighter as well as optimizing conditional statements and removing comments among others. Besides minifying JavaScript files, you can also reduce the size of HTML and CSS files.

Minification is a commonly established practice within the software development industry, and it happens when the prod or production version of an application is built allowing the codebase to be lighter. This allows the users to use fewer data resources at the moment of using the software, .i.e., web or mobile applications.

Besides reducing files’ sizes, minification also gives the client-side application an extra level of security. Let’s understand with an example. Do you remember our previous snippet of code where we defined the buyFood function? If we decide to minify this code, it will look like the following:

function b(){console.log("Food purchased!");}b();

If you notice, the buyFood function is now called b. Also, all the spaces and new lines have been removed. In this case, the piece of code we wrote is not complex and certainly you could have a good guess of what our code does. However, this is not usually the case of real-world projects as they tend to have more code logic and complexity. If an attacker decides to “read” through the logic of a minified version of code, it will take him a lot of time before he can understand what the code does.

There are free tools available to minify your code such as Minify or JavaScript Minifier if you are looking to manually reduce your code size. To avoid manual work, you can also use popular third-party libraries such as uglify, terser, or minify to automate this process.

Secure Frontend Can Still Be Vulnerable To Attacks

Even if you did an excellent job at obfuscating and minifying your client-side code base, your front end is still vulnerable to attacks. Since you cannot control what the client does in the browser, hackers can manipulate files at their will.

Is The Server-Side More Secure Than The Client-Side?

Even though you can attempt to make the client-side as secure as possible, the server-side is safer. Having said that, this doesn’t mean you can avoid implementing best practices to prevent your application from being exploited on the server-side. Nevertheless, the server-side allows developers to gain control of, .i.e. their API (Application Programming Interface).

In fact, stricter security measurements must be taken into account prior to deploying and exposing the server-side as sensitive data or logic manipulating the data resides there and any failure to protect the server can lead to catastrophic outcomes such as data thief or complete deletion of the database.

Should I Worry About Making The Client-Side Safer If The Server-Side is Already Secure?

In the case a system is dependent on both, a backend and a frontend, or a server-side and a client-side, it is important to still give the same level of security to the two. Failure to do so can represent a huge impact on a business. One common scenario where many Junior developers fail is to properly ensure validation of the data. For example, our application has a login page, which contains a form with two input boxes, one for the username and the other for the password.

It has become standard to provide error messages on any of this information prior to submitting the login form, or in other words, making a request to an API to authenticate the user. But what do you think would happen if the password input box displays in plain-text the password of the user as he is typing, instead of hiding the password which happens whenever the attribute type is set as password? Certainly, anyone walking nearby could see the user’s password representing in a user-theft vulnerability.

But that is one case. Can you think of the scenario where someone else has hacked the user’s computer and the hacker is recording everything the user does on the computer? Due to a failure in the development on the client-side, we allowed hackers to get more sensitive information from the user.

Now, let’s think of the scenario where the client-side is secure, but the server-side lacks security. For example, our API has a GET endpoint called /car and it receives an id query parameter to get a specific car record. The id‘s data type is a number. Unfortunately, the API doesn’t validate the id parameter and also doesn’t parameterize its value, but instead, it directly concatenates the id value in the following SQL script. For the purpose of this example, we are going to say that the id value is 1.

SELECT * FROM Cars
WHERE CAR_ID = 	1 

Here, it doesn’t seem to be a major risk. However, someone with basic SQL knowledge will know this is a case of SQL injection. Let’s change the value of id to 1 or CAR_ID != 1, making our SQL script look like the following:

SELECT * FROM Cars
WHERE CAR_ID = 	1 or CAR_ID != 1

Now, our query will return all of the car records, and if the user is not supposed to have access to cars he didn’t create then a hacker will now have full access to the list of cars available in the database.

Therefore, making the assumption that making one side (the server-side or the client-side) more secure than the other is not a good justification to make the other end less secure. As software development security practices evolve, hacking practices do the same. There are smart people out there with malicious intentions who always come up with innovative ways to break into a system.