Auth Bypass in Hapi with Basic Auth
Auth Bypass in Hapi with Basic Auth — how this specific combination creates or exposes the vulnerability
Hapi is a rich framework for building HTTP services in Node.js, and it supports HTTP Basic Auth through its built-in auth scheme API. When Basic Auth is used without strict route configuration or proper validation, it can lead to an authentication bypass, enabling unauthenticated access to protected endpoints. This occurs when route options do not explicitly require authentication, when the auth scope or entity checks are omitted, or when credentials are accepted from multiple sources without strict enforcement.
In a black-box scan, middleBrick tests unauthenticated access to routes that should require credentials. If a route configured with auth: { strategy: 'basic' } does not enforce access: { scope: [...], entity: 'user' } consistently, the scan can reach protected resources without credentials. For example, consider a Hapi server that defines a basic auth strategy but attaches it to the server without requiring it on every route:
const Hapi = require('@hapi/hapi');
const bcrypt = require('@hapi/bcrypt');
const validate = async (request, username, password) => {
const users = {
alice: await bcrypt.hash('secret123', 10)
};
const hashed = users[username];
if (!hashed) return { credentials: null, isValid: false };
const isValid = await bcrypt.compare(password, hashed);
return { credentials: { username }, isValid };
};
const init = async () => {
const server = Hapi.server({ port: 4000 });
server.auth.strategy('basic', 'basic', {
validate: validate
});
// This route explicitly requires auth
server.route({
method: 'GET',
path: '/admin',
options: {
auth: 'basic'
},
handler: (request, h) => ({ admin: true })
});
// This route has no auth option — vulnerable to bypass
server.route({
method: 'GET',
path: '/health',
handler: () => ({ status: 'ok' })
});
await server.start();
};
init();
In this example, /health has no auth option. An authenticated session on /admin does not imply protection is applied consistently. A missing or misconfigured auth key can allow unauthenticated requests to reach endpoints that should be restricted. Hapi’s route-level auth configuration means the framework does not automatically enforce authentication across all routes, which can lead to accidental exposure if developers assume server-level or strategy registration implies global enforcement.
Additionally, scope and entity checks can be omitted. Even when auth is present, missing access restrictions can allow broader access than intended:
server.route({
method: 'GET',
path: '/users/{id}',
options: {
auth: 'basic',
handler: (request, h) => ({ user: request.auth.credentials.username })
}
});
Without explicit access: { scope: ['profile'] } and entity: 'user', the route may accept any authenticated credential, enabling horizontal privilege issues. In practice, this means an attacker who obtains one valid set of Basic Auth credentials might access other users’ data if scoping is not enforced. middleBrick detects such missing or incomplete authorization constraints by correlating spec definitions (OpenAPI) with runtime behavior, highlighting routes where authentication is present but authorization is weak or absent.
Another bypass vector involves accepting credentials via headers while also allowing query or body parameters to override authentication. If route or server configurations permit authentication via multiple mechanisms without strict precedence, an attacker can supply credentials in a less-guarded channel. middleBrick’s unauthenticated scan tests whether protected routes can be reached without any credentials and whether multiple auth inputs can weaken enforcement, surfacing these gaps as high-severity findings.
Basic Auth-Specific Remediation in Hapi — concrete code fixes
To prevent auth bypass in Hapi with Basic Auth, explicitly enforce authentication on every protected route, define strict scope and entity requirements, and avoid ambiguous fallback mechanisms. The following patterns demonstrate secure configurations.
1) Always specify auth on protected routes and avoid omitting it:
server.route({
method: 'GET',
path: '/admin',
options: {
auth: 'basic',
handler: (request, h) => ({ admin: true })
}
});
2) Use access scopes and entity to restrict what authenticated principals can do:
server.route({
method: 'GET',
path: '/users/{id}',
options: {
auth: 'basic',
access: { scope: ['profile', 'email'] },
handler: (request, h) => ({ user: request.auth.credentials.username })
}
});
3) Define a server-wide auth default carefully. If you set a default, ensure it does not unintentionally protect public routes:
server.route({
method: 'GET',
path: '/public',
options: {
auth: false, // explicitly opt out
handler: () => ({ public: true })
}
});
4) Validate and scope credentials rigorously in your validate function. Do not accept incomplete or unsigned credentials:
const validate = async (request, username, password) => {
const users = {
alice: await bcrypt.hash('secret123', 10)
};
const hashed = users[username];
if (!hashed) return { credentials: null, isValid: false };
const isValid = await bcrypt.compare(password, hashed);
if (!isValid) return { credentials: null, isValid: false };
return {
credentials: { username, scope: ['profile'] },
isValid: true
};
};
5) Avoid mixing authentication mechanisms without clear precedence. If you only intend Basic Auth, do not enable additional schemes or passive challenges that could be leveraged to bypass checks.
middleBrick’s scans include checks aligned with frameworks like OWASP API Top 10 to highlight missing authentication enforcement and weak authorization scoping. For teams seeking deeper visibility, the Pro plan adds continuous monitoring so configuration changes can be tracked over time, and the GitHub Action can fail builds if a risk score drops below your defined threshold, helping prevent regressions in CI/CD pipelines.
Related CWEs: authentication
| CWE ID | Name | Severity |
|---|---|---|
| CWE-287 | Improper Authentication | CRITICAL |
| CWE-306 | Missing Authentication for Critical Function | CRITICAL |
| CWE-307 | Brute Force | HIGH |
| CWE-308 | Single-Factor Authentication | MEDIUM |
| CWE-309 | Use of Password System for Primary Authentication | MEDIUM |
| CWE-347 | Improper Verification of Cryptographic Signature | HIGH |
| CWE-384 | Session Fixation | HIGH |
| CWE-521 | Weak Password Requirements | MEDIUM |
| CWE-613 | Insufficient Session Expiration | MEDIUM |
| CWE-640 | Weak Password Recovery | HIGH |