🔥 CyberForge CVE of the Day #094
🚨 CVE-2026-120459 — python-jose
When the HMAC verification key is empty, accepted claims lose their assurance
📅 3rd November 2026 | Evidence cutoff: 2026-11-03T09:37:27Z
🛡️ VulnCheck CNA: Critical / CVSS v4.0 9.1; High / CVSS v3.1 7.4
🎯 The quick hit:
python-jose through 3.5.0 can accept zero-length HMAC key material. The published CVE concerns applications whose HS256, HS384 or HS512 verification key actually resolves to empty, including an octet JWK with an empty k value. Under that condition, untrusted callers can supply forged JWT claims that the affected verifier accepts.
The prerequisite matters. A dependency match is the start of scoping; it does not prove that every application using python-jose exposes the bypass. Establish the actual verifier, algorithm policy, final resolved material and reachable token-consuming route. A missing setting might fail safely, while a nonempty-looking key object might still decode to empty bytes.
The difficult remediation fact is a verified gap: the current captured PyPI and upstream release is 3.5.0, which is inside the affected range. No fixed release was verified. Do not mark “upgrade to latest” as completion or invent a safe next version. Application-side safeguards need an accountable owner, supported change and real integration evidence.
This edition uses public records, tagged source, standards and safe tests of a newly authored readiness helper. No application, real secret, incident dataset or token was tested. No JWT was created or submitted. Operational exposure, compromise, correction and recovery remain questions for the responsible owners.
🔑 Key details:
CVE / CNA: PUBLISHED / VulnCheck. Product: python-jose; package identifier pkg:pypi/python-jose. Its import namespace is jose, which is not the distribution name used for inventory.
CWE: CWE-347, Improper Verification of Cryptographic Signature. The reporter's empty-key finding uses a different weakness label, and its multi-finding issue also discusses unrelated DER and timing problems. Keep those classifications and mechanisms attributed separately.
CVSS v4.0: 9.1 / Critical, VulnCheck CNA:
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N
CVSS v3.1: 7.4 / High, VulnCheck CNA:
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N
These are distinct models. The v4.0 requirements-present condition and v3.1 high-complexity assessment do not remove the application prerequisite. No score is averaged or silently substituted.
NVD: Awaiting Analysis in its captured API record. Both scores originate from disclosure@vulncheck.com: v3.1 is displayed as Primary and v4.0 as Secondary. Those labels do not create an independent NIST assessment.
Required condition: an affected application consumes untrusted JWTs and supplies empty effective material to an applicable HMAC verifier. The CNA has PR:N and UI:N, but the actual key and route still have to be established.
Documented capability: forged claims can be accepted. Actual permissions follow application authorisation and the accepted claims. No universal administrator, host execution, persistence, cross-tenant access or data theft is established by the public record alone.
Fix: no fixed upstream release verified at cutoff. PyPI and the upstream release list show 3.5.0; the primary issue remains open with no comments in the captured API.
Public reproduction: the primary reporter issue includes a short library-level example. It was passively inspected, not executed. That is not a tested exploit against a real application or a confirmed victim event.
Exploitation / SSVC: no primary incident confirmation established in the bounded review. The captured CVE contains no ADP/SSVC assessment; unavailable data is not an exploitation value of “none.”
CISA KEV: no exact match in returned catalog 2026.10.30, released 30th October at 17:02:45.3665Z, containing 1,766 entries. This dated non-match does not establish safety or supply a due date.
FIRST EPSS: the exact-ID request returned HTTP 200 with total 0 and an empty data array. Probability, percentile and score date are unavailable. That is not a 0% forecast.
Credit: the CNA credits Gavin Blacklock and Conner Webber as finders.
🧬 What actually went wrong?
HMAC authentication relies on an authorised issuer and verifier sharing secret material. If the application supplies a publicly predictable empty value instead, a matching integrity computation cannot establish the intended secret holder. The mathematics can still produce a result while the trust input is unsound.
The relevant boundary is resolved key material → authentication assurance → accepted identity and permissions. Claim checks and resource authorisation still matter, but plausible issuer, audience or role values cannot restore secrecy to an empty key.
Passive review of the 3.5.0 source examined HMACKey in the native backend and CryptographyHMACKey in the cryptography backend. The reviewed preparation paths accept string/bytes material or resolve an octet JWK without an explicit zero-length rejection. The import layer selects the cryptography HMAC class when available, otherwise the native class. A deployment's actual backend was not inspected.
This is not a claim that HMAC itself is broken, every absent setting becomes empty or every python-jose dependency is exploitable. Trace the actual route. A resolver may throw before verification; another integration may use an asymmetric algorithm or a sound key. Do not import adjacent algorithm-confusion or timing findings from the same issue into this CVE's effect.
📦 Which deployments belong in scope?
Start with python-jose at or below 3.5.0 in the actual serving interpreter, container image or embedded runtime. Then establish whether its active token path uses HS256/384/512 and whether final material can become empty.
Inventory API workers, replicas, background consumers, tenant/key selectors and refresh/error branches. A workstation environment or one updated image does not attest all serving paths. The installed version, imported backend, application policy and loaded material are different evidence fields.
🕰️ Exposure window and timeline:
The upstream 3.5.0 release was published on 28th May 2025. The reporter's multi-finding issue was created on 8th March 2026 at 04:20:14Z. The CNA's datePublic is the same calendar date at midnight, a date-level field rather than the exact issue-posting time.
Reconstruct the interval where affected serving code, HMAC verification, empty resolved material and route reachability overlap. Use real configuration, secret-version, deployment and readiness records. Include stale workers, partial rollout, refresh failures and rollback. A safe current key cannot establish what an earlier process loaded.
State the retained interval, clock uncertainty, ingestion delay and earlier blind spots. New logging cannot recreate missing history, and an empty search is meaningful only after source health and schema coverage are known.
🗺️ MITRE ATT&CK:
Credential Access / TA0006 → T1606, Forge Web Credentials: a conditional analyst mapping for the CNA-described forging of web claims. It is not an observed actor procedure or a token created by this research.
T1550.001, Application Access Token: retain this use context only if the affected JWT is actually an application access token used to authenticate to the service. The token's role and architecture must be established; not every JWT is an OAuth/access token. Applicable tactic context depends on the actual activity.
Defender pivots are trusted key-state records, existing issuer/session context where available and independently confirmed application actions. ATT&CK provides a vocabulary for those questions; it does not supply local telemetry or prove the CVE caused an event.
🧭 SOC investigation trail:
Objective: establish whether accepted claims occurred under a confirmed weak-key state and whether unapproved access or change followed. Review actual application sources, trusted configuration context and a justified UTC interval. No universal python-jose audit schema is assumed.
C01 — Establish runtime, algorithm and key path
Ask the application owner for each serving interpreter/image and python-jose version, active verification path and trusted algorithm policy. Trace key resolution and decoding to final bytes without exposing secrets. Cover workers, tenants, jobs and refresh/failure paths.
The useful signal is the combination of affected library, HMAC use, empty effective material and a reachable token route. An unused dependency, different environment or failed-before-decode path can change applicability. Escalate confirmed active empty material for immediate exposure control; a dependency match alone remains a scoping result.
C02 — Reconstruct the unsafe interval
Review existing deployment, configuration, secret-source version and readiness metadata. Identify when the implicated state was activated, not simply when a setting was created. Include key refresh, missing selectors, partial rollouts and rollback.
A resolver error might have been safely blocked; another worker might have retained sound material. Secret metadata alone does not establish what every process loaded. Correlate worker/build/configuration and actual serving times. An unresolved interval remains an owned exposure and evidence question.
C03 — Examine acceptance and trusted issuance context
Use already retained application authentication decisions and issuer/session records where that architecture supplies them. Join existing request/session references with trusted verifier/policy versions and consider issuer, audience, validity period and token purpose.
An accepted subject or role may be the suspect assertion. A signature-valid flag under an empty HMAC key is not independent origin evidence. Missing issuer records can also result from distributed issuers, retention loss, delay or long-lived legitimate sessions. Escalate corroborated inconsistencies, not one unmatched field.
C04 — Establish the sensitive operation
Follow suspicious acceptance into resource reads, changes or privileged actions, with their completion state and owner approval. Preserve object, tenant, operation and correlation identifiers where actually logged.
A successful HTTP status does not prove data extraction, role elevation or a completed sensitive effect. Approved support work, scheduled jobs and shared request contexts are alternatives. Corroborated unapproved operations support an incident; attributing the empty-key CVE requires evidence of the verifier/key state at that time.
C05 — Review durable sessions and downstream effects
If unauthorised acceptance/actions are established, ask whether the application created server-side sessions, cached claims or downstream access that survives a key-policy correction. Use the real lifecycle and supported revocation mechanisms.
Do not infer theft of users' passwords or every unrelated key. Session refresh, delegation and missing telemetry can explain later activity. Expand scope only when actual identifiers and effects connect the events. A corrected verifier may coexist with unresolved earlier sessions.
C06 — Verify current controls and separate incident closure
Require invalid material to be rejected before use/activation on every serving path. Validate trusted algorithm/key pairing, claim rules and normal, refresh, error and rollback cases through the owner's authorised integration suite. Check legitimate traffic and service health as well as rejection.
A length-only helper cannot establish entropy, key provenance or real integration. One worker or startup check cannot attest all later paths. No fixed upstream release was verified here. Keep current exposure-control acceptance and the historical incident disposition as separate records with remaining gaps owned.
The analyst handover:
Record service/worker and owner → runtime/policy/key-source evidence → relevant interval → acceptance/action records → competing explanations → confidence/gaps → next owner. Use potential applicability, established exposure, suspicion, corroborated incident or insufficient telemetry according to the evidence.
If a search returns no matches, retain the assets, sources, interval, filters, collection health and blind spots actually examined. A missing dataset or unsupported schema is unavailable evidence. No findings are not proof of a clean system.
🔎 Indicators and observable behaviour:
No confirmed CVE-specific attacker IP, domain, payload hash, kid value, claim string or token fingerprint was established in the reviewed primary sources. A normal JWT format, HMAC algorithm name, login error or 200 response is not a unique CVE signature.
Useful leads are confirmed empty active material, acceptance inconsistent with trusted context, and an independently validated unapproved operation. A readiness failure may instead show that bad material was safely prevented from activating. Keep control failure, suspicious acceptance and observed outcome distinct.
🧰 Optional CVE checks
Check A — Inventory the actual interpreter
From the scoped service's approved virtual environment or container context, the owner can use the documented read-only distribution query:
```bash
python -m pip show python-jose
```
Retain the environment, distribution version, location and acquisition UTC. A not-found/error result applies to that interpreter and cannot clear another worker. Installed metadata does not establish active HMAC use or resolved key state. Official documentation and shell grammar checked; no serving interpreter was queried here.
Check B — Use a narrow readiness contract
A separately authored defensive example checks already-resolved bytes against an algorithm from trusted application policy. It rejects empty material and enforces RFC 7518 HMAC length minima: 32 bytes for HS256, 48 for HS384 and 64 for HS512. It does not parse, sign or verify a token, read secrets from an environment or contact a service.
Eight safe unit-test methods passed for that example: empty/non-bytes/short inputs, length boundaries, explicit algorithm policy and non-disclosing diagnostics. Synthetic predictable fixtures can pass the length contract, deliberately showing that length does not prove entropy. No python-jose code or JWT operation was executed.
The owner still needs real integration tests after trusted resolution/decoding, including selector, refresh, tenant, secret-service failure and rollback cases. This helper is not an upstream patch, deployed control, detector or certificate of application security.
🩹 Remediation and verification:
1⃣. Establish the owner and exact condition. Map the affected runtime, active HMAC verifier, key resolver and token-consuming route. Confirm what reaches verification after trusted decoding and selection. Keep secret values out of routine records.
2⃣. Constrain an unresolved unsafe path. If empty material can become active, use the application/platform owner's supported access or feature controls while correcting it. Assess business continuity and recovery access. A network restriction cannot repair key validation or clear earlier actions.
3⃣. Reject invalid material before use. Validate zero length, appropriate cryptographic size, entropy, trusted provenance and lifecycle. Remove empty fallbacks from missing settings and key-refresh/secret-service failures. A bounded last-known-good policy needs explicit validity and revocation handling; it cannot become an indefinite exception.
4⃣. Keep policy independent. Configure allowed algorithms and key types from trusted application rules, and validate issuer, audience, time and token purpose appropriately. Algorithm allowlisting alone does not cure an empty key under an allowed HMAC algorithm. Plausible claim values are not independent signer evidence.
5⃣. Verify every serving state. Test the authorised integration, legitimate traffic and readiness behaviour across workers, refresh, error, tenant and rollback paths. Retain build/configuration/policy references and non-sensitive results. The package's safe helper tests do not perform this gate.
6⃣. Resolve historical consequences separately. Investigate unexplained acceptance/actions, durable sessions and downstream scope where supported. Use evidence-led revocation, credential and recovery decisions. A current sound key does not settle previous use, and empty-key exposure does not prove unrelated secrets were stolen.
Upstream fix position: no fixed release verified at 2026-11-03T09:37:27Z. PyPI/upstream identify 3.5.0, still within the CNA range. Track an authoritative correction and map it to the deployed build when available. Do not invent a version, relabel a last-affected commit as fixed or treat an arbitrary library migration as already validated.
🧾 Evidence separation:
Published facts are the CVE/CNA identity, condition, range, metrics and dated source states. The reporter's example is a source assertion, passively inspected. CyberForge's safeguards, SOC hypotheses and conditional ATT&CK mappings are analyst work. Local runtimes, real keys, traffic, incidents, deployed correction and recovery remain unassessed.
🔥 CyberForge verdict:
Prioritise confirmed empty effective HMAC material on reachable sensitive verification paths. The risk decision should follow the actual resolver and permission boundary, not just a package scanner, a severity headline or an unavailable forecast.
A dependable response validates the trust input before claims are accepted, then independently checks the operations those claims authorised. Enforce readiness across key activation and refresh, cover every worker, preserve the historical interval and keep any unresolved session or incident question owned.
A verification result is only as trustworthy as the key and policy behind it. Validate the trust input before trusting the claims.
🔗 Sources and further reading:
VulnCheck CNA advisory:
https://www.vulncheck.com/advisories/python-jose-through-3.5.0-authentication-bypass-via-empty-hmac-key
CVE and NVD:
https://www.cve.org/CVERecord?id=CVE-2026-120459
https://nvd.nist.gov/vuln/detail/CVE-2026-120459
Primary reporter issue, containing several separate findings:
https://github.com/mpdavis/python-jose/issues/398
Release/package state:
https://pypi.org/project/python-jose/
https://github.com/mpdavis/python-jose/releases
HMAC and JWT security guidance:
https://www.rfc-editor.org/rfc/rfc7518#section-3.2
https://www.rfc-editor.org/rfc/rfc8725
Dated prioritisation sources:
https://www.cisa.gov/known-exploited-vulnerabilities-catalog
https://api.first.org/data/v1/epss?cve=CVE-2026-120459
Read-only inventory / conditional ATT&CK:
https://pip.pypa.io/en/stable/cli/pip_show/
https://attack.mitre.org/techniques/T1606/
https://attack.mitre.org/techniques/T1550/001/
#CyberForge #CVE #Python #JWT #BlueTeam #SOC