Auth Bypass in Koa with Mutual Tls
Auth Bypass in Koa with Mutual Tls — how this specific combination creates or exposes the vulnerability
Mutual Transport Layer Security (mTLS) requires both the client and the server to present valid certificates during the TLS handshake. In a Koa application, developers often rely on mTLS to provide strong authentication, assuming that a missing client certificate will cause the connection to fail before reaching application logic. This assumption can create an Auth Bypass vulnerability when the server is configured to accept connections without client certificates or when the application layer does not enforce certificate validation on every route.
Koa itself does not terminate TLS; it relies on an underlying server such as Node.js HTTPS or a reverse proxy. If the HTTPS server is set up with requestCert and rejectUnauthorized but the application does not inspect the parsed certificate fields (such as the Common Name or Subject Alternative Name) before authorizing access, an attacker can bypass authentication. For example, a request might reach Koa middleware with a valid TLS connection but without a client certificate, and if the route handler does not explicitly check for certificate presence, the request can be treated as authenticated.
Another scenario involves inconsistent validation across environments. In development or testing, a server might be configured with cert and key but without ca or requestCert, causing the runtime to accept any connection. If this configuration leaks into production or is misapplied, the mTLS boundary weakens. An attacker who can make direct HTTPS requests to the Koa server might exploit this by omitting client certificates, knowing the application logic lacks a certificate presence check.
Additionally, authorization logic that depends on claims extracted from the certificate (such as organizational unit or extended key usage) can be bypassed if the certificate is present but improperly validated. For instance, if the server only checks that a certificate exists and does not verify the certificate chain against a trusted CA, an attacker could present a self-signed or expired certificate that passes the existence check but should be rejected. This misalignment between mTLS termination and application-level authorization creates an Auth Bypass where access controls are effectively skipped.
Using middleBrick, this issue is detected during the Authentication and BOLA/IDOR checks because the scanner observes that the endpoint does not require valid client certificates for access. The report highlights the absence of certificate validation in application code and maps the finding to relevant compliance frameworks such as OWASP API Top 10 and SOC2 controls.
Mutual Tls-Specific Remediation in Koa — concrete code fixes
To secure a Koa application with mTLS, you must enforce client certificate validation at the HTTPS layer and verify certificate details in your application code. Below are concrete, working examples that demonstrate a hardened setup.
1. Enforce client certificates at the HTTPS server
Create an HTTPS server with requestCert and rejectUnauthorized set to true, and provide a trusted CA bundle to validate client certificates.
const fs = require('fs');
const https = require('https');
const Koa = require('koa');
const app = new Koa();
const server = https.createServer({
cert: fs.readFileSync('/path/to/server-cert.pem'),
key: fs.readFileSync('/path/to/server-key.pem'),
ca: fs.readFileSync('/path/to/ca-bundle.pem'),
requestCert: true,
rejectUnauthorized: true,
});
server.on('secureConnect', () => {
// At this point, the client certificate has already been validated by TLS
});
server.listen(8443, () => {
console.log('Koa mTLS server running on port 8443');
});
This configuration ensures that connections without a valid client certificate are rejected before reaching Koa middleware.
2. Validate certificate details in Koa middleware
Even with rejectUnauthorized: true, you should inspect certificate fields to enforce authorization rules. Use the request socket to access the peer certificate.
app.use(async (ctx, next) => {
const cert = ctx.sockets && ctx.sockets.remoteAddress ? // in real setups, extract from secure connection
(ctx.socket.getPeerCertificate ? ctx.socket.getPeerCertificate() : null) : null;
if (!cert || !cert.subject) {
ctx.status = 401;
ctx.body = { error: 'Client certificate required' };
return;
}
// Example: require a specific organizational unit
const ou = cert.subject.OU;
if (!ou || !ou.includes('TrustedService')) {
ctx.status = 403;
ctx.body = { error: 'Insufficient privileges' };
return;
}
// Attach identity to context for downstream handlers
ctx.state.cert = cert;
await next();
});
This middleware rejects requests missing a certificate or lacking the required organizational unit, closing the Auth Bypass path.
3. Use environment-aware configuration
Ensure your configuration consistently enforces mTLS across environments. Avoid conditional logic that disables certificate validation in non-production settings.
const isProduction = process.env.NODE_ENV === 'production';
const server = https.createServer({
cert: fs.readFileSync('/path/to/server-cert.pem'),
key: fs.readFileSync('/path/to/server-key.pem'),
ca: isProduction ? fs.readFileSync('/path/to/ca-bundle.pem') : fs.readFileSync('/path/to/ca-bundle.pem'),
requestCert: true,
rejectUnauthorized: isProduction ? true : true, // keep enforced even in dev/test
});
With these measures, mTLS in Koa provides reliable authentication and prevents Auth Bypass. middleBrick’s Authentication and BOLA/IDOR checks validate that your endpoints require and correctly validate client certificates, aligning with compliance requirements.
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 |