On Mon, 26 Oct 2026 15:02:08 GMT, Artur Barashev <[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 contribut...
>
> src/java.base/share/classes/sun/security/ssl/TrustStoreManager.java line 2:
> 
>> 1: /*
>> 2:  * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights 
>> reserved.
> 
> Copyright year should be updated.

Correction: you are currently employed by a company which signed OCA then do 
not modify Oracle copyright line. Insert this line under the Oracle copyright 
line instead:

`Copyright (c) 2026, <Company Name Goes Here>. All rights reserved.`

For the brand-new unit test just insert the above line, you don't need Oracle 
copyright line there.

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

PR Review Comment: https://git.openjdk.org/jdk/pull/33545#discussion_r4390475563

Reply via email to