HIGH data exposurehapijavascript

Data Exposure in Hapi (Javascript)

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

Hapi is a rich-featured web framework for Node.js, and when used with JavaScript it can inadvertently expose sensitive data through misconfigured routes, serializers, or error handling. Data Exposure in this context refers to the risk that responses return more information than intended — such as internal fields, stack traces, or sensitive payloads — enabling attackers to infer behavior, harvest PII, or prepare further attacks.

One common pattern in Hapi is attaching raw database or service objects directly to the response. Because JavaScript is dynamically typed, it is easy to pass an object containing passwords, tokens, or internal IDs without pruning or transforming it. For example, returning a user record from a database query without removing sensitive keys results in Data Exposure:

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

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

  server.route({
    method: 'GET',
    path: '/users/{id}',
    handler: async (request, h) => {
      const userId = request.params.id;
      // Vulnerable: returning full user object including password hash and internal fields
      const user = await db('users').where({ id: userId }).first();
      return user; // risk: exposes sensitive fields in the response
    }
  });

  await server.start();
};
init();

In JavaScript, it is also common to rely on automatic JSON serialization. If an object contains methods, circular references, or sensitive runtime properties, these may be serialized unless explicitly filtered. Hapi’s default JSON response behavior will include all enumerable properties, which may unintentionally surface internal state:

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

server.route({
  method: 'GET',
    path: '/profile',
    handler: (request, h) => {
      const profile = {
        username: 'alice',
        email: '[email protected]',
        _internalToken: 'abc-123',
        toJSON() {
          // If toJSON is omitted or incomplete, _internalToken may leak
          return { username: this.username, email: this.email };
        }
      };
      return profile;
    }
});

Error handling is another vector. In JavaScript, unhandled exceptions or improperly caught errors can return stack traces or environment details. Hapi’s default error responses may include stack traces in development mode, which in JavaScript are rich sources of internal paths and variable names:

server.route({
  method: 'GET',
  path: '/data',
  handler: (request, h) => {
    // If this throws, Hapi may return a detailed error in some configurations
    const a = someUndefinedFunction();
    return a;
  }
});

Additionally, JavaScript’s flexibility with object references and mutation can lead to Data Exposure when caching or logging responses. If response objects are cached or logged in their entirety, sensitive fields remain persisted in logs or intermediary stores. This is especially risky when using global or module-level variables in JavaScript to store request-scoped data.

Finally, serialization settings in Hapi’s response tools must be carefully tuned. The framework allows customizing JSON.stringify behavior; without explicitly revoking sensitive keys, you risk Data Exposure across all endpoints that rely on default serialization.

Javascript-Specific Remediation in Hapi — concrete code fixes

To mitigate Data Exposure in Hapi with JavaScript, adopt explicit response shaping, strict serialization controls, and defensive error handling. The goal is to ensure only intended data leaves the server, regardless of JavaScript’s dynamic nature.

First, explicitly pick the fields you intend to return instead of passing raw objects. Use a mapping or a dedicated transform layer to remove sensitive keys:

server.route({
  method: 'GET',
  path: '/users/{id}',
  handler: async (request, h) => {
    const userId = request.params.id;
    const user = await db('users').where({ id: userId }).first();
    // Explicitly return only safe fields
    return {
      id: user.id,
      username: user.username,
      email: user.email,
      createdAt: user.created_at
    };
  }
});

Second, define a stable toJSON method on objects that must be serialized, ensuring sensitive properties are omitted consistently across responses:

function toSafeUser(user) {
  return {
    id: user.id,
    username: user.username,
    email: user.email
    // intentionally excluding passwordHash, tokens, internalId
  };
}

server.route({
  method: 'GET',
  path: '/users/{id}',
  handler: async (request, h) => {
    const user = await db('users').where({ id: request.params.id }).first();
    return toSafeUser(user);
  }
});

Third, configure Hapi to limit error exposure. Use domain-based error mapping and avoid returning stack traces in production. In JavaScript, catch errors locally and return generic messages while logging details securely:

server.ext('onPreResponse', (request, h) => {
  const response = request.response;
  if (response.isBoom) {
    // Do not expose stack in production
    const safeResponse = {
      statusCode: response.output.statusCode,
      error: response.output.payload.error,
      message: response.output.payload.message
    };
    return h.response(safeResponse).code(response.output.statusCode);
  }
  return h.continue;
});

Fourth, freeze or deep-copy objects before using them in contexts where JavaScript’s reference semantics might cause unintended sharing. This prevents accidental mutation or leakage via cached references:

const safeData = JSON.parse(JSON.stringify(raw)); // simple deep copy for JSON-safe data
return safeData;

Finally, review all route configurations and plugins for default serialization behaviors. Combine these practices with regular scans using tools like middleBrick to validate that Data Exposure is reduced and that findings align with remediation guidance:

  • Use the middleBrick CLI to scan from terminal with middlebrick scan <url> and verify your endpoints do not leak sensitive fields.
  • Integrate the GitHub Action to add API security checks to your CI/CD pipeline, failing builds if risk scores exceed your threshold.

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

Why does JavaScript’s dynamic typing increase Data Exposure risk in Hapi?
JavaScript’s dynamic typing and permissive serialization can expose internal fields, methods, or runtime properties unless responses are explicitly shaped. Without disciplined field selection and toJSON controls, sensitive data can leak through automatic JSON serialization.
Can Hapi’s default error handling cause Data Exposure in JavaScript?
Yes. If errors are not intercepted and sanitized, Hapi may return stack traces or environment details in JavaScript. Use extension points like onPreResponse to map errors to generic messages and avoid exposing internals.