Back to Blog
high SEVERITY3 min read

HTTP Client `danger_accept_invalid_certs` Permitted MITM Credential

The HTTP client's `validate_certs` parameter allowed disabling TLS certificate validation through `danger_accept_invalid_certs(true)`, exposing Basic Auth credentials to interception. The fix replaces this dangerous capability with a hard error, forcing developers to use proper certificate management instead.

O
By Orbis AppSec
Published September 18, 2026Reviewed September 18, 2026

Answer Summary

The `build_http_client` function's `validate_certs` parameter in the HTTP client permitted disabling all TLS certificate validation. An attacker on the same network could intercept credentials when users connected to servers with invalid certificates. The fix replaces the `danger_accept_invalid_certs(true)` call with an error return, removing the unsafe option entirely. CWE unknown.

Vulnerability at a Glance

cweN/A
fixReplace TLS bypass with hard error, require custom CA certificates instead
riskBasic Auth credentials transmitted without certificate validation, vulnerable to MITM attacks
languageRust
root cause`validate_certs` parameter enabled `danger_accept_invalid_certs(true)` without restriction
vulnerabilityInsecure TLS Configuration / Credential Exposure

Affected Versions

Affected not applicable (first-party code)
Fixed in not applicable (first-party code) — see fix commit
Ecosystem Rust (reqwest)
CVE / GHSA not assigned
CWE unknown

The Vulnerability Explained

A critical security flaw in the HTTP client configuration allowed any caller to disable TLS certificate validation entirely. The build_http_client function accepted a validate_certs boolean parameter that, when set to false, would invoke danger_accept_invalid_certs(true) on the underlying reqwest::ClientBuilder:

if !validate_certs {
    builder = builder.danger_accept_invalid_certs(true);
}

This is precisely the wrong way to handle certificate problems in production code. The danger_accept_invalid_certs method in reqwest is explicitly documented as dangerous—it disables all certificate validation, including hostname verification and trust chain checking. When combined with Basic Auth credentials, this creates a perfect storm: authentication secrets travel over connections that could be intercepted by any attacker positioned between the client and server.

The attack scenario is straightforward. A developer or automated system sets validate_certs to false to work around a certificate issue—perhaps a self-signed certificate in a staging environment, or an expired certificate on a legacy server. An attacker on the same network segment (public WiFi, compromised router, malicious hotspot, or ARP-spoofed LAN) presents a fake certificate for the target hostname. Without validation, the client accepts this certificate and establishes a TLS connection to the attacker. The attacker decrypts the traffic, extracts the Basic Auth credentials, then forwards the request to the real server—completely invisible to both parties.

The reqwest documentation warns that this setting "is highly discouraged and should only be used for debugging purposes." Yet the API made it available as a simple boolean toggle, with no audit trail, no warning, and no alternative path for legitimate certificate customization.

The Fix

The fix removes the dangerous escape hatch entirely. Instead of silently disabling security, the code now returns an error with clear guidance:

if !validate_certs {
    return Err(
        "Disabling TLS certificate validation is not permitted because it exposes credentials to man-in-the-middle attacks. Use a custom CA certificate instead.".to_string(),
    );
}

This change preserves all legitimate use cases through the existing use_custom_ca_certificate path, which properly validates certificates against a custom trust anchor rather than accepting any certificate whatsoever. The error message explicitly names the security risk and points developers toward the correct solution.

The before/after comparison reveals the shift in security posture:

Before After
Silent security downgrade Explicit failure with explanation
MITM vulnerability Credential protection
No alternative provided Directed to custom_ca_certificate_path

Key Takeaways

  • Never expose danger_accept_invalid_certs through a boolean parameter—the convenience of a quick toggle becomes the path of least resistance, and developers will use it in production without understanding the consequences.

  • Certificate problems have certificate solutions—self-signed certificates belong in a custom CA store, not in a bypassed validation path. The custom_ca_certificate_path option provides the flexibility without the exposure.

  • Error messages are security controls—the new error doesn't just stop dangerous behavior; it educates the developer about why the behavior is dangerous and what to do instead.

  • API design is threat modeling—the original design assumed that callers would responsibly use validate_certs. The fix assumes that dangerous capabilities will be misused, and removes them.

