On Wed, 28 Oct 2026 02:53:56 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/X509TrustManagerImpl/StaleTrustedCerts.java that 
>> reproduces the issue, and verifies the fix.
>> 
>> 
>> ---------
>> - [x] I confirm that I make this contri...
>
> Thejasvi Voniadka has updated the pull request incrementally with one 
> additional commit since the last revision:
> 
>   Restored Oracle copyright line

Marked as reviewed by xuelei (Reviewer).

-------------

PR Review: https://git.openjdk.org/jdk/pull/33545#pullrequestreview-5700236732

Reply via email to