Technical information leak - Print Functions - javascript

Technical information leak - Print Functions - javascript

Need

Protection of sensitive information by removing or disabling console logging in production environment

Context

  • Usage of JavaScript for building web applications
  • Usage of Express.js for handling HTTP requests and responses
  • Usage of console functions for debugging purposes

Description

Non compliant code

        const express = require('express');
const app = express();

app.get('/', (req, res) => {
    try {
        // Some code that might throw an error
    } catch (err) {
        console.error(err);  // This is the vulnerability!
    }
});

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

In the provided code snippet, we have an Express.js application that defines a simple route using the app.get method. Inside the route handler, a try-catch block is used to handle potential errors.

The vulnerability lies in the catch block, where we use console.error(err). This method prints the error details, including stack traces, to the console. While useful during development for debugging, this can lead to sensitive information leakage in a production environment.

Attackers may deliberately trigger errors to extract information about the application's internal structure, such as file paths, dependencies, and API details. This can help them craft targeted attacks.

To fix this vulnerability, it is recommended to use a logging framework like winston or pino to store error logs securely. Logs should be properly secured, monitored, and should not contain sensitive data.

Steps

  • Remove or comment out direct console logging (e.g., console.log, console.error) in production code.
  • Use a structured logging framework such as `winston` or `pino` to securely handle logs.
  • Ensure that logged error messages do not expose sensitive details.
  • Store logs securely and restrict access to authorized personnel.
  • Regularly review logs for security monitoring and anomaly detection.

Compliant code

        const express = require('express');
const winston = require('winston');

const app = express();
const logger = winston.createLogger({
    level: 'error',
    format: winston.format.json(),
    transports: [
        new winston.transports.File({ filename: 'error.log' })
    ]
});

app.get('/', (req, res) => {
    try {
        // Some code that might throw an error
    } catch (err) {
        logger.error('An error occurred', { error: err.message });
    }
});

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

The original code was vulnerable due to the use of console.error(err), which could potentially expose sensitive information about the application's internals. This is especially risky in a production environment.

The revised code mitigates this risk by replacing console.error(err) with a structured logging approach using the winston library, a widely used logging framework for Node.js applications.

A logger instance is created with different logging levels, allowing for better control over log messages. Instead of directly logging to the console, errors are logged securely with logger.error(). This ensures that sensitive information is not exposed in production logs.

By using a logging framework, logs can be directed to secure storage, access-controlled, and monitored for unusual activity, reducing the risk of information leaks.

References