Most Common Security Vulnerabilities Using JavaScript

Most Common Security Vulnerabilities Using JavaScript

JavaScript is undoubtedly the most popular programming language for web development. A survey by Stack Overflow shows that over 67% of professional developers use JavaScript. Additionally, it is used by more than 95% of websites on the web. 

From a security perspective, JavaScript is fourth on the list of the most vulnerable languages – only behind Java, PHP, and C. For this reason, developers must remain proactive and defensive in securing their JavaScript applications to keep the web safe.

This post dives into common JavaScript vulnerabilities, the risks they pose, and how developers can address these vulnerabilities to keep their web applications secure. 

Cross-Site Scripting

According to OWASP, cross-site scripting (XSS) is one of the most widespread security risks in web applications. It occurs when an attacker injects malicious code into the client-side of an application. This normally happens when an application accepts untrusted (or user-supplied) data on a web page without escaping or validating it properly.

A successful XSS attack occurs when the browser executes the malicious scripts from in a manner determined by the threat actor. Generally, XSS attacks will require some form of interaction from the victim, either through social engineering or request to visit a particular page. 

If an attacker exploits XSS vulnerabilities, they could perform malicious actions like account tampering, data theft, remote control, or even malware distribution.

To prevent XSS attacks, developers should separate untrusted data or user input from the active browser content. In JavaScript, you can achieve this by:

  • Validating and sanitizing input from users to ensure it only contains acceptable characters that cannot be used to launch XSS attacks.
  • Using safe methods such as innerText for manipulating the DOM. Unlike innerHTML, this method escapes dangerous content, thereby preventing DOM-based XSS.
  • Using frameworks that automatically escape XSS vulnerabilities by design. For instance, Node JS has the encodeURI and encodeURIComponent global functions that help prevent XSS attacks. You should also consider using advanced packages like the xss-filters .

The following code snippet shows how to use XSS filters from the npm package in express applications.

const express = require('express');
const xssFilters = require('xss-filters');
const util = require('util');  
const app = express();  
app.get('/', (req, res) => {   const unsafeFirstname = req.query.firstname;   
const safeFirstname = xssFilters.inHTMLData(unsafeFirstname);    
res.send(util.format('<h1>Tom%s</h1>', safeFirstname)); });  

app.listen(3000);

SQL Injection

SQL databases are vulnerable to injection attacks where query parameters are exploited to execute arbitrary instructions. 

Below is an express framework router that is vulnerable to an SQL injection attack:

const express = require('express');
const db = require('./db');

const router = express.Router();

router.get('/email', (req, res) => {
  db.query('SELECT email FROM users WHERE id = ' + req.query.id);
    .then((record) => {
      // logical flow
      res.send(record[0]);
    })
});

In the example above, the application gets user IDs from URLs and retrieves the corresponding email address by querying the database. Two things are wrong in the code snippet.

First, the database query is built using a string concatenation. The second issue is that the user input is concatenated to the query instead of being handled as untrusted data.

An attacker might craft a query string id parameter in such a way that it retrieves all tables or writes into the database. For instance, when the attacker supplies these string parameters:

1 UNION SELECT group_concat(table_name) FROM information_schema.tables WHERE table_name = database()

This would result to a query like this one:

When this query is executed successfully, it would pull the list of all tables in the databases. An attacker can then retrieve any information they want.

SELECT email FROM users WHERE id = 1 UNION SELECT group_concat(table_name) FROM information_schema.tables WHERE table_name = database()

To mitigate SQL injections, developers should always perform proper input validation. When input from the user fails the validation checks, the SQL query is not executed.

Another way of preventing SQL injection is using parameterized queries or prepared statements instead of concatenations. Parameterized queries are used to abstract the SQL syntax from the input parameters.

In the example below, parameterized queries are used to prevent potential SQL injection attacks.

const express = require('express');
const db = require('./db');

const router = express.Router();

router.get('/email', (req, res) => {
  db.query('SELECT email FROM users WHERE id = $1', req.query.id);
    .then((record) => {
      // logical flow continues
      res.send(record[0]);
    })
});

Sensitive cookie exposure

The client-side script on every browser can access all the content returned by an application to the server. This includes cookies that often contain sensitive data such as session IDs. 

Exposing session identifiers, whether in URLs, error messages, or logs is a bad practice that opens up an application to security issues like cross-site request forgery(CSRF), session hijacking and session fixation.

