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