The bug
Bun (89k stars) had a TLS hostname verification bypass in tls.connect(). One file returned a value under one key. Another file read it under a different key. The difference was a single capital letter.
In src/js/node/tls.ts, the host fallback was returned under the key serverName (camelCase). In src/js/node/net.ts, the consumer read tls.servername (all lowercase). The result: self.servername was always undefined. The guard && self.servername evaluated to false. checkServerIdentity was skipped entirely. And tls.connect({host, port}) without an explicit servername option reported authorized: true for any certificate.
Here is the one-letter difference that broke TLS for every Bun user:
// src/js/node/tls.ts — the producer return { serverName: host || "localhost" }; ^ // src/js/node/net.ts — the consumer if (self.authorized && self.servername) { checkServerIdentity(self.servername, cert); } // self.servername is undefined — check never runs
The impact was severe. An attacker with any valid CA-signed certificate -- a free Let's Encrypt cert for attacker.com -- could intercept TLS connections from any Bun application. Every pg.connect(), every ioredis connection, every mysql2 query, every nodemailer send. The certificate didn't need to match the hostname. The check that would have caught the mismatch never executed.
This wasn't a regression. The bug existed since the TLS implementation was written. Every version of Bun with tls.connect() was affected.
caused the bypass
pg, ioredis, mysql2, nodemailer
by 4 Ensemble reviewers
The fix: oven-sh/bun #29096 -- "tls: fix tls.connect skipping hostname verification when servername omitted."
What Ensemble found
We ran Ensemble against the fix PR with 4 independent reviewers: a Security Engineer, an Architecture Reviewer, a Senior Code Reviewer, and a Skeptic Reviewer. They produced 17 issues total. The interesting part isn't just that they validated the fix -- it's that they found problems in the fix itself.
The Security Engineer validated the fix, confirmed it addressed the bypass, and noted RFC 6066 compliance: IP addresses should be rejected for SNI, which the fix handles correctly. This is the straightforward value -- an expert-persona reviewer confirming the security properties of a patch.
But the Architecture Reviewer found something more interesting.
The Architecture Reviewer flagged two structural weaknesses in the fix PR itself. First: the hostname verification logic was duplicated across two handler implementations (SocketHandlers and SocketHandlers2). This is the exact kind of copy-paste that caused the original bug -- a naming inconsistency between two files. Duplicating the fix across two handlers means the next developer who touches this code has to remember to update both. The Architecture Reviewer pointed out that this already went wrong once in this very PR.
Second: a fragile fallback chain. The fix uses self.servername || self._host || "localhost". That trailing "localhost" means a misconfigured connection silently verifies against "localhost" instead of failing. A security fix that fails silently is a security fix that will eventually stop being a security fix.
Why this bug is hard for humans
This is a cross-file naming inconsistency. The producer (tls.ts) and the consumer (net.ts) are in different files. A human reviewing either file in isolation would see correct-looking code. serverName is a perfectly reasonable key. servername is a perfectly reasonable property. You have to hold both files in your head simultaneously and notice that the casing doesn't match.
JavaScript doesn't help. There's no type error. No runtime exception. undefined is falsy, so the guard silently skips the check. The connection succeeds. The authorized property is true. Everything looks correct unless you specifically test with a mismatched certificate and verify that the connection is rejected.
Multi-model review helps here because each reviewer parses the full diff independently. They don't share context. They don't inherit assumptions. When one file writes serverName and another reads servername, three independent reviewers parsing the code fresh are more likely to notice the mismatch than a single reviewer who has been staring at the codebase for hours.
The honest part
Three things to be upfront about.
References
tls.ts (producer), net.ts (consumer)Cross-file bugs hide in plain sight
Ensemble runs multiple independent AI reviewers on every PR. Different perspectives catch what single-pass review misses -- like a capital letter that bypassed TLS.