Skip to content
Transport security Reviewed 2026-09-12

Disabled TLS certificate validation

TLS encryption is not enough if the client accepts an impostor's certificate. Certificate validation establishes whether the server presents a certificate chain trusted under the client's policy and whether the certificate matches the intended server identity. Disabling these checks can allow a network attacker to impersonate the service and read or alter traffic.

Trust boundary: a certificate is supplied by the remote endpoint. A callback that always returns success replaces authentication with acceptance of whatever that endpoint presents. Correctly signed certificates also require the appropriate hostname/identity check; trusted issuance alone is insufficient.

C#: remove the accept-all callback

These HttpClientHandler configuration fragments target modern .NET. The first bypasses server validation; the second leaves the platform's normal checks in place.

// Unsafe
var handler = new HttpClientHandler {
    ServerCertificateCustomValidationCallback = (_, _, _, _) => true
};
// Safer: keep the standard certificate validation behavior.
var handler = new HttpClientHandler();
using var client = new HttpClient(handler) {
    Timeout = TimeSpan.FromSeconds(10)
};

Use System.Net.Http and System. Production services should also follow the recommended HttpClient lifetime/factory pattern for their application. Do not retain an accept-all branch controlled by an easily misconfigured “development” flag. See the .NET certificate-validation callback reference.

JavaScript / Node.js: retain peer and hostname checks

These are options for https.request to a fixed application-owned destination; no request is made by the fragment.

// Unsafe
const options = {
  hostname: 'api.example.com', port: 443, path: '/status',
  rejectUnauthorized: false,
};
// Safer
const options = {
  hostname: 'api.example.com', port: 443, path: '/status',
  rejectUnauthorized: true,
};

Do not replace checkServerIdentity with an accept-all callback or disable verification globally through environment settings. Handle TLS errors without retrying with checks disabled. The Node TLS documentation describes trust configuration and identity checking. Default protocol/cipher policy is separate from certificate validation.

Python Requests: verify the certificate

# Unsafe
response = requests.get('https://api.example.com/status', verify=False, timeout=10)
# Safer: requests must be imported; normal verification is also the default.
response = requests.get('https://api.example.com/status', verify=True, timeout=10)
response.raise_for_status()

For a private CA, provide the approved CA bundle through the supported client configuration, such as Requests' verify='/approved/path/ca-bundle.pem', and protect that configuration from untrusted changes. A self-signed certificate is not a reason to accept every certificate. See Requests certificate verification.

Diagnose the cause instead of disabling checks

Check the destination hostname, certificate validity, intermediate chain, system time, and the client's CA store. Keep trust configuration and runtime packages maintained. Certificate pinning, if the application requires it, needs a rotation and recovery design and should not accidentally remove standard identity checks. Revocation behavior varies by platform and policy; do not assume a default client implements every possible certificate policy.

Regression test

Use a local test CA and HTTPS server. A certificate signed by that CA for the expected local hostname should succeed when the test client explicitly trusts it. An untrusted certificate, hostname mismatch, or expired certificate should fail. Assert the error path never retries with verification disabled. These tests exercise the actual client and runtime configuration; a source scan alone does not prove a live handshake is verified.

Related: Go, Ruby and PHP verification examples, cleartext protocols, and SSRF destination control.

Reference: CWE-295 — improper certificate validation.