Insecure or unset HTTP headers - CORS - TypeScript

Insecure or unset HTTP headers - CORS - TypeScript

Need

Enforce secure and specific HTTP headers for Cross-Origin Resource Sharing (CORS)

Context

  • Usage of TypeScript for type-checking and compiling JavaScript code
  • Usage of Express for building web applications and APIs

Description

Non compliant code

        import express from 'express';

const app = express();

app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Headers', '*');
  res.setHeader('Access-Control-Allow-Methods', '*');
  next();
});

app.get('/api/data', (req, res) => {
  res.json({ message: 'This is sensitive data!' });
});

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

The vulnerability in this code is related to insecure or unset HTTP headers, specifically the Cross-Origin Resource Sharing (CORS) policy.

In the code, the Access-Control-Allow-Origin header is set to *, which means that any domain is allowed to access the resources served by this application. This wildcard configuration can be exploited by attackers to include resources from untrusted origins, potentially leading to cross-site scripting (XSS) attacks or data leakage.

Additionally, the Access-Control-Allow-Headers and Access-Control-Allow-Methods headers are also set to *, allowing any headers and methods to be used in cross-origin requests. This can further increase the attack surface and potential security risks.

To address this vulnerability, it is recommended to remove the wildcard (*) and explicitly define the trusted origins for accessing the application resources. This ensures that only specified domains are allowed to make cross-origin requests.

Steps

  • Remove the wildcard (*) from the 'Access-Control-Allow-Origin' header and define explicitly the trusted origins for sharing resources.
  • Remove the wildcard (*) from the 'Access-Control-Allow-Headers' header and define explicitly the allowed headers.
  • Remove the wildcard (*) from the 'Access-Control-Allow-Methods' header and define explicitly the allowed HTTP methods.
  • Update the code to handle preflight requests if necessary.
  • Test the updated code to ensure proper functioning.

Compliant code

        import express from 'express';

const app = express();

const allowedOrigins = ['https://trusted-domain1.com', 'https://trusted-domain2.com'];

app.use((req, res, next) => {
  const origin = req.headers.origin;
  if (allowedOrigins.includes(origin)) {
    res.setHeader('Access-Control-Allow-Origin', origin);
  }
  res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  next();
});

app.get('/api/data', (req, res) => {
  res.json({ message: 'This is sensitive data!' });
});

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

The fixed code addresses the vulnerability by implementing proper Cross-Origin Resource Sharing (CORS) policies.

First, the code imports the Express framework and creates an instance of the application.

Next, an array called allowedOrigins is defined, which contains the trusted domains that are allowed to access the application's resources.

The code then sets up a middleware function using app.use() that will be executed for every incoming request. This middleware function checks the origin header of the request to determine the domain from which the request originated.

If the origin is found in the allowedOrigins array, the code sets the Access-Control-Allow-Origin header in the response to the value of the origin header. This allows requests from the trusted domains to access the resources.

Additionally, the code sets the Access-Control-Allow-Headers header to specify the allowed request headers, and the Access-Control-Allow-Methods header to specify the allowed HTTP methods.

Finally, the code defines a route for the /api/data endpoint, which simply responds with a JSON message containing sensitive data.

The application listens on port 3000, and a message is logged to the console indicating that the server is running.

Overall, the fixed code explicitly defines the trusted origins for sharing resources and removes the wildcard (*) that could potentially allow resources to be accessed from untrusted origins.

References