Type Confusion in Express with Bearer Tokens
Type Confusion in Express with Bearer Tokens — how this specific combination creates or exposes the vulnerability
Type confusion in Express applications using Bearer tokens typically arises when token handling logic does not enforce strict type checks, allowing an attacker to manipulate how the application interprets authentication data. When an Express route expects a structured token payload (e.g., a JWT decoded into an object) but receives a value that is not an object—such as a string, number, or null—the application may incorrectly coerce or access properties, leading to authorization bypass or runtime errors.
Consider an endpoint that decodes a Bearer token and directly accesses a property without verifying the decoded type:
app.get('/user/profile', (req, res) => {
const authHeader = req.headers.authorization;
const token = authHeader && authHeader.split(' ')[1];
if (!token) return res.sendStatus(401);
// Vulnerable: no validation that decoded is an object
const decoded = jwt.verify(token, process.env.JWT_SECRET);
const role = decoded.role; // type confusion if decoded is not an object
if (role !== 'admin') return res.sendStatus(403);
res.json({ message: 'Admin data' });
});
If jwt.verify is tricked (e.g., via a malformed token or a weak secret) into returning a string or number—perhaps due to a library misconfiguration or an unexpected token format—then decoded.role may evaluate to undefined or coerce unexpectedly. This type confusion can cause the application to treat a non-admin token as having elevated privileges, effectively bypassing intended access controls.
Another scenario involves inconsistent type expectations between middleware and route handlers. For example, if a middleware attaches a user object to req.user after token verification, but a later route assumes req.user is always a string ID, an attacker could exploit this mismatch by providing a token that decodes to a non-object value, leading to property access on a primitive and potential privilege escalation.
These issues are detectable by security scanners like middleBrick, which runs checks such as Input Validation and Property Authorization in parallel. By submitting an unauthenticated URL to middleBrick, you receive a security risk score and findings that highlight where type expectations are not enforced, along with prioritized remediation guidance mapped to frameworks such as OWASP API Top 10.
Using the free tier, you can quickly assess unauthenticated endpoints for this class of issue. For continuous coverage across many APIs, the Pro plan provides automated scanning on a configurable schedule, and the CLI allows you to integrate checks into development workflows with JSON output for precise tracking.
Bearer Tokens-Specific Remediation in Express — concrete code fixes
To prevent type confusion when handling Bearer tokens in Express, enforce strict type validation on decoded token payloads before accessing any properties. Always treat decoded tokens as objects and verify their structure and types explicitly.
Here is a secure pattern using the jsonwebtoken library with type checking:
const jwt = require('jsonwebtoken');
function verifyToken(token) {
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
// Enforce that decoded is an object with expected shape
if (typeof decoded !== 'object' || decoded === null) {
throw new Error('Invalid token payload');
}
if (typeof decoded.role !== 'string' || typeof decoded.sub !== 'string') {
throw new Error('Token payload malformed');
}
return decoded;
} catch (err) {
throw new Error('Token verification failed');
}
}
app.get('/user/profile', (req, res) => {
const authHeader = req.headers.authorization;
const token = authHeader && authHeader.split(' ')[1];
if (!token) return res.sendStatus(401);
const decoded = verifyToken(token);
// At this point, decoded is guaranteed to be an object with typed fields
if (decoded.role !== 'admin') return res.sendStatus(403);
res.json({ message: 'Admin data', userId: decoded.sub });
});
This approach ensures that decoded is an object and that critical fields like role and sub are strings, preventing type confusion attacks. It also centralizes verification logic, which reduces the risk of inconsistent handling across routes.
For broader protection, combine this with input validation libraries such as joi or zod to define and enforce token payload schemas:
const Joi = require('joi');
const tokenSchema = Joi.object({
sub: Joi.string().required(),
role: Joi.string().valid('user', 'admin').required(),
exp: Joi.number().required(),
});
function validateTokenPayload(payload) {
const { error } = tokenSchema.validate(payload);
if (error) throw new Error('Invalid token payload');
return payload;
}
app.get('/user/settings', (req, res) => {
const authHeader = req.headers.authorization;
const token = authHeader && authHeader.split(' ')[1];
if (!token) return res.sendStatus(401);
const decoded = jwt.verify(token, process.env.JWT_SECRET);
const validated = validateTokenPayload(decoded);
if (validated.role !== 'admin') return res.sendStatus(403);
res.json({ settings: 'secure data' });
});
These practices align with input validation and property authorization checks performed by security tools like middleBrick. Using the GitHub Action, you can enforce that any API with weak token handling fails CI/CD gates before deployment. The MCP Server allows you to scan APIs directly from IDEs while writing such safeguards, and the Dashboard helps you track improvements over time.
Finally, document token expectations in your API specifications (OpenAPI 3.0/3.1) and resolve all $ref references so that runtime behavior matches the defined schema. This reduces the likelihood of type confusion and supports compliance mapping to standards such as OWASP API Top 10 and SOC2.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |