HIGH double freeexpressbearer tokens

Double Free in Express with Bearer Tokens

Double Free in Express with Bearer Tokens — how this specific combination creates or exposes the vulnerability

In Express.js applications that rely on Bearer token authentication, a Double Free vulnerability can arise when token parsing, validation, and storage logic are inconsistently applied across middleware and route handlers. This typically occurs when a token is decoded or verified in one layer (e.g., an authentication middleware) and then decoded or freed again in another (e.g., a route handler or a secondary validation utility), without a shared ownership model or reference tracking. Because Bearer tokens are often passed via the Authorization header as Authorization: Bearer <token>, improper handling of string references, asynchronous verification promises, or repeated calls to token parsing libraries can lead to use-after-free or memory corruption patterns in the underlying runtime, especially when native addons or C++ bindings are involved.

The risk is compounded when token validation is performed multiple times per request—for example, once by a generic auth middleware and again within a specific route or service. If the token payload is mutated or partially freed between these validations, an attacker can manipulate the request by resubmitting malformed tokens, causing the application to follow invalid memory states. This can lead to crashes or, in more severe environments, arbitrary code execution. From a security risk perspective, this maps to authentication bypass and integrity violations, which are among the most critical findings in API security scans.

Real-world examples include scenarios where JSON Web Tokens (JWTs) are verified using libraries such as jsonwebtoken, and the decoded payload is both stored in req.user and re-parsed in downstream logic. If an attacker sends a token with a manipulated header or payload that triggers edge-case memory handling in the JWT library, the repeated verification and object creation can expose the vulnerability. While this is a runtime concern rather than a specification flaw, the OpenAPI contract may fail to document the exact validation steps, causing runtime behavior to diverge from documented expectations. This discrepancy is detectable by spec-aware scanners that cross-reference the OpenAPI/Swagger definition with runtime authentication behavior.

Because middleBrick scans the unauthenticated attack surface and runs 12 security checks in parallel—including Authentication, Input Validation, and Property Authorization—it can surface inconsistencies in how tokens are handled across the request lifecycle. The LLM/AI Security module further ensures that system prompt leakage or token handling logic is not inadvertently exposed through error messages or debug output. Findings include severity-ranked guidance, mapped to frameworks such as OWASP API Top 10 and PCI-DSS, helping teams understand the risk without requiring internal architecture details.

Bearer Tokens-Specific Remediation in Express — concrete code fixes

To remediate Double Free risks in Express when using Bearer tokens, centralize token extraction and verification so that each request is authenticated exactly once. Use a single middleware function that validates the token, attaches the payload to req.user, and ensures no downstream code re-verifies or re-parses the same token. Below is a secure pattern using the jsonwebtoken library:

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

const PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
-----END PUBLIC KEY-----`;

function authenticateToken(req, res, next) {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1];
  if (!token) {
    return res.status(401).json({ error: 'Access token required' });
  }

  jwt.verify(token, PUBLIC_KEY, { algorithms: ['RS256'] }, (err, decoded) => {
    if (err) {
      return res.status(403).json({ error: 'Invalid or expired token' });
    }
    req.user = decoded;
    next();
  });
}

app.use(authenticateToken);

app.get('/profile', (req, res) => {
  res.json({ user: req.user });
});

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

For applications using opaque tokens (e.g., random strings stored in a database or cache), avoid decoding the token payload multiple times. Instead, validate the token once via a remote introspection endpoint or a local cache, then store a minimal user identifier in req.user. Here is an example using a custom introspection check:

app.use((req, res, next) => {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1];
  if (!token) {
    return res.status(401).json({ error: 'Access token required' });
  }

  // Assume validateToken is a function that checks token validity against a service
  validateToken(token).then(isValid => {
    if (!isValid) {
      return res.status(403).json({ error: 'Invalid token' });
    }
    // Attach only necessary data to avoid re-validation
    req.user = { tokenId: hashToken(token) };
    next();
  }).catch(() => res.status(500).json({ error: 'Authentication service error' }));
});

Ensure that error handling does not leak token material in responses or logs. Configure your logging layer to redact Authorization header values and avoid printing raw tokens. The middleBrick CLI can be used to verify that your authentication flow does not expose tokens in error messages or debug output by running middlebrick scan <url> and reviewing the Authentication and Data Exposure findings. Teams on the Pro plan can enable continuous monitoring to detect regressions in token handling as the API evolves, while the GitHub Action can fail builds if the security score drops below a defined threshold.

Frequently Asked Questions

Why does resending the same Bearer token in multiple middleware layers increase risk?
Resending and reprocessing the same Bearer token across multiple layers can cause repeated parsing or verification, which may trigger memory handling issues such as double-free vulnerabilities. To reduce risk, authenticate once per request and attach the result to req.user for downstream use.
How can I verify my Express app does not leak Bearer tokens in error messages?
Use the middleBrick CLI to scan your endpoint: middlebrick scan <url>. Review Authentication and Data Exposure findings. Also ensure error responses return generic messages and that logging redacts Authorization headers.