This is the companion to our hardcoded signing keys piece, and it is the other half of the same disease. That post was about hardcoded secrets: a key shipped in the artifact that anyone can read. This one is about hardcoded trust settings: a security decision shipped in the artifact that nobody can change. The first hands the attacker a credential directly. The second tears down the wall that was supposed to keep credentials from being intercepted in transit. Both are properties of what shipped, not behaviors of the running service, and both hide from the scanners most teams rely on.
The relevant weakness is CWE-295 (Improper Certificate Validation): the product does not validate, or incorrectly validates, the certificate presented by the host it connects to. When a TLS client skips that check, the encryption is still there, but the authentication is gone. You have a private channel to whoever answered, and you have no idea who answered. That is precisely the gap a man-in-the-middle needs. Verifiable security.
The class in one paragraph
TLS does two jobs at once. It encrypts the channel, and it authenticates the peer by validating the certificate the peer presents against a trusted chain and the expected hostname. Disable the second job and the first becomes theater. A client that connects with InsecureSkipVerify: true, verify=False, a custom trust-everything callback, or any equivalent will happily complete a handshake with an attacker who terminates the connection in the middle, presents any certificate at all, and forwards the traffic onward. The encryption protects the attacker's interception as faithfully as it would have protected the real endpoint. When the client then sends credentials over that channel, as a management agent must in order to log in to what it manages, the attacker reads them in cleartext on their side of the proxy. The defining property is that the insecure choice is baked into the agent. The operator cannot harden it, because the validation was never wired to a setting. It is hardcoded off.
CVE-2026-53475 is the textbook instance. The affected component is an assisted-migration agent in a Kubernetes virtualization migration toolchain, the kind of agent an operator installs to inventory and move virtual machines out of a vSphere estate. To do that work it authenticates to vCenter, the management plane of the entire virtual environment. The agent hardcodes an insecure TLS connection to vCenter: certificate validation is disabled in code rather than gated behind a flag the operator controls. An attacker with a position on the network path between the agent and vCenter, an adjacent-network attacker rather than a remote one, intercepts the TLS session and obtains the vCenter administrator credentials the agent transmits. With vCenter administrator credentials, the attacker controls every host, every virtual machine, every datastore, and every snapshot in the estate. The blast radius is the whole virtual environment.
Why this hides from your scanners
The reason hardcoded insecure TLS persists is that the controls most teams rely on are structurally blind to it.
- Version and CVE-by-banner scanning miss it. The agent is running the exact version it claims to be. Nothing about the version string reveals that one connection inside the agent skips certificate validation. Two installs of the identical build behave identically, because the insecure choice is not a deployment option, it is the only behavior. A version match cannot surface a flaw that is uniform across every copy of that version.
- Runtime DAST sees an agent that works. A dynamic scanner watches the agent connect to vCenter, complete a TLS handshake, authenticate, and do its job. From the outside it is a healthy encrypted session. The scanner has no privileged view of whether the client validated the server certificate, and in the common case where nobody is actively intercepting at scan time, there is simply nothing anomalous to observe. The vulnerability is a missing check, and a missing check produces no signal until someone exploits it.
- The insecure line is in code nobody re-reads. A single TLS client option set during early development, when the test vCenter used a self-signed certificate and disabling validation was the quick way to make the integration work, survives into the shipped product. The comment that said fix before release is gone. The reviewer who would have caught it saw a working migration and approved it. The setting is one boolean in one client constructor, buried in an agent that does a hundred other things.
Detecting this class requires inspecting the agent's configuration and connection code, not probing the agent from the network. You have to read how it builds its TLS client. That is the entire point.
The attacker decision tree
No exploit code. The attacker only has to be on the path and present a certificate the agent was built never to check.
The decisive feature is step 2. The attacker does not break TLS, guess a password, or trigger a memory bug. They present a certificate, any certificate, a self-signed one minted thirty seconds earlier, and the agent accepts it because validation was hardcoded off. Everything after that is ordinary credential capture over a channel the attacker controls. This is why CWE-295 is rated high-likelihood-of-exploit: once the client refuses to authenticate the server, interception is deterministic for anyone who can get on the wire. The attack requires adjacency rather than a remote network position, which is the one mercy here, but adjacency is cheap inside a flat datacenter VLAN, a shared management network, or any environment where the agent and vCenter were never segmented from each other.
The class is everywhere, not just one agent
Disabled certificate validation is one of the most common real-world TLS failures, and it spans every kind of client. The shape is always the same: a developer turned off validation to get past a certificate error during integration, and the override shipped. A close relative is CWE-297 (Improper Validation of Certificate with Host Mismatch), where the chain is checked but the hostname is not, so a valid certificate for the wrong host sails through. Both leave a man-in-the-middle unauthenticated and undetected. The history of TLS is full of the broader lesson that an unauthenticated or downgradeable channel is an interceptable one: CVE-2014-3566 (POODLE) showed a man-in-the-middle forcing a downgrade and reading cleartext, and the defensive response was always to authenticate the peer and refuse the insecure path. The migration agent simply removes that authentication entirely.
The variants share a single shape:
- Validation disabled in the client.
InsecureSkipVerify: truein Go,verify=Falsein a Python request, a trust-allX509TrustManagerin Java, or--insecurewired in permanently. CVE-2026-53475 is this case: the agent connects to vCenter with validation off. - Hostname check skipped. The chain validates but the code never confirms the certificate belongs to the host it dialed. A valid certificate for any host the attacker controls is accepted. CWE-297.
- Trust anchor too broad. A custom callback that returns success for any certificate, or a baked-in CA that the operator cannot scope, so the agent trusts far more than the one endpoint it should.
- No way to harden it. The common thread across all of these in a shipped agent is that the operator has no setting to turn validation on. The insecure choice is hardcoded, exactly the property that makes this the trust-settings sibling of hardcoded secrets.
What we observe
We are honest about the limits of our visibility. CelvexGroup's continuous validation runs against assets and software the customer flags into scope, and the always-safe lane we operate is passive recon, version reads, and configuration and source inspection rather than active interception of live management traffic. We do not set up a man-in-the-middle against a customer's production vCenter to prove the point. Within that scope, inspecting how agents and integrations are configured to make their outbound TLS connections, the pattern is consistent: certificate validation gets disabled during integration and never gets turned back on, because the connection works either way and nothing in the pipeline forces the question. A management agent that authenticates successfully raises no alarm. The single line that would have made it validate the server is almost always optional in the code, and therefore almost always left off.
What to do about it: the trust contract
Hardcoded insecure TLS is a build-time and configuration problem, so the controls live there. We summarize them as a contract every client that opens a TLS connection should satisfy.
TLS trust contract: six controls that end the class
- Validate the certificate by default, always. Verify the chain to a trusted anchor and verify the hostname matches the host you dialed. This is the default behavior of every mature TLS library. The bug is always an explicit override of it, so the fix is to remove the override.
- Never ship an insecure TLS default that the operator cannot change. If validation can be relaxed at all, it must be an explicit, off-by-default, loudly-logged operator setting, never a hardcoded constant. An agent that connects to a management plane should not offer the relaxation at all.
- Pin or scope trust to the endpoint you actually talk to. For an agent that only ever connects to one vCenter, pin the expected certificate or constrain the trust anchor to that host. Do not trust the whole world to reach one server.
- Prefer mutual TLS for agent-to-management-plane links. When an agent holds credentials to the control plane of an entire estate, authenticate both ends. mTLS means the attacker cannot impersonate the server and the server cannot accept a rogue agent.
- Make the test path honest. The reason validation gets disabled is a self-signed certificate in a lab. Solve that by issuing the lab a real certificate from an internal CA, not by teaching the agent to skip validation. The shortcut that unblocks the lab is the vulnerability that ships.
- Audit every TLS client constructor in CI. Grep the codebase and the dependencies for the disable-validation idioms and fail the build on a hit that is not behind a guarded, documented operator flag. Treat a hardcoded
InsecureSkipVerify: trueas a failed build, not a warning.
Encryption without authentication is a private line to a stranger. If the agent will not check who answered, the attacker only has to answer first.
The detection grep, in concrete terms, is to hunt the disable-validation idioms across the agent's source and its dependencies:
# Go: the classic disabled-validation flag
$ grep -rn "InsecureSkipVerify" --include="*.go" .
# Python: requests / urllib3 / ssl with verification off
$ grep -rnE "verify\s*=\s*False|CERT_NONE|check_hostname\s*=\s*False" \
--include="*.py" .
# Java / JVM: trust-all managers and null hostname verifiers
$ grep -rnE "X509TrustManager|ALLOW_ALL_HOSTNAME_VERIFIER|TrustAllCerts" .
# CLI and config: permanent --insecure / skip-tls flags
$ grep -rnE "insecure[-_]?skip|--insecure|skip[-_]?tls[-_]?verify" .
Read each hit. Confirm validation is on by default and that any relaxation is behind a guarded operator flag, not a hardcoded constant. For an agent that authenticates to a management plane, confirm there is no relaxation path at all. The exercise is finishable in an afternoon for any agent, and it is the only way to find this class, because the running agent will keep authenticating successfully and tell you nothing.
How Celvex catches this
Find. Prove. Fix. Verify.
We inspect the configuration and connection code of agents and integrations in scope, hunting the disable-validation idioms and the hardcoded trust settings that let an agent open a TLS session it never authenticates.
For a confirmed hardcoded insecure TLS path, we ship a signed Proof Capsule with the exact file and line, the disabled-validation construct, and an authorized lab demonstration that an unrelated certificate is accepted on the agent's own out-of-band test path.
The Capsule's remediation block points at the trust contract: remove the override, pin or scope the trust anchor, move to mutual TLS for control-plane links, and add the CI grep that fails the build on a hardcoded disable.
After the fix lands, the agent rejects a certificate it should not trust and the CI gate is green. The finding closes automatically and the verified-fix event is recorded for the auditor.
This sits squarely in the cloud and infrastructure validation lane, where the evidence is how a component is configured to connect rather than a live interception of production traffic. Our cloud security validation capability is built for exactly this: proving a property of how an agent or integration trusts the management plane, signing the proof, and letting the customer reverify it independently. We do not claim to mount a man-in-the-middle against your production vCenter. We do claim that when an agent in scope opens a TLS connection with validation hardcoded off, we find it, prove it with a reproducible Capsule, and verify the fix held.
Bottom line
The agent you install to manage your infrastructure is a credential conduit, and a conduit that skips certificate validation is a credential leak. CVE-2026-53475, rated CVSS 9.3, is the clean example: an assisted-migration agent hardcodes an insecure TLS connection to vCenter, so an attacker on the same network segment intercepts the session, presents any certificate at all, and harvests the vCenter administrator credentials, which is to say the keys to the entire virtual estate. Your version scanner reports the correct version. Your runtime DAST watches a healthy encrypted session. The insecure line is one boolean in one client constructor that nobody re-reads. This is the other half of the hardcoded-secrets story: not a key in the box, but a trust setting nailed to off. The fix is not clever. Validate by default, never ship an insecure default the operator cannot change, pin or scope trust, prefer mutual TLS to the management plane, and grep your TLS clients in CI. The audit is an afternoon. Until that afternoon, every agent that skips the check is one adjacent attacker away from your control plane.
Verifiable security. Find it. Prove it. Fix it. Verify the fix held. That is what we ship.
Sources
- NVD: CVE-2026-53475 (CVSS 9.3, CWE-295): assisted-migration agent hardcodes insecure TLS to vCenter, enabling MITM credential theft. Red Hat assigning authority.
- MITRE CWE-295: Improper Certificate Validation
- MITRE CWE-297: Improper Validation of Certificate with Host Mismatch
- NVD: CVE-2014-3566 (POODLE): SSL 3.0 downgrade and man-in-the-middle cleartext recovery
- OWASP: Transport Layer Security Cheat Sheet (certificate and hostname validation guidance)
- CELVEX Group: The key was in the box (hardcoded signing keys, the companion piece)
- CELVEX Group: Proof Capsule format
- CELVEX Group: Cloud security validation
Find the disabled check before someone else does.
Free Exposure Check, no signup required. We inspect the agents and integrations in your footprint for hardcoded insecure TLS, and ship a Proof Capsule for the highest-confidence finding.
Run a Free Scan →