To prevent this, developers must consistently use HTTPS and implement HTTP-Only cookies. The HTTP-Only attribute in cookies tells the browser to prevent cookie access through the DOM. By doing this, client-side script attacks are prevented from accessing sensitive data stored in cookies.

Another way of securing user sessions is opting by per-requests as opposed to using per-session identifiers. Any time the client requests privileged access permissions, terminate the session and re-authenticate them before granting access.

Here is an example cookie that uses Express – Node.js and stores session data on the SQLite database using the connect-sqlite3 package. Notice how we use HTTP only secure cookies.

const express = require('express');
const session = require('express-session');
const SQLiteStore = require('connect-sqlite3')(session);
const util = require('util');

// express-session configuration
const sessionMiddleware = session({
    store: new SQLiteStore({
      table: 'sessions',
      db: 'sessions.db',
      dir: __dirname
    }),
    secret: 'H@rden y0ur c00k1e5',
     saveUninitialized: false,
      resave: false,
      rolling: true,
      name: 'ssid',
      domain: 'localhost',
      httpOnly: true,
      secure: true,
      sameSite: 'strict'
});

const app = express();

// tell Express to use the 'sessionMiddleware'
app.use(sessionMiddleware);

app.get('/', (req, res) => {
  // trigger the 'Set-Cookie' (otherwise no cookie would be set)
  req.session.counter = (req.session.counter || 0) + 1;
 
  res.send(util.format('You have ve visited this page %dtimes',
    req.session.conter));
});

app.listen(4000, () => {
  console.log('Application listening on port 4000');
});

Components with known vulnerabilities

There are tons of security risks associated with the use of vulnerable application components. For instance, vulnerabilities in some libraries or other elements such as browser plugin code are a security loophole in your applications. 

To ensure the components you’re using do not compromise your application’s security, always keep up with the current versions of all. Do not rely on unpatched components for building or integrating into your web application.

Another security concern is re-using JavaScript code from open source directories such as GitHub. When you copy code from a random user and re-use it in your application without auditing it, you might introduce security issues in your application.

Instead, exercise caution and inspect every component of your application. You do not want to use any broken code that comes your way, or even worse, code with intentionally malicious scripts.

Putting it all together

Adopting good coding practices can secure applications against common JavaScript vulnerabilities on both the client-side and server-side. When using JavaScript, always follow the following key guidelines for enhanced security:

  • Never trust user input
  • Use proper encoding/escaping
  • Sanitize user input
  • Define a content security policy
  • Set secure cookies
  • Secure API keys on the client-side
  • Encrypt data transmitted between the client and the server
  • Use secure components and APIs for development
  • Use updated libraries and frameworks
  • Conduct regular scans on your codebase


Following these best coding practices is usually the first step for securing your web applications.

要查看或添加评论,请登录

Aleksandar Cvjetan的更多文章

  • How deep learning fakes videos (Deepfake) and how to detect it?

    How deep learning fakes videos (Deepfake) and how to detect it?

    Fabrication of celebrity porn pics is nothing new. However, in late 2017, a user on Reddit named Deepfakes started…

  • The Official GitHub CLI 1.0 is here

    The Official GitHub CLI 1.0 is here

    GitHub, the world’s most popular Git hosting provider has existed without an official CLI tool for years now. It’s…

  • The Big O Notation - An Introduction

    The Big O Notation - An Introduction

    A long time ago, before the emergence of 10x engineers, software engineers sought ways to solve real-world problems…

  • Everything new coming in ES2021

    Everything new coming in ES2021

    Every year since 2015, JavaScript has been receiving constant yearly updates to its specification with new interesting…

  • GraphQL vs REST vs gRPC

    GraphQL vs REST vs gRPC

    If you’ve read an article or even some brief description of GraphQL, it probably included a line about what it does…

  • The TypeScript 4.0 Beta Is Here

    The TypeScript 4.0 Beta Is Here

    TypeScript 4.0 beta version was released on June 25, 2020.

    1 条评论
  • Watch & Compile your Sass with npm

    Watch & Compile your Sass with npm

    I build a lot of websites and simple prototypes using Node.js and Sass.

  • Deno is new Node?

    Deno is new Node?

    About 3 months ago, Ryan Dahl (the inventor of Node.js) gave a talk in JSConf called “10 Things I Regret About Node.

    4 条评论
  • Bootstrap 5 — Release date, Important updates and Latest news

    Bootstrap 5 — Release date, Important updates and Latest news

    The most popular Bootstrap source is coming up with latest version Bootstrap 5??. In this article, we will share…

社区洞察

其他会员也浏览了