Integer Overflow in Express with Bearer Tokens
Integer Overflow in Express with Bearer Tokens — how this specific combination creates or exposes the vulnerability
An integer overflow in an Express application using Bearer tokens can occur when a numeric value derived from or associated with a token exceeds the safe integer range supported by JavaScript. In JavaScript, integers are represented as 64-bit floating point numbers, and safe integer range is limited to Number.MAX_SAFE_INTEGER (2^53 - 1). If an API endpoint parses a token payload or extracts a numeric claim (such as exp, iat, or a custom numeric scope) and performs arithmetic or comparison operations without validating size, the result can wrap around, leading to authentication bypass, privilege escalation, or logic flaws.
Consider an Express route that decodes a Bearer token and uses a numeric claim to determine access level. For example, a token may include a scope_id claim intended to represent a tenant or user ID. If the application adds 1 to this ID to compute the next resource to check, and the claim contains a large value near Number.MAX_SAFE_INTEGER, the addition can overflow to a negative number or zero. This can cause the application to treat a high-privilege tenant as a low-privilege one, or inadvertently grant access to another tenant’s resources (a BOLA/IDOR pattern).
In practice, an attacker who can influence the numeric portion of a Bearer token (for instance, by modifying a non‑cryptographically signed claim in a loosely validated token) might supply a very large integer. When the server performs calculations such as buffer sizes, array indices, or database offsets using this value, the overflow can lead to incorrect memory access patterns, out-of-bounds reads, or unexpected behavior. This is especially relevant when the token is used to compute offsets for data retrieval or to decide how many items to return in a response. The vulnerability is not in the token format itself, but in the unsafe handling of numeric values extracted from the token within Express middleware or route handlers.
Real-world examples in other ecosystems illustrate the pattern: vulnerabilities involving integer overflow in JWT handling have been observed when libraries or custom code fail to validate numeric headers or claims. Although this specific scenario is not tied to a published CVE in the context of Express and Bearer tokens, the underlying class of flaw aligns with common weaknesses such as CWE-190 (Integer Overflow or Wraparound). The risk is compounded when the application trusts token claims without re‑validating them against a trusted identity provider or internal authorization store.
To detect such issues, middleBrick runs checks that examine how numeric values from Bearer tokens are used in runtime logic, including comparisons, arithmetic, and access control decisions. The scanner looks for patterns where token-derived numbers flow into operations that could overflow, and it cross‑references these findings with the API specification to highlight high‑risk endpoints. This helps developers identify unsafe handling of token claims before they can be exploited in production.
Bearer Tokens-Specific Remediation in Express — concrete code fixes
Remediation focuses on validating and sanitizing numeric values derived from Bearer tokens before using them in calculations or access control. Do not trust claims such as exp, iat, or custom numeric fields unless verified through a trusted authentication source. Use explicit checks to ensure values are within expected ranges and avoid arithmetic that could overflow.
Example 1: Safe numeric extraction and range validation
Instead of directly using a token claim in arithmetic, validate it first:
const jwt = require('jsonwebtoken');
function validateToken(req, res, next) {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return res.status(401).send('Unauthorized');
}
const token = authHeader.split(' ')[1];
let payload;
try {
payload = jwt.verify(token, process.env.JWT_SECRET);
} catch (err) {
return res.status(401).send('Invalid token');
}
// Validate numeric claim safely
const scopeId = payload.scope_id;
if (typeof scopeId !== 'number' || !Number.isInteger(scopeId) || scopeId <= 0 || scopeId > 1000000) {
return res.status(403).send('Forbidden: invalid scope');
}
req.user = { scopeId };
next();
}
app.use(validateToken);
Example 2: Avoiding overflow in calculations
If you must perform arithmetic on values derived from a token, use BigInt or enforce strict upper bounds:
app.get('/resource/:index', (req, res) => {
const base = req.user?.scopeId || 1000;
const index = Number(req.params.index);
// Validate inputs
if (!Number.isSafeInteger(index) || index < 0) {
return res.status(400).send('Bad request');
}
// Use BigInt to prevent overflow when needed
const bigBase = BigInt(base);
const bigIndex = BigInt(index);
const sum = bigBase + bigIndex;
if (sum > BigInt(Number.MAX_SAFE_INTEGER)) {
return res.status(400).send('Bad request: value too large');
}
const safeSum = Number(sum);
// Proceed with safeSum
res.json({ calculatedValue: safeSum });
});
Example 3: Middleware to enforce token claim constraints
Apply global checks to ensure token-derived numbers remain within safe ranges:
function safeTokenClaims(req, res, next) {
const token = req.headers.authorization?.split(' ')[1];
if (!token) {
return next();
}
try {
const payload = jwt.verify(token, process.env.JWT_SECRET);
if (payload.iat && (typeof payload.iat !== 'number' || payload.iat > Date.now() / 1000 + 60)) {
return res.status(403).send('Forbidden: invalid token timing');
}
if (payload.exp && (typeof payload.exp !== 'number' || payload.exp * 1000 < Date.now())) {
return res.status(401).send('Token expired');
}
// Reject unexpected large numeric claims
for (const key of Object.keys(payload)) {
if (typeof payload[key] === 'number' && (payload[key] > 1e6 || payload[key] < -1e6)) {
return res.status(403).send('Forbidden: suspicious token claim');
}
}
req.tokenPayload = payload;
} catch (err) {
return res.status(401).send('Invalid token');
}
next();
}
app.use(safeTokenClaims);
These examples demonstrate how to handle Bearer tokens safely in Express by validating types, enforcing ranges, and avoiding unchecked arithmetic on untrusted numeric data. Combining these practices with runtime scanning helps identify unsafe patterns before they can be exploited.