I was reviewing how Bouncy Castle handled the fix for CVE-2023-33201, an LDAP injection bug from 2023. Clean patch, applied to X509LDAPCertStoreSpi.java. They added filterEncode() to sanitize certificate Subject DN values before stuffing them into LDAP filter strings. But I wanted to know if that was the only place they built LDAP filters from certificate data.
It wasn't.
LDAPStoreHelper.java, same library, same pattern, same problem. Line 504:
for (int i = 0; i < attributeNames.length; i++)
{
filter += "(" + attributeNames[i] + "=" + attributeValue + ")";
}
filter = "(|" + filter + ")";
No filterEncode(). No escaping of LDAP metacharacters. The attributeValue comes from the certificate's Subject DN and goes straight into the filter string.
The git history confirmed it. The 2023 fix touched X509LDAPCertStoreSpi.java in commits b9b03cc6e and e8c409a83. LDAPStoreHelper.java was never patched. Two years of the same vulnerability sitting in a parallel code path.
If you control the Subject DN of an X.509 certificate, you can inject LDAP filter syntax. Create a cert with a CN like *)(|(cn=*) and when Bouncy Castle processes it, the constructed filter becomes:
(cn=*)(|(cn=*)*)
Instead of returning the one certificate you queried for, the LDAP server returns everything. I tested this against a local LDAP setup. A normal query for "user1" returned 1 result. The injected filter returned all 5 certificates in the directory, including admin and CA certs.
The attack requires a specific scenario. An application has to process attacker-controlled certificates and use Bouncy Castle's LDAP certificate store to look them up. That's not every deployment, but for the ones that do this, you're looking at information disclosure of every certificate in the directory.
This is a pattern I keep coming back to. When a vulnerability gets patched, the fix usually targets the exact code path that was reported. But the same pattern often exists in other parts of the codebase. The original researchers and the maintainers are focused on the specific bug. Nobody goes back and audits every other place the same mistake might exist.
LDAPStoreHelper is in a different package (org.bouncycastle.x509.util vs org.bouncycastle.jce.provider), so it's easy to miss. That's the whole point. These things are easy to miss, which is why variant analysis works.
I reported this to the Bouncy Castle team and had a fix on GitHub within five days, over the New Year's weekend no less. That says a lot about how seriously they take security reports. They went further than just patching the one file. They rewrote the code to share common LDAP filter construction between the two classes so this can't happen again. That's the right way to fix a variant. Not just patch the spot, but eliminate the category.
The vulnerability was assigned CVE-2026-0636. The fix is in Bouncy Castle 1.84.
If you're working on cryptographic library security or variant analysis, feel free to reach out.