In-depth vulnerability research, detection engineering & applied cryptography.
A widely-deployed open-source cryptography library enforces an RFC 5280 path-length constraint (the rule that stops a subordinate CA from minting further CAs) only when the certificate also carries a separate, unrelated extension. Drop that extension and the limit is silently skipped: a CA that was explicitly forbidden from delegating can issue rogue sub-CAs that the library accepts as valid. I found it by variant-hunting a security patch the maintainers had just shipped. The fix closed one instance of the gating mistake and left this one behind.
This is a faithful, self-contained reproduction of the flaw's logic (no library named yet; that waits for the fix). You're looking at a certificate chain where a CA limited to pathLenConstraint = 0, meaning "you may issue end-entity certificates only, never another CA", has nonetheless issued a sub-CA. A correct validator must reject this. Toggle the keyUsage extension on that intermediate and watch the current library change its verdict on a chain that should always be rejected, while the patched build stays put.
Both validators re-evaluate the instant you flip the switch.
One toggle, two verdicts. The current library lets the presence of an unrelated extension decide whether it enforces the path-length limit, so flipping keyUsage flips its answer on a chain that should always be rejected. The patched validator ignores that field and rejects the chain every time.
Certificate-chain validators decide whether each intermediate is allowed to act as a CA. RFC 5280 makes two of those decisions independent: §4.2.1.9 says a basicConstraints pathLenConstraint caps how many CAs may follow in the path, and §6.1.4 applies that cap to every intermediate unconditionally. The presence of a keyUsage extension is governed separately by §4.2.1.3 and has nothing to do with path-length processing.
The vulnerable code couples them anyway: the path-length check sits behind a guard that only runs if (keyUsage extension is present). The author's reasoning was that having parsed keyUsage they "know" the basic constraints are present too, but that conflates two orthogonal extensions. Remove keyUsage and a real, signed, constraint-bearing CA escapes its own limit. It's the same "gate a mandatory check on an optional field" anti-pattern that a recently-published advisory fixed for a sibling check. This is the instance that fix didn't reach.
Finding the bug was half the work; not crying wolf on the others was the rest. I ran four more independent deep analyses against the same library's most security-critical paths. Each produced a rigorous negative, and a negative I can defend is worth more than a finding I can't. This is the discipline that keeps a report from getting auto-rejected as noise.
A recently-rewritten schema validator does ignore trailing elements, but every trust-bearing sink is guarded by an outer length check or sits under a real signature. Not weaponizable.
Probed the Bleichenbacher / low-exponent class with real e=3 keys. Tight padding + full-byte parsing + exact-digest compare pin the hash to the low-order bytes. No no-private-key forgery.
Differential-tested against OpenSSL across non-canonical, low-order and cofactor edge cases. The S<L fix plus byte-exact R compare make the accepted-signature set a singleton. No divergence.
DN/issuer spoofing, trust-anchor confusion, critical-extension smuggling, algorithm downgrade. Trust anchoring is byte-exact; no false-accept beyond the path-length issue above.