Null Pointer Dereference in Express with Hmac Signatures
Null Pointer Dereference in Express with Hmac Signatures
Null pointer dereference in an Express route that uses Hmac signatures occurs when code attempts to read a property or call a method on a value that is null or undefined. This can happen when signature verification fails and the code does not handle a missing or malformed payload before accessing nested fields. For example, an Express route that expects a JSON body with a nested object may compute an Hmac signature and then directly access request.body.data.timestamp without confirming request.body or request.body.data exists. If the client sends an incomplete or malicious payload, the runtime value can be null or undefined, leading to a runtime exception that may crash the process or expose stack traces.
When Hmac signatures are involved, developers sometimes skip validation steps or assume a verified signature guarantees a well-formed payload. In practice, an attacker can send a valid Hmac over a minimal or malformed JSON structure that omits required fields. If the verification passes but the code later dereferences null fields, the application throws a null pointer dereference. This intersects with the unauthenticated attack surface because an external scanner can trigger the route without credentials. The vulnerability is not in the Hmac algorithm itself, but in unchecked assumptions about data presence after verification. Common patterns include destructuring nested objects, accessing properties on parsed JSON, or passing values to functions that expect non-null inputs.
In the context of the 12 security checks run by middleBrick, a null pointer dereference may be surfaced under Input Validation and Property Authorization. The scanner observes runtime behavior when malformed payloads are supplied with valid Hmac signatures, looking for crashes or information leaks. Because the scan tests the unauthenticated attack surface, it can detect cases where missing guards lead to exceptions. A robust approach is to validate and sanitize all inputs before use, ensure optional fields are checked for null or undefined, and use safe access patterns. This reduces the chance that a valid Hmac signature masks an unsafe assumption about data shape, preventing crashes that could be leveraged for denial of service or indirect information disclosure.
Hmac Signatures-Specific Remediation in Express
To remediate null pointer dereference risks in Express when using Hmac signatures, enforce strict validation of the request payload before any property access. Always check that required fields exist and are of the expected type, even when the Hmac verification succeeds. Use defensive coding patterns such as optional chaining and explicit null checks. Below are concrete, working examples that demonstrate a safe verification flow in Express.
First, a minimal Express setup that verifies an Hmac signature and safely accesses nested fields:
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());
const SHARED_SECRET = process.env.HMAC_SECRET;
function verifyHmac(req, res, next) {
const signature = req.get('x-hmac-signature');
if (!signature) {
return res.status(400).json({ error: 'Missing signature' });
}
const payload = JSON.stringify({
timestamp: req.body?.timestamp,
data: req.body?.data
});
const expected = crypto.createHmac('sha256', SHARED_SECRET).update(payload).digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
return res.status(401).json({ error: 'Invalid signature' });
}
next();
}
app.post('/event', verifyHmac, (req, res) => {
if (!req.body || !req.body.data) {
return res.status(400).json({ error: 'Invalid payload structure' });
}
const { timestamp, details } = req.body.data;
if (timestamp == null || details == null) {
return res.status(400).json({ error: 'Missing required fields' });
}
res.json({ received: { timestamp, details } });
});
app.listen(3000, () => console.log('Server running on port 3000'));
Second, an alternative pattern using a validation library to enforce shape and non-null fields before processing:
const express = require('express');
const crypto = require('crypto');
const { body, validationResult } = require('express-validator');
const app = express();
app.use(express.json());
const SHARED_SECRET = process.env.HMAC_SECRET;
function verifyHmac(req, res, next) {
const signature = req.get('x-hmac-signature');
if (!signature) {
return res.status(400).json({ error: 'Missing signature' });
}
const payload = JSON.stringify({ timestamp: req.body.timestamp, data: req.body.data });
const expected = crypto.createHmac('sha256', SHARED_SECRET).update(payload).digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
return res.status(401).json({ error: 'Invalid signature' });
}
next();
}
app.post('/event',
verifyHmac,
[
body('data').isObject().withMessage('data must be an object'),
body('data.timestamp').isInt({ min: 0 }).withMessage('timestamp must be a positive integer'),
body('data.details').isObject().withMessage('details must be an object')
],
(req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const { timestamp, details } = req.body.data;
res.json({ received: { timestamp, details } });
}
);
app.listen(3000, () => console.log('Server running on port 3000'));
In both examples, the Hmac verification runs before any property access, and explicit checks ensure req.body and req.body.data are present. This prevents null pointer dereference while maintaining the integrity of signature-based authentication.