Skip to main content

Insecure or unset HTTP headers - X-XSS Protection

Need

Implementation of secure and properly configured HTTP headers

Context

  • Requirement: Node.js v14.0.0 or higher
  • Usage of Express for building web applications and APIs

Description

Non compliant code

import express from 'express';

const app = express();

app.get('/', (req, res) => {
const userInput = req.query.input;
res.header('X-XSS-Protection', '0');
res.send(`<h1>${userInput}</h1>`);
});

app.listen(3000, () => {
console.log('Server is running on port 3000');
});

In the given TypeScript code, the vulnerability lies in the insecure or unset HTTP header, specifically the X-XSS-Protection header. The X-XSS-Protection header is set to '0' using the res.header() function, which effectively disables the XSS protection filter.

This vulnerability can lead to stored XSS (Cross-Site Scripting) attacks. In this code, the user input is directly rendered on the page without any sanitization or validation. This means that an attacker can inject malicious scripts or code as the userInput and it will be executed by the browser when the page is loaded.

By disabling the XSS protection filter, the application becomes more susceptible to XSS attacks. The X-XSS-Protection header is considered deprecated, and it is recommended to use more modern security measures, such as Content Security Policy (CSP) headers, to mitigate XSS vulnerabilities.

To fix this vulnerability, the X-XSS-Protection header should be disabled or removed from the server's response headers. Instead, the application should implement a Content Security Policy (CSP) header to define security policies and prevent XSS attacks.

Steps

  • Remove the line 'res.header('X-XSS-Protection', '0');' from the code.
  • Install the 'helmet' package by running 'npm install helmet'.
  • Import the 'helmet' package in the code: 'import helmet from 'helmet';'.
  • Add the following line of code after creating the 'app' instance: 'app.use(helmet());'.
  • Update the response code to use a template engine or sanitize the 'userInput' variable before sending it to the client.

Compliant code

import express from 'express';
import helmet from 'helmet';

const app = express();

app.use(helmet());

app.get('/', (req, res) => {
const userInput = req.query.input;
// TODO: Sanitize userInput or use a template engine to render the response
res.send(`<h1>${userInput}</h1>`);
});

app.listen(3000, () => {
console.log('Server is running on port 3000');
});

The fixed code addresses the vulnerability by implementing proper security measures using the helmet package in Express.

First, the code imports the express and helmet packages. express is a popular web application framework for Node.js, and helmet is a middleware that helps secure Express applications by setting various HTTP headers.

Next, an instance of the Express application is created using express().

The helmet() middleware is then applied to the application using app.use(helmet()). This middleware automatically sets various HTTP headers to enhance security, including the necessary headers to prevent XSS attacks.

The code defines a single route for the root path ("/") using app.get(). When a GET request is made to the root path, the code retrieves the input query parameter from the request using req.query.input.

Before rendering the response, the code should sanitize the userInput variable to prevent any potential XSS attacks. Alternatively, a template engine can be used to render the response securely.

Finally, the application listens on port 3000 using app.listen(), and a message is logged to the console indicating that the server is running.

By using the helmet middleware, the code ensures that the necessary security headers, including the X-XSS-Protection header, are set correctly to prevent stored XSS vulnerabilities.

References