Vulnerable Components in Adonisjs with Mutual Tls
Vulnerable Components in Adonisjs with Mutual Tls
Mutual Transport Layer Security (mTLS) in AdonisJS involves both the server requesting and validating a client certificate, and the client presenting a certificate trusted by the server. When this setup is misconfigured or combined with framework-specific behaviors, it can expose components that undermine the intended assurance. Vulnerable components often arise at the intersection of AdonisJS request lifecycle, TLS configuration, and certificate validation logic.
One common pattern is binding the HTTPS server with an AdonisJS provider while also configuring the TLS options in start/server.js. If the server is configured to request client certificates (requestCert: true) but does not enforce strict verification, an attacker can present an unsigned or self‑signed certificate that the server may accept depending on the underlying Node.js TLS defaults. This misconfiguration maps to authentication weaknesses covered by the Authentication check and can allow unauthenticated access to routes that should require mTLS.
A second vulnerable component is the handling of certificate contents within application code. AdonisJS does not inherently parse client certificate fields; developers often extract values such as Common Name (CN) or Subject Alternative Name (SAN) from the request socket. If these values are used directly for authorization or binding to application identities without validation, this can lead to Insecure Direct Object References (IDOR) or Broken Access Control issues, aligning with the BOLA/IDOR check. For example, using request.socket.getPeerCertificate() and then performing logic like if (cert.subject.CN === username) grantAccess() is risky if the certificate is not also validated against a trusted store and its claims verified.
A third vulnerable component is the configuration of the TLS context options themselves. Node.js TLS servers support numerous options, and some have subtle interactions. For instance, setting rejectUnauthorized: false at the server level will cause the server to accept untrusted certificates, effectively disabling mTLS enforcement even when certificate presentation is requested. This can interact poorly with AdonisJS middleware that assumes authenticated TLS sessions, leading to inconsistent security boundaries. Similarly, weak protocol selections (e.g., allowing TLS 1.0 or 1.1) or ciphers can expose the endpoint to downgrade attacks, relevant to the Encryption and Input Validation checks.
Finally, the interplay with OpenAPI/Swagger spec analysis can highlight mismatches between documented TLS expectations and runtime behavior. If the spec indicates mTLS is required but the server implementation does not enforce certificate validation, runtime findings will flag this as a discrepancy between spec and execution. This is especially important when using $ref-heavy specs where definitions must be resolved correctly to ensure the documented security schemes align with actual server configuration in AdonisJS.
Mutual Tls-Specific Remediation in Adonisjs
Remediation focuses on strict server-side enforcement, careful handling of certificate data, and alignment with framework configuration. Begin by ensuring the HTTPS server is configured to require and validate client certificates. Use a trusted CA to sign client certificates and validate them explicitly in your server setup.
const { Application } = require('@adonisjs/fold')
const https = require('https')
const fs = require('fs')
const server = https.createServer({
key: fs.readFileSync('path/to/server-key.pem'),
cert: fs.readFileSync('path/to/server-cert.pem'),
ca: fs.readFileSync('path/to/ca-cert.pem'),
requestCert: true,
rejectUnauthorized: true
}, (req, res) => {
const cert = req.socket.getPeerCertificate()
if (!cert || Object.keys(cert).length === 0) {
res.statusCode = 400
res.end('Client certificate required')
return
}
// Validate certificate fields against your identity provider
const fingerprint = cert.fingerprint
// Lookup and bind to application user, then proceed
res.end('OK')
})
server.listen(443)
In AdonisJS, you can encapsulate this logic within a custom provider or use an HTTPS hook while ensuring rejectUnauthorized: true is set to prevent acceptance of untrusted certificates. Avoid using rejectUnauthorized: false in production, as this nullifies the assurance provided by mTLS.
When extracting identity from the certificate, perform additional validation rather than relying on CN alone. Compare the certificate fingerprint or a mapped claim against a registry of authorized clients. Combine this with AdonisJS middleware to protect routes:
class MTLSAuthMiddleware {
async handle ({ request, response, connection }, next) {
const cert = request.socket.getPeerCertificate()
if (!cert || Object.keys(cert).length === 0) {
return response.status(401).send('mTLS required')
}
const allowedFingerprints = new Set(['AA:BB:CC:...'])
if (!allowedFingerprints.has(cert.fingerprint)) {
return response.status(403).send('Certificate not authorized')
}
// Attach identity to request for downstream use
request.authCert = cert
await next()
}
}
module.exports = MTLAuthMiddleware
Ensure your TLS options do not inadvertently weaken security. Prefer modern ciphers and protocols, and keep your CA bundle up to date. Regularly rotate server and client certificates and monitor for revoked certificates. These steps reduce risk across the Authentication, Encryption, and Input Validation checks by ensuring only properly authorized and properly formed certificates are accepted.
Leverage the middleBrick CLI to validate your configuration by scanning your endpoint:
middlebrick scan https://api.example.com
Use the GitHub Action to enforce mTLS expectations in CI/CD, failing builds if runtime findings indicate missing or misconfigured certificate validation.