CVE-2026-78223: Token revocation record built from unverified JWT claims in AshAuthentication
Improper Verification of Cryptographic Signature vulnerability in team-alembic AshAuthentication allows a caller of the token revocation action to neutralise a revocation or write arbitrary rows into the token resource.
AshAuthentication.TokenResource.RevokeTokenChange.change/3 reads the :token argument and decodes it with AshAuthentication.Jwt.peek/1, which delegates to Joken.peekclaims/1 and performs no signature check, unlike Jwt.verify/4. The jti, exp and sub claims it returns are written straight onto the revocation record, guarded only by bytesize(token) > 0. Because expiresat derives from the attacker-chosen exp, a forged copy of a genuine token that keeps the real jti but backdates exp yields a revocation row that is already expired: expungeexpired removes it and the genuine token passes revoked? again. Arbitrary jti and sub values can be inserted the same way.
This issue affects ashauthentication: from 0.2.0 before 4.15.0 and from 5.0.0-rc.0 before 5.0.0-rc.14.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
team-alembic AshAuthenticationto a version that resolves this vulnerability.Fixed in 4.15.0 - Upgrade
Upgrade
team-alembic AshAuthenticationto a version that resolves this vulnerability.Fixed in 5.0.0-rc.14
Event History
Frequently Asked Questions
Which deployments are affected?
Affected versions are ash_authentication 0.2.0 through versions before 4.15.0, and 5.0.0-rc.0 through versions before 5.0.0-rc.14.
What does an attacker need to exploit this issue?
The attacker needs to be able to call the token revocation action with a non-empty token value. The supplied JWT is decoded without signature verification, allowing attacker-controlled jti, exp, and sub claims to be written to the revocation record.
How can this be used to bypass revocation?
An attacker can submit a forged token that retains the jti of a genuine token but uses an already-expired exp value. Once the expired revocation row is removed by expunge_expired, the genuine token can pass the revocation check again.
What should be done if patching cannot happen immediately?
Restrict access to the token revocation action so untrusted callers cannot submit arbitrary token values. The vulnerability is reachable through that action because it accepts a token whose claims are used without signature verification.