HIGH path traversalhapiapi keys

Path Traversal in Hapi with Api Keys

Path Traversal in Hapi with Api Keys — how this specific combination creates or exposes the vulnerability

Path Traversal occurs when user-controlled input is used to construct file system paths without proper validation, allowing an attacker to access files outside the intended directory. In a Hapi server that relies on API keys for access control, this risk can be amplified if keys are treated as a primary authorization boundary without validating file paths.

Consider a Hapi route that serves user-uploaded documents. If the route uses an API key to identify a tenant or user and directly concatenates a user-supplied filename into a filesystem path, an attacker can supply inputs like ../../../etc/passwd to traverse directories. Even with an API key in place, the server may still serve sensitive files if path normalization is missing. The API key identifies the caller but does not guarantee that the requested file belongs to the caller’s allowed scope, creating a privilege confusion scenario.

For example, a route defined as:

const Hapi = require('@hapi/hapi');
const fs = require('fs').promises;
const path = require('path');

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

server.route({
  method: 'GET',
  path: '/files/{filename}',
  options: {
    validate: {
      headers: Joi.object({
        'api-key': Joi.string().required()
      }).unknown()
    },
    handler: async (request, h) => {
      const apiKey = request.headers['api-key'];
      const tenantDir = `/data/${apiKey}`;
      const filePath = path.join(tenantDir, request.params.filename);
      return fs.readFile(filePath, 'utf8');
    }
  }
});

An attacker can send a request with api-key: tenantA and filename: ../../tenantB/config.json. The server resolves the path to /data/tenantA/../../tenantB/config.json, which may escape the tenant’s directory if the application does not canonicalize and verify that the resolved path remains within /data/tenantA. The presence of the API key does not prevent unauthorized file access; it only identifies the tenant making the request.

In this context, the API key is used for tenant identification but not for path scoping. Without additional checks—such as ensuring the resolved path starts with the expected base directory—an attacker can leverage directory traversal to read arbitrary files accessible to the process, including configuration files, logs, or other tenants’ data. This pattern is relevant to the BOLA/IDOR checks in middleBrick’s 12 security tests, which look for insecure direct object references and improper authorization boundaries even when authentication tokens like API keys are present.

Api Keys-Specific Remediation in Hapi — concrete code fixes

To mitigate path traversal when using API keys in Hapi, you must validate and sanitize file paths independently of the key-based tenant identification. The API key can determine the tenant directory, but the filename must be normalized and confined to that directory.

Use path.resolve and path.relative to ensure the resolved path does not escape the tenant root. Avoid directly concatenating user input into paths, and prefer using a strict allowlist for filenames or a mapping layer that decouples user input from filesystem names.

Secure example with proper path confinement:

const Hapi = require('@hapi/hapi');
const fs = require('fs').promises;
const path = require('path');

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

server.route({
  method: 'GET',
  path: '/files/{filename}',
  options: {
    validate: {
      headers: Joi.object({
        'api-key': Joi.string().required()
      }).unknown()
    },
    handler: async (request, h) => {
      const apiKey = request.headers['api-key'];
      const tenantDir = path.resolve('/data', apiKey);
      const safeName = request.params.filename.replace(/[^a-zA-Z0-9._-]/g, '');
      const filePath = path.resolve(tenantDir, safeName);

      // Ensure the resolved path is within the tenant directory
      if (!filePath.startsWith(tenantDir)) {
        throw Boom.forbidden('Access denied');
      }

      return fs.readFile(filePath, 'utf8');
    }
  }
});

Key remediation steps:

  • Resolve the tenant directory with path.resolve to eliminate . and .. segments.
  • Normalize the user-supplied filename by removing or replacing potentially dangerous characters, or map it to a storage-safe identifier.
  • After constructing the full path, verify that it starts with the tenant directory; reject the request if it escapes.
  • Consider using a filename-to-uuid mapping in your database so that user input never directly influences the filesystem path.

These practices complement API key usage by ensuring that even if an API key identifies a tenant, file access remains confined to that tenant’s directory, addressing both path traversal and authorization boundary concerns covered by middleBrick’s checks such as Property Authorization and BOLA/IDOR.

Related CWEs: inputValidation

CWE IDNameSeverity
CWE-20Improper Input Validation HIGH
CWE-22Path Traversal HIGH
CWE-74Injection CRITICAL
CWE-77Command Injection CRITICAL
CWE-78OS Command Injection CRITICAL
CWE-79Cross-site Scripting (XSS) HIGH
CWE-89SQL Injection CRITICAL
CWE-90LDAP Injection HIGH
CWE-91XML Injection HIGH
CWE-94Code Injection CRITICAL

Frequently Asked Questions

Can API keys alone prevent path traversal in Hapi?
No. API keys identify a tenant or user but do not enforce file path boundaries. Without path normalization and validation, an attacker can traverse directories regardless of the presence of an API key.
How does middleBrick relate to path traversal with API keys?
middleBrick runs checks such as BOLA/IDOR and Property Authorization that can detect insecure direct object references and missing path confinement, even when API keys are used for authentication.