HIGH data exposurehapibasic auth

Data Exposure in Hapi with Basic Auth

Data Exposure in Hapi with Basic Auth — how this specific combination creates or exposes the vulnerability

The combination of Hapi’s default behaviors and Basic Authentication can unintentionally expose sensitive data when transport protections are absent or when debugging/logging settings reveal credentials or application internals. Basic Authentication sends credentials in an Authorization header encoded as Base64, which is trivial to decode if intercepted. Without TLS, credentials and any data returned by the endpoint are transmitted in clear text across the network, enabling passive sniffing and session hijacking.

Even when TLS is enabled, implementation issues can lead to data exposure. For example, Hapi servers that log request or response details may inadvertently record Authorization headers or sensitive payloads if logging is not carefully scoped. Hapi’s built-in validation and error reporting can also surface raw input and server details in error responses, giving an attacker information about data structures, user identifiers, or backend behavior. These error messages may include stack traces, database field names, or object representations that should never reach untrusted clients.

Another vector specific to Hapi involves route configuration and caching. If responses containing sensitive data are cached by intermediary proxies or the server’s own cache mechanisms without appropriate controls, and if those caches are improperly segmented or purged, data can be read by unintended users. Hapi’s route options, such as cache settings, must be explicitly configured to avoid storing sensitive information. Similarly, CORS misconfigurations can allow unauthorized origins to read responses that include sensitive data, especially when credentials are handled via headers and the server defaults to overly permissive rules.

The scanner’s checks for Data Exposure analyze whether endpoints return sensitive information such as personally identifiable information (PII), authentication tokens, or internal identifiers without protective mechanisms like masking or encryption. In a Hapi service using Basic Auth, the scanner inspects response payloads, headers, and error messages for patterns that match known sensitive data formats and flags endpoints where such exposure occurs. It also evaluates whether TLS is enforced and whether server-side logging or instrumentation might leak credentials or data in logs or metrics.

These findings map to real-world attack patterns and compliance considerations. For example, improper error handling in Hapi can contribute to information disclosure as described in parts of the OWASP API Security Top 10, and unencrypted transmission of credentials aligns with risks around insecure transport. A concrete example of risky code is a Hapi server that responds with full validation error objects containing user input, which may reveal whether a given username exists or expose internal field names.

Basic Auth-Specific Remediation in Hapi — concrete code fixes

To mitigate data exposure when using Basic Authentication in Hapi, enforce TLS, avoid logging sensitive headers, and structure error responses to minimize information leakage. Below are concrete, working examples that demonstrate secure configurations and practices.

1. Enforce TLS and use the h2 module for secure communication

Always serve your Hapi application over HTTPS. Use the h2 module to enforce TLS and require secure communication before any route logic executes.

const Hapi = require('@hapi/hapi');
const tls = require('tls');

const init = async () => {
  const server = Hapi.server({
    port: 443,
    host: '0.0.0.0',
    tls: {
      key: fs.readFileSync('/path/to/server.key'),
      cert: fs.readFileSync('/path/to/server.crt'),
      rejectUnauthorized: true
    }
  });

  server.auth.scheme('custombasic', (server) => {
    return {
      authenticate(request, h) {
        const credentials = request.auth.credentials;
        if (!credentials || credentials.user !== 'secureuser') {
          return h.response({ message: 'Unauthorized' }).code(401);
        }
        return credentials;
      }
    };
  });

  server.auth.strategy('simple', 'custombasic');

  server.route({
    method: 'GET',
    path: '/secure',
    options: {
      auth: 'simple',
      plugins: {
        // Avoid logging sensitive headers
        logs: { collect: false }
      }
    },
    handler: (request, h) => {
      return { data: 'This is protected and only for authenticated, TLS-secured clients.' };
    }
  });

  await server.start();
  console.log('Server running securely with TLS and Basic Auth');
};

init();

2. Avoid logging Authorization headers or sensitive payloads

Configure your Hapi server and logging plugins to exclude Authorization headers and request/response bodies from logs. With the good-behavior logging approach, you reduce the risk of credentials or PII being persisted inadvertently.

const Hapi = require('@hapi/hapi');
const goodBehavior = require('good');

const server = Hapi.server({
  port: 4000,
  host: 'localhost'
});

await server.register({
  plugin: goodBehavior,
  options: {
    reporters: {
      console: [{
        module: 'good-squeeze',
        name: 'Squeeze',
        args: [{ log: '*', response: '*' }]
      }, {
        module: 'good-console'
      }, 'stdout']
    }
  }
});

