HIGH data exposurehapi

Data Exposure in Hapi

How Data Exposure Manifests in Hapi

Data exposure in Hapi applications often stems from improper response filtering and inadequate validation of what data gets sent to clients. Unlike traditional web applications, Hapi's plugin architecture and response toolkit can inadvertently expose sensitive information through several mechanisms.

The most common vulnerability occurs when developers use h.response() with entire objects or database models without explicitly defining the response schema. Consider this problematic pattern:

const getUser = async (request, h) => {
  const user = await User.findById(request.params.id);
  return h.response(user); // Exposes password hash, internal IDs, etc.
};

Hapi's default behavior doesn't automatically sanitize responses, meaning any field present in the returned object becomes part of the API response. This includes password hashes, API keys, internal database IDs, and other sensitive metadata that should never leave the server.

Another Hapi-specific exposure vector involves plugin configuration. When using plugins like hapi-auth-jwt2 or hapi-auth-basic, improper error handling can leak authentication details:

server.auth.strategy('jwt', 'jwt', {
  key: process.env.JWT_SECRET,
  validate: async (decoded, request) => {
    return { isValid: true }; // No error handling for invalid tokens
  }
});

Without proper validation error responses, attackers can enumerate valid tokens by observing response differences. Hapi's flexible response system means that authentication failures might return different status codes or error messages that reveal system details.

Response toolkit misuse creates another exposure channel. Developers sometimes use h.state() or h.header() to pass internal debugging information to clients:

const debugEndpoint = (request, h) => {
  const debugInfo = {
    query: request.query,
    payload: request.payload,
    auth: request.auth,
    internalState: someInternalObject
  };
  return h.response(debugInfo);
};

This pattern, often left in production code, exposes the complete request context and any internal state objects to anyone who can access the endpoint.

Hapi-Specific Detection

Detecting data exposure in Hapi requires examining both the route definitions and the actual response patterns. middleBrick's scanning approach for Hapi applications focuses on runtime behavior rather than static analysis, which is particularly effective for dynamic JavaScript applications.

The scanner tests for data exposure by making requests to Hapi endpoints and analyzing the responses for sensitive information patterns. For authentication-related endpoints, middleBrick looks for:

  • Password hashes or bcrypt strings in responses
  • API keys, JWT secrets, or encryption keys
  • Internal database identifiers beyond simple numeric IDs
  • Stack traces or error messages containing system details
  • Database connection strings or configuration objects
  • Session tokens or authentication cookies in JSON responses

For Hapi's plugin ecosystem, middleBrick specifically tests plugin configuration exposure. Many Hapi applications use plugins that might inadvertently expose configuration through error responses or debug endpoints. The scanner checks for:

// What middleBrick tests for in Hapi plugin responses
const sensitivePatterns = [
  /password.*hash/i,
  /api[_-]?key/i,
  /jwt[_-]?secret/i,
  /private[_-]?key/i,
  /connection[_-]?string/i,
  /mongodb://.*@.*//i
];

middleBrick's OpenAPI analysis is particularly valuable for Hapi applications since many Hapi developers use hapi-swagger or similar plugins to generate API documentation. The scanner cross-references the OpenAPI spec with actual runtime responses to identify discrepancies where the documented response doesn't match the actual sensitive data being returned.

The CLI tool makes Hapi-specific scanning straightforward:

npm install -g middlebrick
middlebrick scan https://api.yourservice.com/user/123 --format=json

For CI/CD integration, the GitHub Action can be configured to scan Hapi endpoints before deployment:

- name: Scan Hapi API Security
  uses: middlebrick/middlebrick-action@v1
  with:
    url: https://staging.yourservice.com
    fail-below: B

Hapi-Specific Remediation

Remediating data exposure in Hapi requires a defense-in-depth approach using Hapi's built-in features and careful response handling. The most effective strategy combines response validation, plugin configuration hardening, and proper error handling.

For response sanitization, Hapi's response.schema validation should be used consistently:

const userResponseSchema = Joi.object({
  id: Joi.string().required(),
  username: Joi.string().required(),
  email: Joi.string().email().required(),
  createdAt: Joi.date().required()
});

const routes = [
  {
    method: 'GET',
    path: '/users/{id}',
    options: {
      response: {
        schema: userResponseSchema
      }
    },
    handler: async (request, h) => {
      const user = await User.findById(request.params.id);
      return h.response(user).type('application/json');
    }
  }
];

This ensures that even if the database model contains sensitive fields, only the explicitly defined schema gets returned to clients.

For authentication plugin hardening, implement proper error handling and validation:

server.auth.strategy('jwt', 'jwt', {
  key: process.env.JWT_SECRET,
  validate: async (decoded, request) => {
    try {
      const user = await User.findById(decoded.sub);
      if (!user) {
        return { isValid: false };
      }
      return { isValid: true, credentials: { user } };
    } catch (err) {
      return { isValid: false };
    }
  },
  responseSchema: {
    response: Joi.object({
      message: Joi.string().required()
    })
  }
});

Hapi's response toolkit provides methods for safe response construction. Always use h.response().type() to explicitly set content types and avoid automatic serialization of unexpected objects:

const safeResponse = (data, h) => {
  const sanitized = {
    id: data.id,
    name: data.name,
    email: data.email
  };
  return h.response(sanitized)
    .type('application/json')
    .header('X-Content-Type-Options', 'nosniff');
};

For plugin configuration exposure, use environment variables and never log sensitive configuration:

const init = async () => {
  const server = Hapi.server({
    port: process.env.PORT || 3000,
    host: process.env.HOST || 'localhost'
  });

  // Never log secrets
  server.ext('onRequest', (request, h) => {
    if (process.env.NODE_ENV === 'development') {
      console.log(`Request: ${request.path}`);
    }
    return h.continue;
  });

  return server;
};

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

How does middleBrick detect data exposure in Hapi applications?
middleBrick performs black-box scanning by making actual requests to your Hapi endpoints and analyzing the responses. It looks for patterns like password hashes, API keys, internal IDs, and other sensitive information in the JSON responses. The scanner also tests authentication endpoints for information leakage through error responses and examines OpenAPI specs for discrepancies between documented and actual responses.
Can middleBrick scan Hapi applications that use authentication?
Yes, middleBrick can scan authenticated Hapi endpoints. You can provide authentication headers, cookies, or JWT tokens as part of the scan configuration. The scanner will use these credentials to access protected routes and test for data exposure in authenticated contexts, which is often where the most sensitive data is accessible.