Pii Leakage in Express with Hmac Signatures
Pii Leakage in Express with Hmac Signatures — how this specific combination creates or exposes the vulnerability
In Express applications, Hmac Signatures are commonly used to verify the integrity and origin of requests, for example when a webhook or a third‑party service sends a JSON payload along with an HMAC header. If response building or logging inadvertently includes sensitive data such as email addresses, phone numbers, or government IDs, and if the Hmac verification step does not prevent exposure in all code paths, PII can be leaked through error messages, debug endpoints, or logs. The combination is risky because developers may assume that Hmac verification alone protects the response content, but verification only authenticates the source—it does not control what data is included in the response or logged during processing.
During a black‑box scan, middleBrick tests unauthenticated endpoints that accept Hmac‑signed input and inspects whether responses or logs can disclose PII. For instance, if an Express route parses an Hmac header, validates it, and then returns user details including a full email address or internal identifiers in JSON, a low‑privilege attacker who can trigger error paths or observe logs may obtain PII. MiddleBrick specifically checks for Data Exposure across categories such as PII and maps findings to frameworks like OWASP API Top 10 and GDPR, highlighting cases where authenticated or unauthenticated endpoints return sensitive data without proper minimization or masking.
Another vector involves inconsistent handling of Hmac verification failures. If an Express route does not uniformly exit before constructing a response, an attacker might force a code path that skips verification and returns data that includes PII. middleBrick’s authentication and BOLA/IDOR checks are designed to surface these inconsistencies by observing whether responses differ based on presence or validity of Hmac headers, and whether error responses expose stack traces or data fields that should remain internal.
Hmac Signatures‑Specific Remediation in Express — concrete code fixes
To prevent PII leakage when using Hmac Signatures in Express, ensure verification is strict, responses contain only necessary data, and errors do not leak information. Below are concrete, working examples that demonstrate a secure pattern.
1. Consistent verification and early exit
Always verify the Hmac before processing business logic, and exit immediately on failure to avoid unintended data exposure.
const crypto = require('crypto');
const express = require('express');
const app = express();
app.use(express.json());
const SHARED_SECRET = process.env.WEBHOOK_SECRET;
function verifyHmac(req) {
const signature = req.headers['x-hub-signature-256'];
if (!signature || !signature.startsWith('sha256=')) {
return false;
}
const hash = crypto.createHmac('sha256', SHARED_SECRET)
.update(JSON.stringify(req.body))
.digest('hex');
const expected = signature.split('=')[1];
return crypto.timingSafeEqual(Buffer.from(hash), Buffer.from(expected));
}
app.post('/webhook', (req, res) => {
if (!verifyHmac(req)) {
return res.status(401).json({ error: 'invalid signature' });
}
// process verified payload
const masked = {
id: req.body.id,
email: req.body.email ? req.body.email.replace(/(.{2}).+(@.*)/, '$1***$2') : null
};
res.json({ received: masked });
});
2. Avoid logging PII
Ensure logs do not include sensitive fields. Use a sanitization helper when structured logging is required.
function sanitizeLog(payload) {
const { email, phone, ssn, ...safe } = payload;
return safe;
}
app.post('/webhook', (req, res) => {
if (!verifyHmac(req)) {
return res.status(401).json({ error: 'invalid signature' });
}
console.log('webhook received', sanitizeLog(req.body));
const masked = {
id: req.body.id,
email: req.body.email ? req.body.email.replace(/(.{2}).+(@.*)/, '$1***$2') : null
};
res.json({ received: masked });
});
3. Use schema validation and field selection
Validate input shape and explicitly pick fields to return, reducing the risk of accidentally including PII.
const { body, validationResult } = require('express-validator');
app.post('/webhook', [
body('id').isString(),
body('email').isEmail().optional()
], (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
if (!verifyHmac(req)) {
return res.status(401).json({ error: 'invalid signature' });
}
const { id, email } = req.body;
// only include intended fields
res.json({ id, email: email ? email.toLowerCase() : undefined });
});
4. Centralized error handling
Use an error-handling middleware to ensure stack traces and PII are not returned in production.
app.use((err, req, res, next) => {
console.error('Unexpected error:', err && err.message ? err.message : err);
res.status(500).json({ error: 'internal server error' });
});
Related CWEs: dataExposure
| CWE ID | Name | Severity |
|---|---|---|
| CWE-200 | Exposure of Sensitive Information | HIGH |
| CWE-209 | Error Information Disclosure | MEDIUM |
| CWE-213 | Exposure of Sensitive Information Due to Incompatible Policies | HIGH |
| CWE-215 | Insertion of Sensitive Information Into Debugging Code | MEDIUM |
| CWE-312 | Cleartext Storage of Sensitive Information | HIGH |
| CWE-359 | Exposure of Private Personal Information (PII) | HIGH |
| CWE-522 | Insufficiently Protected Credentials | CRITICAL |
| CWE-532 | Insertion of Sensitive Information into Log File | MEDIUM |
| CWE-538 | Insertion of Sensitive Information into Externally-Accessible File | HIGH |
| CWE-540 | Inclusion of Sensitive Information in Source Code | HIGH |