// Ensure sensitive headers are not included in logs
server.ext('onPreResponse', (request, h) => {
  const response = request.response;
  if (response && response.headers) {
    // Example: strip or avoid exposing sensitive headers in any custom logging
    // Actual header removal should be done at proxy/load balancer if needed
  }
  return h.continue;
});

server.route({
  method: 'POST',
  path: '/login',
  options: {
    auth: false,
    plugins: {
      // Configure logging to exclude Authorization
      good: {
        logFilters: {
          excludeHeaders: ['authorization', 'cookie']
        }
      }
    }
  },
  handler: (request, h) => {
    const { username, password } = request.payload;
    // Validate credentials and issue response without echoing raw Authorization
    if (username === 'admin' && password === 'correct') {
      return { message: 'Login successful' };
    }
    return { message: 'Invalid credentials' };
  }
});

3. Return safe error messages and avoid data leakage

Customize Hapi’s error responses to avoid exposing stack traces, validation details, or data structure information. Use generic messages and ensure that errors do not include raw user input or internal identifiers.

const Hapi = require('@hapi/hapi');

const server = Hapi.server({
  port: 5000,
  host: 'localhost'
});

server.route({
  method: 'GET',
  path: '/profile',
  options: {
    auth: false,
    handler: (request, h) => {
      // Simulate a condition where data might be missing
      const user = null;
      if (!user) {
        // Return a generic error that does not reveal internal details
        const error = new Error('Resource not found');
        error.show = false; // Prevent Hapi from showing internal details in debug mode
        return h.response({ message: 'Not found' }).code(404);
      }
      // Return safe, masked data only when appropriate
      return { id: user.id, name: user.name };
    }
  }
});

server.ext('onPreResponse', (request, h) => {
  const response = request.response;
  if (response && response.isBoom) {
    // Avoid leaking stack traces or internal error details
    response.output.payload.show = false;
    response.output.payload.message = 'An error occurred';
  }
  return h.continue;
});

server.start();

4. Configure route caching and CORS carefully

Explicitly control caching for sensitive endpoints and apply restrictive CORS settings to prevent unintended data reads. Do not rely on defaults when handling authenticated responses that may include private data.

const Hapi = require('@hapi/hapi');

const server = Hapi.server({
  port: 6000,
  host: 'localhost'
});

server.route({
  method: 'GET',
  path: '/sensitive',
  options: {
    auth: false,
    cache: {
      // Explicitly disable caching or set short, private-only policies
      privacy: 'private',
      expiresIn: 1000 * 60 // 1 minute if caching is necessary
    },
    cors: {
      origin: ['https://trusted.example.com'],
      additionalHeaders: ['authorization'],
      credentials: true
    },
    handler: (request, h) => {
      return { note: 'Sensitive data should only be served to authorized, same-origin clients' };
    }
  }
});

server.start();

These remediation steps reduce the likelihood of data exposure by ensuring that credentials are not transmitted or logged in the clear, that errors do not disclose internal details, and that caching and CORS do not inadvertently expose sensitive responses.

Related CWEs: dataExposure

CWE IDNameSeverity
CWE-200Exposure of Sensitive Information HIGH
CWE-209Error Information Disclosure MEDIUM
CWE-213Exposure of Sensitive Information Due to Incompatible Policies HIGH
CWE-215Insertion of Sensitive Information Into Debugging Code MEDIUM
CWE-312Cleartext Storage of Sensitive Information HIGH
CWE-359Exposure of Private Personal Information (PII) HIGH
CWE-522Insufficiently Protected Credentials CRITICAL
CWE-532Insertion of Sensitive Information into Log File MEDIUM
CWE-538Insertion of Sensitive Information into Externally-Accessible File HIGH
CWE-540Inclusion of Sensitive Information in Source Code HIGH

Frequently Asked Questions

Does middleBrick fix data exposure findings in Hapi?
No. middleBrick detects and reports data exposure findings with severity, details, and remediation guidance. It does not fix, patch, or block issues. You must apply the recommended code and configuration changes in your Hapi service.
How often should I scan a Hapi API that uses Basic Auth?
Scan whenever you deploy changes to routes, authentication, or logging configurations. The Pro plan supports continuous monitoring on a configurable schedule so you can detect regressions in data exposure promptly.