Disabling TLS certificate validation (rejectUnauthorized: false) makes every outbound HTTPS connection trivially man-in-the-middle-able. CWE-295 (Improper Certificate Validation) is the classification, and it's particularly dangerous for payment processor integrations, OAuth token exchanges, and inter-service calls where data sensitivity is highest. OWASP A02 2021 (Cryptographic Failures) and API Security Top 10 2023 API8 cover TLS misuse. Developers add rejectUnauthorized: false to work around local cert issues and commit it to production — a search across GitHub shows this pattern in thousands of repositories. An attacker on the same network path can intercept the full request and response, including auth tokens and payment data.
Info severity because exploiting disabled TLS validation requires network-path access, but the consequence — full MITM interception of sensitive API calls — is critical.
Remove every rejectUnauthorized: false from production code. For local development with self-signed certificates, set the flag conditionally on NODE_ENV and never commit the unconditional override.
// Bad — never do this in production
const agent = new https.Agent({ rejectUnauthorized: false })
const res = await fetch('https://api.stripe.com/v1/charges', { agent })
// Good — explicit validation (this is also the default, no option needed)
const res = await fetch('https://api.stripe.com/v1/charges')
// Acceptable for local dev only — gated on environment
const agent = new https.Agent({
rejectUnauthorized: process.env.NODE_ENV !== 'development'
})
For internal services with private CAs, provide the CA certificate explicitly rather than disabling validation: new https.Agent({ ca: fs.readFileSync('internal-ca.pem') }).
ID: api-security.design-security.tls-validation
Severity: info
What to look for: Enumerate every relevant item. Check how the application makes outbound HTTPS requests (to payment processors, external APIs, webhooks). Verify that TLS certificate validation is enabled (not disabled with rejectUnauthorized: false).
Pass criteria: All outbound HTTPS requests validate TLS certificates. Certificate validation is not disabled. Critical integrations use certificate pinning.
Fail criteria: Outbound HTTPS requests disable certificate validation (rejectUnauthorized: false in Node.js), or do not validate certificates.
Skip (N/A) when: The application makes no outbound HTTPS requests.
Detail on fail: "Outbound HTTPS requests have certificate validation disabled (rejectUnauthorized: false)" or "Stripe integration disables TLS validation — vulnerable to MITM attacks"
Remediation: Enable TLS validation:
// Bad: Disabled validation
https.request(url, { rejectUnauthorized: false }, callback)
// Good: Default (validates by default)
https.request(url, callback)
// Good: Explicit validation
https.request(url, { rejectUnauthorized: true }, callback)
// For critical integrations, use certificate pinning
const https = require('https')
const fs = require('fs')
const agent = new https.Agent({
ca: fs.readFileSync('ca-cert.pem'),
cert: fs.readFileSync('client-cert.pem'),
key: fs.readFileSync('client-key.pem')
})
https.request(url, { agent }, callback)