How Orbis AppSec Detected This

Source: The validate_certs parameter passed to build_http_client

Sink: reqwest::ClientBuilder.danger_accept_invalid_certs(true) invoked when certificate validation is disabled

Missing control: No restriction on when TLS validation could be disabled; no requirement for custom CA certificates as an alternative

CWE: unknown

Fix: Replace the dangerous TLS bypass with a hard error that directs developers toward proper certificate management

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

The validate_certs parameter was a foot-gun: an easy-to-use option that destroyed the security guarantees of TLS. The fix recognizes that developers facing certificate errors need guidance toward proper solutions, not an escape hatch that exposes credentials. By converting the silent vulnerability into an explicit error with actionable advice, the code now protects users while still supporting legitimate certificate customization through the custom_ca_certificate_path mechanism.

Prevention and further reading

Frequently Asked Questions

Does the `validate_certs` parameter still exist after the fix, and what happens when it's set to false?

The parameter still exists, but when `validate_certs` is false, the function now returns an error instead of disabling TLS validation. The error message directs developers to use custom CA certificates.

Is there any legitimate use case still supported for connecting to servers with non-standard certificates?

Yes. The `use_custom_ca_certificate` option with `custom_ca_certificate_path` remains fully functional. This provides the same flexibility without exposing credentials to man-in-the-middle attacks.

What Rust crate provides the `danger_accept_invalid_certs` method that was being misused here?

The `reqwest` HTTP client crate provides this method. It's intended for testing only and is explicitly marked as dangerous in the API documentation.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #11

Related Articles

critical

JWT Authentication Disabled Signature Validation in

A critical misconfiguration in JWT authentication explicitly disabled signature validation, allowing attackers to forge valid tokens with arbitrary claims and bypass authentication entirely. The fix re-enables signature validation on all incoming bearer tokens, restoring the security boundary of the authentication layer.

critical

`requests.get()`/`delete()`/`post()` with `verify=False` in Release

A critical security vulnerability in a release automation script disabled SSL certificate verification on every HTTPS request to GitHub's API. By passing `verify=False` to `requests.get()`, `requests.delete()`, and `requests.post()`, the script exposed OAuth tokens and release binaries to man-in-the-middle attacks on any network the script ran from.

critical

ExternalHttpClient::request() Sent Basic Auth Over Plain HTTP

The `ExternalHttpClient::request()` helper accepted a `$basicAuth` string and passed it straight to the HTTP client's `auth` option without checking that the target URL used `https://`. Any external JSON data source configured with an `http://` endpoint therefore shipped a base64-encoded `Authorization: Basic` header in cleartext on every scheduled load. The fix rejects the request outright — before a client is even created — when the URL scheme is not HTTPS.

critical

How insufficient PBKDF2 iterations happen in JavaScript and how to fix it

A critical vulnerability in `libs/wgs/pbkdf2.js` used only 1 iteration for PBKDF2 password hashing, making passwords trivially crackable. The fix increases iterations to 600,000, aligning with OWASP 2023 recommendations and preventing GPU-accelerated brute-force attacks.

critical

How Hardcoded Encryption Salts Compromise Credential Storage in Node.js and How to Fix It

A critical vulnerability in `scripts/bench-cpu.js` used a hardcoded static salt (`'byok-relay-salt'`) when deriving encryption keys with scrypt, allowing attackers to decrypt all encrypted credentials if the encryption secret was compromised. The fix replaces the hardcoded salt with cryptographically secure random bytes generated per operation, ensuring each user's encrypted credentials require a unique derived key.

high

SHACL Viewer Path Traversal in graph3d(): Unvalidated `path`

The `graph3d()` and `graph2d()` request handlers in SHACL Viewer directly concatenated user-supplied `path` parameters into filesystem paths, enabling directory traversal outside the intended `/shapes/` directory. The fix introduces `_resolve_shapes_path()` with `os.path.realpath()` validation to enforce containment within the shapes directory.