HIGH dangling dnshapijavascript

Dangling Dns in Hapi (Javascript)

Dangling DNS in Hapi with JavaScript — How This Combination Exposes the Vulnerability

Dangling DNS occurs when a subdomain's DNS record (such as a CNAME) points to a domain or service that no longer exists or is deprovisioned, but the application still accepts traffic for that hostname. In a Hapi.js server, this can lead to serious security risks if the server does not validate the Host header against a strict allowlist of expected domains. An attacker can exploit a dangling DNS pointer to point a subdomain to an IP they control, then send requests with a forged Host header matching the dangling subdomain. If the Hapi server routes based on the Host without validation, it may process the request as if it originated from a trusted domain, potentially bypassing authentication, enabling SSRF, or facilitating cache poisoning attacks.

For example, consider a Hapi.js API that uses subdomain routing for tenant isolation: tenant1.api.example.com, tenant2.api.example.com. If the DNS record for tenant1.api.example.com is a CNAME pointing to a deprecated service (e.g., an old Azure App Service) that has been deleted, an attacker can claim that Azure subdomain and configure it to point to their own server. When they send a request to the Hapi server with Host: tenant1.api.example.com, the server may process it as tenant1’s traffic, especially if routing relies solely on the Host header. This could allow unauthorized access to tenant-specific data or execution of privileged operations.

Hapi.js does not automatically validate the Host header by default. While it uses the header for virtual hosting and routing, developers must explicitly enforce hostname validation. Failure to do so means the server trusts any Host header value that matches a route, regardless of DNS legitimacy. This is particularly dangerous in cloud environments where DNS records are frequently created and destroyed, increasing the likelihood of dangling pointers going unnoticed.

JavaScript-Specific Remediation in Hapi — Concrete Code Fixes

To mitigate dangling DNS risks in a Hapi.js application, implement strict Host header validation at the server level. This ensures the server only processes requests for domains you explicitly control and expect. The validation should occur early in the request lifecycle, ideally in a server extension point, so invalid hosts are rejected before routing or authentication logic runs.

Use Hapi’s ext('onPreAuth') extension point to validate the Host header against an allowlist of approved hostnames. This approach is framework-appropriate, leverages Hapi’s plugin system, and avoids modifying route logic. The allowlist should include all legitimate domains and subdomains your API serves, excluding any that rely on third-party or ephemeral services prone to deprovisioning.

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

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

  // Define allowlist of expected hostnames
  const allowedHosts = [
    'api.example.com',
    'tenant1.api.example.com',
    'tenant2.api.example.com',
    'api.staging.example.com'
  ];

  // Validate Host header early in request lifecycle
  server.ext('onPreAuth', (request, h) => {
    const host = request.headers.host;
    if (!host || !allowedHosts.includes(host)) {
      return h.response({ error: 'Invalid host header' }).code(400);
    }
    return h.continue;
  });

  // Example route
  server.route({
    method: 'GET',
    path: '/',
    handler: (request, h) => {
      return { status: 'ok', tenant: request.headers.host };
    }
  });

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

init().catch(err => {
  console.error(err);
  process.exit(1);
});

This code rejects any request with a Host header not in the allowedHosts array, returning a 400 Bad Request. It prevents attackers from exploiting dangling DNS by ensuring the server only responds to hostnames you explicitly authorize. For dynamic environments, consider updating the allowlist via automated DNS checks or infrastructure-as-code synchronization, but never rely on DNS alone for trust decisions.

Additionally, disable Hapi’s automatic virtual hosting based on Host header if not needed, though explicit validation as shown above is sufficient and clearer in intent. Always combine this with other defenses: enforce strict TLS validation, use CDN or WAF policies to restrict hostnames at the edge, and monitor DNS records for dangling pointers using external tools. However, remember that middleBrick does not fix or block vulnerabilities — it detects and reports them. The remediation above is the developer’s responsibility to implement in their Hapi.js application.

Frequently Asked Questions

Does Hapi.js automatically protect against dangling DNS attacks?
No, Hapi.js does not automatically validate the Host header against an allowlist. By default, it processes requests based on the Host header for routing and virtual hosting without verifying whether the hostname corresponds to a legitimate, controlled domain. Developers must implement explicit Host header validation using server extension points or route-level checks to mitigate dangling DNS risks.
Can I use environment variables to manage the allowed hosts list in Hapi.js for different deployment stages?
Yes, you can define the allowed hosts list using environment variables (e.g., process.env.ALLOWED_HOSTS) and parse it at startup. This allows you to maintain separate lists for development, staging, and production without changing code. Ensure the variable is split into an array (e.g., process.env.ALLOWED_HOSTS.split(',')) and trimmed to avoid whitespace issues. Never include wildcard entries like *.example.com in security-sensitive contexts unless absolutely necessary and paired with additional validation.