Disabled TLS certificate validation

Disabled TLS certificate validation

Description

Disabling server certificate validation, for example with rejectUnauthorized: false or NODE_TLS_REJECT_UNAUTHORIZED=0, prevents a TLS client from reliably authenticating the server. An attacker on the network path may present an untrusted certificate and impersonate the intended server. Interception through a hostile proxy, gateway, or public network may expose sensitive data or allow response manipulation and session theft.

Potential impact

  • A man-in-the-middle attacker may establish a connection using a fake certificate.
  • Credentials, tokens, or personal information may be exposed to an impersonating server. TLS encryption itself is not removed.
  • The attacker may modify responses or insert malicious payloads.
  • Users or applications may communicate with an attacker while believing it is the legitimate service.

Remediation

  • Remove rejectUnauthorized or retain its default true value.
  • Do not set process.env.NODE_TLS_REJECT_UNAUTHORIZED=0 to disable validation globally.
  • Supply trusted private or public CA certificates through ca in https.Agent or tls.connect.
  • Keep hostname verification enabled. tls.connect does not enable SNI automatically; set servername alongside host when the server requires it.
  • If pinning is required, compare with a trusted certificate or public key and plan for certificate changes. The fingerprint256 example below compares the entire certificate's SHA-256 fingerprint, not its public key.
  • Isolate any temporary test-only exception from production configuration and builds.

Examples

Before

javascript
// Before, example 1: disable certificate validation globally
const https = require('https');
const tls = require('tls');

function fetchInsecure() {
  // Disabling TLS validation globally is dangerous
  process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

  https.get({ hostname: 'api.example.org', path: '/v1/data' }, (res) => {
    res.on('data', () => {});
  });
}

// Before, example 2: disable certificate validation in an agent
function postInsecure() {
  const insecureAgent = new https.Agent({ keepAlive: true, rejectUnauthorized: false });

  const req = https.request({
    hostname: 'secure.example.org',
    method: 'POST',
    path: '/login',
    agent: insecureAgent,
    headers: { 'Content-Type': 'application/json' }
  }, (res) => res.resume());

  req.write(JSON.stringify({ user: 'alice', pass: 'secret' }));
  req.end();
}

After

javascript
// After: retain default validation and use a trusted CA bundle
const https = require('https');
const fs = require('fs');

// Example path to a private or public CA bundle
const caBundle = fs.readFileSync('/etc/ssl/certs/company-ca-bundle.pem');

function fetchSecure() {
  // rejectUnauthorized defaults to true
  const secureAgent = new https.Agent({
    keepAlive: true,
    ca: caBundle,           // Supply trusted CAs
    // https derives servername from the request host; do not disable it
  });

  https.get({
    hostname: 'api.example.org',
    path: '/v1/data',
    agent: secureAgent
  }, (res) => {
    let body = '';
    res.on('data', (c) => body += c);
    res.on('end', () => console.log('OK:', body.length));
  });
}

// Optional: certificate pinning using the certificate SHA-256 fingerprint
const tls = require('tls');
function connectWithPinning(expectedFingerprint256) {
  const socket = tls.connect({ host: 'secure.example.org', port: 443, ca: caBundle }, () => {
    const cert = socket.getPeerCertificate(true);
    if (!cert || !cert.fingerprint256 || cert.fingerprint256 !== expectedFingerprint256) {
      socket.destroy(new Error('Certificate pinning mismatch'));
      return;
    }
    socket.write('GET / HTTP/1.1\r\nHost: secure.example.org\r\n\r\n');
  });
}

Explanation:

  • Before: rejectUnauthorized: false or NODE_TLS_REJECT_UNAUTHORIZED=0 bypasses certificate and hostname validation failures, allowing an attacker with a fake certificate to impersonate the server.
  • After: Default validation (rejectUnauthorized: true) and a trusted CA bundle authenticate the server. Optional pinning adds another identity check. Also verify CA trust, hostname validation, and behavior during certificate changes in production.

References