CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Dashboard
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-88Q6-JCJG-HVMW
8.80.04%

The 'None' Shall Pass: Total Auth Bypass in jose-swift

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 22, 2026·5 min read·11 visits

PoC Available

Executive Summary (TL;DR)

A critical authentication bypass affects 'jose-swift' versions <= 6.0.1. The library improperly handles JWTs with the 'alg': 'none' header, returning a successful verification result immediately without checking for a valid signature. This allows attackers to forge tokens with arbitrary privileges. The fix (v6.0.2) enforces algorithm blacklisting and signature presence checks.

In the world of JSON Web Tokens (JWT), the 'none' algorithm is the cryptographer's equivalent of a screen door on a submarine. It exists for debugging, yet it somehow keeps finding its way into production logic. This time, the victim is 'jose-swift', a popular library for JOSE standards in the Swift ecosystem. A critical logic flaw in the signature verification process allowed attackers to bypass authentication entirely by simply telling the server, 'Trust me, I'm unverified.' By manipulating the JWT header to specify the 'none' algorithm, an attacker could forge tokens with arbitrary claims—becoming admin, modifying user data, or accessing protected routes—without knowing the signing key.

The Hook: Trusting the Burglar

In the realm of modern authentication, we rely heavily on the JSON Web Token (JWT). It’s the stateless passport of the web. The server signs it, hands it to the client, and says, 'Show me this later, and I'll know it's you.' The security of this entire system rests on one assumption: The cryptographic signature cannot be forged.

'jose-swift' is a comprehensive implementation of these standards for the Swift ecosystem, used by iOS, macOS, and server-side Swift developers to handle JWS (Signing) and JWE (Encryption). It handles the messy math so developers don't have to.

But what happens when the library decides to trust the metadata inside the token before verifying the token itself? It’s analogous to a bouncer checking ID, seeing a sticky note on it that says 'I am 21', and letting the person in without looking at the birth date. That is exactly what happened here. A logic flaw in the verification routine turned a robust cryptographic library into a rubber stamp for forgery.

The Flaw: The 'None' Algorithm Strikes Back

The 'none' algorithm is a vestige of the original JWT specification, intended for situations where the integrity of the token is already guaranteed by the transport layer (like mutual TLS) or for debugging. In a 'none' token, the signature segment is empty. The token essentially says, 'I am unsigned.'

The vulnerability in jose-swift (GHSA-88Q6-JCJG-HVMW) is a classic instance of CWE-347: Improper Verification of Cryptographic Signature. The library failed to decouple the request for an algorithm from the policy enforcing it.

When a token arrives, the library parses the header to determine which algorithm was used to sign it. In the vulnerable versions, if the header claimed the algorithm was none, the library's verification logic short-circuited. It didn't just skip the signature check; it explicitly returned true (valid), assuming that if the token said it was unsigned, and the code reached that point, it must be acceptable. This effectively delegated the security decision to the attacker-controlled input.

The Code: The Smoking Gun

Let's look at the crime scene. The vulnerability lived in JWS+Verify.swift. The logic was devastatingly simple. Here is the vulnerable verification function:

public func verify<Key>(key: Key?) throws -> Bool {
    // VULNERABLE CODE
    guard SigningAlgorithm.none != protectedHeader.algorithm else {
        return true // <--- The fatal flaw
    }
    // ... actual cryptographic verification would happen here ...
}

Do you see it? The guard statement checks if the algorithm is none. If it is none, the guard fails, executing the else block. The else block simply returns true.

This meant that if an attacker sent a token with {"alg": "none"}, the function would immediately return true without ever checking a key, a signature, or a whitelist. It essentially said: 'Oh, you aren't using encryption? Go right ahead.'

To fix this in version 6.0.2, the maintainers had to invert this philosophy. They introduced a check to ensure that even if none is somehow processed (which it shouldn't be in production), it cannot coexist with a signature, and it must be explicitly allowed by a validator.

The Exploit: Becoming Admin

Exploiting this requires no special tools—just a text editor and a basic understanding of Base64Url encoding. Here is how an attacker creates a Golden Ticket:

  1. Capture a legitimate token: The attacker logs in as a low-privileged user to get a valid structure. eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMTIzIiwiYWRtaW4iOmZhbHNlfQ.signature_bytes

  2. Modify the Header: Decode the first part. Change "alg": "HS256" to "alg": "none". Re-encode it. eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0

  3. Forge the Payload: Decode the second part. Change "admin": false to "admin": true (or inject any other claim you want). Re-encode it. eyJzdWIiOiJ1c2VyMTIzIiwiYWRtaW4iOnRydWV9

  4. Reassemble: Combine the new header and payload with a period. You can leave the signature empty or put garbage there, as the vulnerable code returns true before parsing the signature segment (though standard none implementation usually expects a trailing dot with no signature). eyJhbGciOiJub25l... .eyJzdWIi... .

  5. Attack: Send this token in the Authorization header. The verify() function sees alg: none, returns true, and the application processes the payload believing the user is an admin.

The Fix: Stopping the Bleeding

The remediation in version 6.0.2 (PR #62) introduces multiple layers of defense. First, it kills the short-circuit logic. Second, it adds sanity checks.

Here is the logic in the patched version:

public func verify<Key>(key: Key?) throws -> Bool {
    // PATCHED LOGIC
    if SigningAlgorithm.none == protectedHeader.algorithm, !signature.isEmpty {
        // If alg is none, but you sent a signature, we know you are up to no good.
        throw JWSError.algorithmNoneButSignatureFound
    }
    
    // Proceed to validator checks which now include a blacklist
    // ...
}

Furthermore, the developers introduced a SigningAlgorithmBlackListValidator. By default, this validator now runs on verification and explicitly blocks none unless the developer goes out of their way to remove the block. This shifts the library from 'insecure by default' to 'secure by default'.

Official Patches

beatt83Pull Request #62 fixing the signature verification bypass

Technical Appendix

CVSS Score
8.8/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
EPSS Probability
0.04%

Affected Systems

iOS Applications using jose-swiftmacOS Applications using jose-swiftServer-side Swift (Vapor, Kitura) utilizing jose-swift for Auth

Affected Versions Detail

Product
Affected Versions
Fixed Version
jose-swift
beatt83
<= 6.0.16.0.2
AttributeDetail
Attack VectorNetwork (AV:N)
Attack ComplexityLow (AC:L)
Privileges RequiredNone (PR:N)
CWECWE-347 (Improper Signature Verification)
CVSS Score8.8 (Critical)
Exploit StatusPoc Available / Trivial

MITRE ATT&CK Mapping

T1550.001Application Access Token
Use Alternate Authentication Material
T1078Valid Accounts
Defense Evasion
CWE-347
Improper Verification of Cryptographic Signature

The product verifies a cryptographic signature, but the verification logic is implemented incorrectly, allowing the signature check to be bypassed.

Known Exploits & Detection

GitHubOfficial unit tests added in the patch demonstrate the vulnerability and fix logic.

Vulnerability Timeline

Vulnerability Published
2026-01-09
Patch Merged (Version 6.0.2)
2026-01-10

References & Sources

  • [1]GitHub Advisory: Improper Verification of Cryptographic Signature in jose-swift
  • [2]History of the 'None' Algorithm Vulnerability

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.