See for yourself – run a scan on your code right now


Error messages in web development can be likened to that friend who always spills the beans at the most inopportune times. They’re well-intentioned, aiming to help developers debug and users understand issues, but they can sometimes be too forthcoming. In the landscape of web applications, such transparency can be a grave security concern. As we navigate through this article, we’ll delve deeper into the nuances of error handling, emphasizing the importance of safeguarding the confidential aspects of our web applications.

The Problem: Information Leakage

Information leakage is not just about the accidental exposure of data; it’s about the unintended revelation of potentially critical details that can compromise the security of your application. 

These seemingly innocuous details can be a treasure trove for malicious actors, whether it’s system configurations, database structures, or user-specific data. 

Think of it as leaving your personal journal, filled with your deepest secrets, open and unattended in a bustling café. The risk isn’t just about someone reading it; it’s about potentially misusing that information.


The Basics: Understanding Error Messages

Error messages are essential for debugging during development. However, they can reveal too much information when exposed to end-users. For example, a database error might disclose table names, or a stack trace could reveal your application’s internal workings.

Code Snippet: Basic Error Handling in JavaScript

try {
  // Some code that might throw an error
  throw new Error(“This is a custom error message.”);
} catch (error) {
  console.error(`Caught an error: ${error.message}`);

In this JavaScript snippet, we’re using a try-catch block to handle errors. If an error occurs in the try block, the code in the catch block will execute. Here, we’re logging the error message to the console. While this is fine during development, exposing such detailed error messages in a production environment can be risky.

Best Practices for Secure Error Handling

Generic Error Messages

At the heart of secure error handling lies the principle of ambiguity. While it’s essential for developers to understand the root cause of an error during the development phase, it’s equally crucial to ensure that end-users are shielded from these intricate details. 

A simple, generic error message can inform the user of an issue without handing over the keys to your application’s inner workings. It’s akin to telling someone you’re busy without revealing the specifics of your schedule.

try {
  // Some risky code
} catch (error) {
  console.error(“An error occurred. Please try again later.”);

In this modified snippet, we’ve replaced the detailed error message with a generic one. This informs the user that something went wrong, without giving away any specifics.

Custom Error Pages

Custom error pages serve a dual purpose. Not only do they enhance the user experience by providing a consistent look and feel during error scenarios, but they also act as a protective barrier, concealing the intricate details of your application’s architecture. 

Think of it as a polite doorman who, instead of bluntly stating that a resident is not home, courteously informs visitors that they can’t be reached at the moment.

app.use((err, req, res, next) => {

Here, we’re using Express.js middleware to catch all errors and render a custom error page. This improves user experience and enhances security by not exposing stack traces or other sensitive information.

Log Errors Securely

While the external face of your error handling should be as generic as possible, internally, detailed logging is invaluable. It’s essential to have a comprehensive record of errors for debugging and analysis. 

However, the key is to ensure these logs are stored securely, away from prying eyes. It’s like having a private diary with a lock, where you jot down your daily events, ensuring it’s kept in a safe place.

const winston = require(‘winston’);

try {
  // Some risky code
} catch (error) {
  winston.error(`An error occurred: ${error.message}`);

In this snippet, we’re using the Winston logging library to log errors. This allows developers to debug issues without risking information leakage.

Advanced Techniques

Rate Limiting Error Responses

An unusually high frequency of error responses can be a red flag, indicating potential malicious activity. Rate limiting acts as a protective shield, ensuring your application doesn’t become an easy target for attackers trying to exploit vulnerabilities. 

It’s the digital equivalent of a security guard monitoring the number of times someone tries to enter a building and denying access after a certain limit.

const rateLimit = require(“express-rate-limit”);

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100 // limit each IP to 100 requests per windowMs


Here, we’re using the express-rate-limit middleware to limit the number of requests from each IP address. This can help mitigate brute-force attacks that aim to trigger errors and gather information.

Monitoring and Alerts

Being proactive is the name of the game. Setting up monitoring tools not only helps in keeping an eye on the health of your application but also acts as an early warning system. 

By getting alerts on unusual patterns or high error rates, you can take swift action, potentially thwarting any malicious attempts. It’s like having a security camera that sends you a notification when it detects suspicious activity.

const monitoringTool = require(“some-monitoring-tool”);


In this hypothetical example, we’re using a monitoring tool that sends an alert when a high error rate is detected. This allows you to take immediate action.

User Training

Often, the frontline of defense against potential security threats is the end-user. By educating users about the significance of error messages and the potential risks associated with them, you empower them to be an active part of the security protocol. 


Error handling, while essential for the smooth functioning and debugging of an application, can inadvertently become a chink in the armor if not done right. Striking the right balance between user-friendliness and security is the challenge. As we’ve seen, it’s possible to turn error handling from a potential vulnerability into a robust security feature with the right measures in place. So, don’t wait for a breach to happen. Tighten up those error messages, and ensure your web app remains as guarded as a fortress. Interested in seeing how you can further enhance your application’s security? Book a demo with today!

About ShiftLeft

ShiftLeft empowers developers and AppSec teams to dramatically reduce risk by quickly finding and fixing the vulnerabilities most likely to reach their applications and ignoring reported vulnerabilities that pose little risk. Industry-leading accuracy allows developers to focus on security fixes that matter and improve code velocity while enabling AppSec engineers to shift security left.

A unified code security platform, ShiftLeft CORE scans for attack context across custom code, APIs, OSS, containers, internal microservices, and first-party business logic by combining results of the company’s and Intelligent Software Composition Analysis (SCA). Using its unique graph database that combines code attributes and analyzes actual attack paths based on real application architecture, ShiftLeft then provides detailed guidance on risk remediation within existing development workflows and tooling. Teams that use ShiftLeft ship more secure code, faster. Backed by SYN Ventures, Bain Capital Ventures, Blackstone, Mayfield, Thomvest Ventures, and SineWave Ventures, ShiftLeft is based in Santa Clara, California. For information, visit:


See for yourself – run a scan on your code right now