HIGH cache poisoninghapijwt tokens

Cache Poisoning in Hapi with Jwt Tokens

Cache Poisoning in Hapi with Jwt Tokens — how this specific combination creates or exposes the vulnerability

Cache poisoning occurs when an attacker causes a cache to store malicious content that is subsequently served to other users. In Hapi, this risk can emerge when responses that include sensitive Jwt Tokens are cached inadvertently. If a server caches a response that contains a set-cookie or an authorization header with a JWT, and that response is keyed by a non-unique input such as a query parameter, an authenticated attacker may force the storage of a token under a shared cache key.

Hapi applications often use caching plugins (such as @hapi/catbox) to improve performance. When JWT-based authentication is used, cached responses must be scoped to the requesting user or omit sensitive headers entirely. If the cache key does not incorporate user context (e.g., the subject or identifier from the JWT payload), one user’s token may be stored and later returned to another user, leading to token leakage via cache side channels.

In practice, this can happen when route configurations in Hapi set cache options without accounting for authorization headers or JWT claims. For example, a route that caches based solely on URL and query parameters may store a response that includes an Authorization: Bearer <JWT> header. Subsequent requests that do not include the same JWT may still receive the cached response, inadvertently exposing the token or allowing privilege confusion.

Additional risk arises if cached error responses include sensitive information from JWT claims. For instance, if an upstream service returns a JSON payload with user roles encoded in the JWT and this response is cached, an attacker who can influence cache key generation might retrieve another user’s role information without presenting a valid token for that user.

To detect this class of issue, scans compare runtime outputs for sensitive headers and JWT-related artifacts against the caching behavior defined in the OpenAPI/Swagger specification. Findings highlight mismatches where cached responses contain Jwt Tokens or related authorization headers without user-specific cache partitioning.

Jwt Tokens-Specific Remediation in Hapi — concrete code fixes

Remediation focuses on ensuring cache keys incorporate user identity and that cached responses never include sensitive Jwt Tokens or authorization headers. Below are concrete Hapi patterns to address the issue.

1. Include user identifier in cache key

When using @hapi/catbox, derive the cache key from a combination of the route path and the user’s subject (e.g., from the validated JWT).

// Example: Hapi route with user-aware cache key
const Hapi = require('@hapi/hapi');
const Catbox = require('@hapi/catbox');
const Memory = require('@hapi/catbox-memory');

const server = Hapi.server({ port: 4000 });

server.cache({
  name: 'userCache',
  engine: Memory,
  expiresIn: 60 * 1000
});

server.route({
  method: 'GET',
  path: '/profile',
  options: {
    auth: 'jwt',
    cache: {
      cache: 'userCache',
      // key is built from route + user id from JWT payload
      generateTimeout: 2000,
      dropTimeout: false,
      partition: 'profile',
      // The key will be used by catbox to isolate caches per user
      // Implementation detail: derive key in pre handler
    },
    handler: async (request, h) => {
      const userId = request.auth.credentials.userId; // from JWT
      const cacheKey = `profile-${userId}`;
      const cached = await request.cache.get(cacheKey);
      if (cached) {
        return cached;
      }
      const data = { userId, name: 'Alice' }; // protected data
      await request.cache.set(cacheKey, data, 60000);
      return data;
    }
  }
});

server.auth.strategy('jwt', 'bearer-access-token', {
  validate: async (request, decoded) => ({
    isValid: true,
    credentials: {
      userId: decoded.sub
    }
  })
});

server.auth.default('jwt');

(async () => {
  await server.start();
  console.log('Server running on %s', server.info.uri);
})();

2. Do not cache responses containing Jwt Tokens

Ensure that responses containing Authorization or Set-Cookie headers with JWTs are marked as non-cacheable or cached with user-specific isolation.

// Example: Explicitly exclude sensitive headers from shared cache
server.route({
  method: 'GET',
  path: '/user-settings',
  options: {
    auth: 'jwt',
    cache: {
      cache: 'userCache',
      // Generate unique key per user to prevent cross-user leakage
      generateTimeout: 2000,
      partition: 'settings',
      // Custom key function to include user ID
      // (catbox supports a generateFunc in some setups; here we handle in handler)
    },
    handler: async (request, h) => {
      const userId = request.auth.credentials.userId;
      const settings = { theme: 'dark', notifications: true };
      // Do not place JWT in cached payload
      return settings;
    }
  }
});

Additionally, configure your upstream services to set Cache-Control: no-store for responses that include Jwt Tokens, and avoid caching any payload that contains access tokens or refresh tokens. MiddleBrick scans can validate that cached responses do not include sensitive headers and that the OpenAPI spec documents appropriate cache constraints.

For continuous assurance, use the middleBrick CLI to scan endpoints and verify that JWT-bearing responses are not cached. The GitHub Action can fail builds if risk thresholds are exceeded, and the MCP Server allows you to run scans directly from your AI coding assistant while developing Hapi routes.

Frequently Asked Questions

How does middleBrick detect cache poisoning risks involving Jwt Tokens?
middleBrick runs 12 parallel security checks, including Property Authorization and Data Exposure. It compares cached response behavior in runtime tests against the OpenAPI/Swagger spec, flagging cases where responses containing JWT-related headers are stored without user-specific cache partitioning.
Can the free plan be used to validate remediation for Cache Poisoning in Hapi?
Yes. The free plan provides 3 scans per month, which is sufficient to validate that Jwt Tokens are not leaking via cache and that cache keys incorporate user context. Upgrade paths such as Starter or Pro add continuous monitoring and CI/CD integration for automated regression detection.