Zero-Day with due Unauthenticated AES-CFB
How a missing integrity check in opaque OIDC access tokens enabled identity impersonation — and what identity providers should take from the fix.
Identity systems sit at the center of almost every modern application. If an access token can be altered so that it still looks valid, but now represents someone else, the rest of the security model collapses with it.
While evaluating a widely used OpenID Connect library (zitadel/oidc), PurpleSwarm found exactly that class of failure in the OpenID Provider path: opaque access tokens were protected for confidentiality, but not for integrity. A holder of a legitimate token could alter it in a way that caused the provider to treat it as belonging to a different user.
What went wrong
Opaque tokens are meant to be meaningless to clients. The provider encrypts internal identity material and later decrypts it during validation or introspection.
Encryption answers one question: can an outsider read the token contents?
It does not automatically answer another: can an outsider change the token without detection?
In this case, the OpenID Provider encrypted subject information inside opaque access tokens without an integrity guarantee. That made token contents confidential, but still malleable. Once a valid token was obtained, identity inside it could be rewritten. Token introspection then confirmed the forged identity as active.
The issue was limited to the OpenID Provider side of the library. Relying Party and Resource Server usage was not affected. Deployments that relied on signed JWT access tokens, rather than opaque encrypted bearer tokens, were outside the exposure path.
Why this matters
Authentication bypass at the identity layer is high-impact by design. Applications often trust introspection results and treat the returned subject as ground truth. If that subject can be forged, every downstream authorization decision built on it becomes unreliable.
This is also easy to underestimate during design review. Teams see “tokens are encrypted” and assume tampering is impossible. Confidentiality and authenticity are different properties. Without both, encrypted identity material can still become an impersonation primitive.
Responsible disclosure and fix
We reported the issue to the vendor on February 19, 2026. A fix was released on April 8, 2026 in zitadel/oidc, moving opaque provider tokens to authenticated encryption so tampering is detected rather than silently accepted.
Despite the library’s wide use as an OpenID Provider building block, the vendor did not publish a security advisory of their own. Without a CVE or advisory, many downstream teams had no clear signal that they needed to upgrade or revoke legacy opaque tokens. On July 20, 2026 — five months after our responsible disclosure — we therefore reported the vulnerability to MITRE ourselves so it could be tracked and communicated through the CVE program.
Operators should upgrade to the fixed library release. If opaque tokens were in use, outstanding tokens issued under the old scheme should be revoked after the change. Switching cryptography without invalidating active tokens leaves the old, forgeable material usable until expiry.
A temporary mitigation for OpenID Provider deployments is to supply a custom crypto implementation that provides authenticated encryption, or to avoid opaque encrypted bearer tokens entirely. In all cases, revoke active opaque tokens after the change.
What teams should take away
The most reliable design is also the simplest: do not invent token cryptography when you do not need it.
A random UUID4 is sufficient in almost every case. Issue an opaque identifier, store the session or access-token metadata on the server, and look it up on use. Modern databases are more than capable of this pattern and can index on the order of 100 million items without issue. If index locality later becomes a measured bottleneck, UUID7 is an option — but it embeds a timestamp, which is not ideal for bearer tokens. Prefer UUID4 unless you have a concrete reason to change.
Encrypting session or access tokens should be avoided unless there is a real requirement that server-side lookup cannot meet. Encrypted client-held blobs create avoidable crypto risk; an opaque ID with server-side state keeps identity authoritative where it belongs.
If encryption is genuinely required, AES-GCM is all you need. It provides authenticated encryption — confidentiality and integrity together — without exotic constructions or unauthenticated modes.
Also keep in mind:
- Confidentiality is not authenticity. “Encrypted” does not mean “unforgeable.”
- Introspection is part of the trust boundary. If it affirms a forged subject, application authentication follows.
- Crypto migrations require operational follow-through. New algorithms do not protect old tokens that remain accepted.
- Library defaults are production defaults. Most consumers never override them.
PurpleSwarm focuses on proving whether weaknesses are reachable and exploitable, not only theoretically interesting. Findings like this are why continuous offensive validation of identity flows matters: the failure mode is not a missing header check, but a broken assumption about what encryption guarantees.
If you operate an OpenID Provider, upgrade promptly, revoke legacy opaque tokens, and verify that tampered tokens are rejected end to end.