You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Saving an unregistered Credential subclass through a platform store still throws a raw NotSupportedException, while InMemoryCredentialStore accepts it (#171 fixed only CredentialCache.AddOrReplace) #206
The #194 fix for #171 added CredentialSerialization.ThrowIfUnknownType (CredentialCache/Storage/CredentialSerialization.cs:146). It is called only from CredentialCache.AddOrReplace (CredentialCache/CredentialCache.cs:208).
A store can also be used directly through CredentialStoreFactory.CreateDefault(...) or CredentialCache.Instance.Store, and its Save skips that check. Each platform store calls CredentialSerialization.Serialize before any native call, so System.Text.Json's polymorphism error escapes:
Linux: NativeSecretBuffer.cs:152
Windows: WindowsCredentialStore.cs:79
macOS: MacOsCredentialStore.cs:77
InMemoryCredentialStore.Save doesn't serialize, so it accepts the same credential.
A probe test on Linux at b2c2772, with class ProbeA : Credential left unregistered:
linux store Save(unregistered): System.NotSupportedException: Runtime type 'ProbeA' is not supported by polymorphic type 'Credential'
factory store Save(unregistered): System.NotSupportedException
factory store Save(built-in type, no secret service): CredentialStoreException (control)
in-memory Save(unregistered): ok
The public CredentialSerialization.Serialize, which the README tells custom-store authors to call, throws the same raw NotSupportedException.
Why it matters
This is the split #171 described, still present one layer down. A consumer whose tests run against InMemoryCredentialStore passes. In production the platform store throws an exception type that nothing around a store call expects, since store failures are otherwise CredentialStoreException. The behaviour is the same on all three platforms because the throw happens before any native code runs.
Suggested fix / acceptance criteria
Call ThrowIfUnknownType at the top of CredentialSerialization.Serialize/SerializeToString, so every platform store and every custom store built on them gets it. Also call it in InMemoryCredentialStore.Save.
Save of an unregistered subclass throws the same exception, with the same message, from the in-memory store, the platform stores and CredentialCache.AddOrReplace.
Add a test that calls Save directly on InMemoryCredentialStore and on the default store, with an unregistered subclass.
Priority: Medium. It hits only unregistered Credential subclasses. The effect is the wrong exception type (NotSupportedException instead of the documented failure) and a behaviour split between the in-memory store and the platform stores, so tests can pass while production throws. No data is lost or leaked.
Area: Serialization and store layer (CredentialSerialization, InMemoryCredentialStore, the three platform stores).
Activity
matt-edmondson commentedon Nov 8, 2026
Triage
Credentialsubclasses. The effect is the wrong exception type (NotSupportedExceptioninstead of the documented failure) and a behaviour split between the in-memory store and the platform stores, so tests can pass while production throws. No data is lost or leaked.CredentialSerialization,InMemoryCredentialStore, the three platform stores).ThrowIfUnknownTypeintoSerialize/SerializeToStringis a small, contained change.RegisterDerivedTypeaccepting types that can't round-trip). Fixing them together would make every store reject or accept the same set of types.Generated by Claude Code