Cache Poisoning in Hapi with Basic Auth
Cache Poisoning in Hapi with Basic Auth — how this specific combination creates or exposes the vulnerability
Cache poisoning occurs when an attacker causes a cache to store malicious content, which is then served to other users. In Hapi, when HTTP Basic Auth is used without additional safeguards, this risk can manifest through the interaction of caching layers and authentication handling. If responses are cached based solely on the request URL without incorporating the Authorization header or user context, different authenticated users may inadvertently receive cached responses intended for others.
Consider a scenario where a Hapi server caches a response for a GET endpoint that requires Basic Auth. If the cache key excludes the Authorization header, a user with limited permissions might receive a cached response originally generated for an admin user. This can expose sensitive data or functionality, effectively bypassing intended access controls. The vulnerability is not in Basic Auth itself but in how caching logic treats authenticated requests as interchangeable based on non-varying request attributes.
Additionally, an attacker could attempt to poison the cache by sending crafted requests that result in error or redirect responses being cached. If the server returns different content based on authentication status and the cache does not differentiate these states, poisoned entries can persist across requests. For example, a 401 response for an invalid user might be cached and subsequently served to a valid user, causing unexpected authentication challenges or information disclosure.
To detect such risks, scanning tools like middleBrick analyze the unauthenticated attack surface and check whether caching behavior varies appropriately with authentication context. The tool runs multiple security checks in parallel, including Authentication and BOLA/IDOR evaluations, to identify inconsistencies that could enable cache poisoning or privilege confusion in frameworks such as Hapi.
Basic Auth-Specific Remediation in Hapi — concrete code fixes
To mitigate cache poisoning when using HTTP Basic Auth in Hapi, ensure that cached responses are segregated by authentication context. This can be achieved by including the Authorization header or a derived user identifier in the cache key, or by avoiding caching for authenticated responses altogether where sensitivity is high.
The following example demonstrates a secure Hapi setup with Basic Auth and cache-control headers tailored to prevent unauthorized cache sharing:
const Hapi = require('@hapi/hapi');
const auth = require('basic-auth');
const validate = async (request, username, password, h) => {
// Replace with secure credential verification
const isValid = username === 'admin' && password === 'secure_password';
if (!isValid) {
return { isValid: false };
}
return { isValid: true, credentials: { username } };
};
const init = async () => {
const server = Hapi.server({
port: 3000,
host: 'localhost'
});
server.auth.strategy('simple', 'basic', { validate });
server.route({
method: 'GET',
path: '/secure-data',
options: {
auth: 'simple',
handler: (request, h) => {
const user = request.auth.credentials.username;
// Avoid caching authenticated responses by default
h.state('auth', 'user');
return { data: `Sensitive data for ${user}`, noCache: true };
},
cache: {
privacy: 'private'
}
}
});
// Public endpoint with explicit cache rules
server.route({
method: 'GET',
path: '/public-info',
handler: () => ({ info: 'Public data' }),
options: {
cache: {
privacy: 'public',
maxAge: 60000
},
handler: (request, h) => {
return { info: 'Public data' };
}
}
});
await server.start();
console.log('Server running on %s', server.info.uri);
};
init();
Key practices include setting cache.privacy to 'private' for authenticated responses, avoiding shared cache storage for user-specific data, and ensuring that cache keys incorporate user identity when caching is necessary. middleBrick’s checks for Authentication and Data Exposure can help verify that such configurations are correctly enforced and that no sensitive data is inadvertently cached.