On Fri, 23 Oct 2026 16:09:48 GMT, Thejasvi Voniadka <[email protected]>
wrote:
> The sun.security.ssl.TrustStoreManager.TrustAnchorManager keeps one cached
> TrustStoreDescriptor (path, type, provider, password, last-modified time). It
> uses that descriptor to validate two caches: the loaded KeyStore (ksRef) and
> the extracted trusted certificates (csRef).
>
> getTrustedCerts() replaces the descriptor, ksRef and csRef together when the
> descriptor has changed. getKeyStore() replaces the descriptor and ksRef but
> leaves csRef alone.
>
> If getTrustedKeyStore() runs after the trust store file was modified, the
> cached descriptor is updated while csRef still holds the old certificates. A
> following getTrustedCerts() call finds a matching descriptor and returns the
> old set.
>
> TrustManagerFactory.init((KeyStore) null) then builds a trust manager that
> does not include the new certificates, until the JVM restarts or the weakly
> referenced csRef is cleared by the garbage collector.
>
> The only caller of getTrustedKeyStore() in the JDK is
> SSLContextImpl.DefaultManagersHolder.getTrustManagers(). It runs when the
> default TrustManagerFactory provider is not SunJSSE, so the problem is
> reachable with public APIs only.
>
> Steps to Reproduce:
>
> Create a PKCS12 trust store with one certificate and point
> javax.net.ssl.trustStore, trustStorePassword and trustStoreType at it.
> Build a default trust manager with TrustManagerFactory.getInstance("PKIX",
> "SunJSSE") and init((KeyStore) null), and keep a reference to it. It has 1
> accepted issuer.
> Add a second certificate to the file, making sure its last-modified time
> changes.
> Register a TrustManagerFactory provider that is not SunJSSE at position 1
> (for example, one that delegates to SunJSSE), and call
> SSLContext.getDefault().
> Build another default SunJSSE trust manager as in step 2.
>
> Results
> Expected: The new trust manager has 2 accepted issuers.
> Actual: It has 1.
>
> The new test StaleTrustedCerts implements these steps. It fails on an
> unpatched 21.0.11 and passes with the fix.
>
> Fix
> Clear the cached certificates in getKeyStore() together with the other caches:
>
> this.descriptor = descriptor;
> this.ksRef = new WeakReference<>(ks);
> this.csRef = new WeakReference<>(null);
>
> csRef is private and read only by getTrustedCerts(), which already reloads
> when get() returns null.
>
> Testing
> Included test
> test/jdk/sun/security/ssl/TrustStoreManager/StaleTrustedCerts.java that
> reproduces the issue, and verifies the fix.
>
>
> ---------
> - [x] I confirm that I make this contribution in accordance with the [OpenJDK
> Interim AI Policy](https://openjdk.org/leg...
Looks good to me. Thank you!
-------------
Marked as reviewed by xuelei (Reviewer).
PR Review: https://git.openjdk.org/jdk/pull/33545#pullrequestreview-5635444961