netflix/lemur · Security
Lemur: JWT verifier honors attacker-supplied alg, enabling ATO
- GHSA ID
- GHSA-r9gp-7f88-9r54
- CVE ID
- CVE-2026-55165
- Severity
- medium
- Published
- Updated
- CVSS
- 4.8 · CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N
- CVSS v3
- 4.8 · CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N
Description
| Field | Value |
|---|---|
| Title | Lemur 1.9.0: JWT verifier trusts attacker-supplied alg from token header — defense-in-depth gap; chain-dependent ATO with secret disclosure |
| Component | lemur/lemur/auth/service.py:130-137 |
| CWE | CWE-347 (Improper Verification of Cryptographic Signature) |
| Attack Prerequisite | Defense-in-depth gap on its own — no single-request exploit against PyJWT 2.x. Single-request ATO requires a separate disclosure issue that leaks LEMUR_TOKEN_SECRET, or a future migration to asymmetric signing without fixing this sink. |
| Affected Versions | github.com/Netflix/lemur version = "1.9.0". Same code present in every prior release that has the auth/service.py:130 block. |
Exploit Code & Lab Set-up
sequenceDiagram
participant Attacker
participant Lemur as Lemur API
participant Disclosure as Disclosure surface
participant Audit as Audit logging
Note over Attacker,Lemur: "Today: PyJWT 2.x mitigation holds for alg=none"
Attacker->>Lemur: "Bearer alg=none token with [payload]"
Lemur->>Lemur: "pyjwt.decode raises (alg=none + non-None key)"
Lemur-->>Attacker: "403 Forbidden"
Note over Disclosure,Lemur: "Chain step: separate disclosure leaks LEMUR_TOKEN_SECRET"
Attacker->>Disclosure: "trigger debug / SSRF / backup leak"
Disclosure-->>Attacker: "LEMUR_TOKEN_SECRET value"
Note over Attacker,Lemur: "Forge HS256 admin token with leaked secret"
Attacker->>Lemur: "Bearer alg=HS256 admin token signed with leaked secret"
Lemur->>Lemur: "algorithms=[HS256] (taken from header) — accepted"
Lemur-->>Attacker: "200 OK, role=admin"
Note over Audit: "alg=HS256 in audit log - no anomaly flag because attacker picks alg"
CWEs
- CWE-347 · Improper Verification of Cryptographic Signature