Search
Find a vulnerability
Search criteria
16 vulnerabilities found for jose by potatosalad
CVE-2026-65632 (GCVE-0-2026-65632)
Vulnerability from nvd – Published: 2026-10-26 19:53 – Updated: 2026-10-26 19:53
VLAI
EPSS
VEX
Title
ECDSA signature length is not validated in jose, allowing signature malleability
Summary
The jose library accepts ECDSA (ES256, ES256K, ES384, and ES512) JWS signatures of a non-canonical length. When verifying an ECDSA signature, jose_jwk_kty_ec:verify/4 in src/jwk/jose_jwk_kty_ec.erl splits the raw signature in half by its actual byte length (split_binary(Signature, byte_size(Signature) div 2)) instead of enforcing the fixed length required by RFC 7518 §3.4, and then decodes each half with crypto:bytes_to_integer/1, which ignores leading zero bytes.
As a result, an attacker who holds one valid token can prepend leading zero bytes to each of the R and S halves to produce longer signatures that still split evenly and decode to the same (r, s) pair, so many distinct signature byte strings all verify against the same key (signature malleability). This does not allow forging new payloads or impersonating a signer, because the underlying (r, s) values are unchanged. It does defeat any security control that assumes a valid token or its signature is unique, such as token-revocation-by-hash, replay or idempotency caches, and deduplication logic.
This issue affects jose: from 1.0.0 before 1.11.13.
Severity
CWE
- CWE-347 - Improper Verification of Cryptographic Signature
Assigner
References
5 references
| URL | Tags |
|---|---|
| https://github.com/potatosalad/erlang-jose/securi… | vendor-advisoryrelated |
| https://cna.erlef.org/cves/CVE-2026-65632.html | related |
| https://osv.dev/vulnerability/EEF-CVE-2026-65632 | related |
| https://github.com/potatosalad/erlang-jose/commit… | related |
| https://github.com/potatosalad/erlang-jose/commit… | patch |
Impacted products
2 products
| Vendor | Product | Version | |
|---|---|---|---|
| potatosalad | jose |
Affected:
1.0.0 , < 1.11.13
(semver)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
|
| potatosalad | jose |
Affected:
a7746ecd4950f85a393136e449a91dac62b5c429 , < 72ce1866622b9329347dc52a94173ac0317bc9cf
(git)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
{
"containers": {
"cna": {
"affected": [
{
"collectionURL": "https://repo.hex.pm",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwk_kty_ec"
],
"packageName": "jose",
"packageURL": "pkg:hex/jose",
"product": "jose",
"programFiles": [
"src/jwk/jose_jwk_kty_ec.erl"
],
"programRoutines": [
{
"name": "jose_jwk_kty_ec:verify/4"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "1.11.13",
"status": "affected",
"version": "1.0.0",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwk_kty_ec"
],
"packageName": "potatosalad/erlang-jose",
"packageURL": "pkg:github/potatosalad/erlang-jose",
"product": "jose",
"programFiles": [
"src/jwk/jose_jwk_kty_ec.erl"
],
"programRoutines": [
{
"name": "jose_jwk_kty_ec:verify/4"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "72ce1866622b9329347dc52a94173ac0317bc9cf",
"status": "affected",
"version": "a7746ecd4950f85a393136e449a91dac62b5c429",
"versionType": "git"
}
]
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.11.13",
"versionStartIncluding": "1.0.0",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "AND"
}
],
"credits": [
{
"lang": "en",
"type": "reporter",
"value": "Peter Ullrich"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Andrew Bennett"
},
{
"lang": "en",
"type": "analyst",
"value": "Jonatan M\u00e4nnchen / EEF"
}
],
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eThe \u003ccode\u003ejose\u003c/code\u003e library accepts ECDSA (ES256, ES256K, ES384, and ES512) JWS signatures of a non-canonical length. When verifying an ECDSA signature, \u003ccode\u003ejose_jwk_kty_ec:verify/4\u003c/code\u003e in \u003ccode\u003esrc/jwk/jose_jwk_kty_ec.erl\u003c/code\u003e splits the raw signature in half by its actual byte length (\u003ccode\u003esplit_binary(Signature, byte_size(Signature) div 2)\u003c/code\u003e) instead of enforcing the fixed length required by RFC 7518 \u00a73.4, and then decodes each half with \u003ccode\u003ecrypto:bytes_to_integer/1\u003c/code\u003e, which ignores leading zero bytes.\u003c/p\u003e\n\u003cp\u003eAs a result, an attacker who holds one valid token can prepend leading zero bytes to each of the R and S halves to produce longer signatures that still split evenly and decode to the same \u003ccode\u003e(r, s)\u003c/code\u003e pair, so many distinct signature byte strings all verify against the same key (signature malleability). This does not allow forging new payloads or impersonating a signer, because the underlying \u003ccode\u003e(r, s)\u003c/code\u003e values are unchanged. It does defeat any security control that assumes a valid token or its signature is unique, such as token-revocation-by-hash, replay or idempotency caches, and deduplication logic.\u003c/p\u003e\n\u003cp\u003eThis issue affects jose: from 1.0.0 before 1.11.13.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "The `jose` library accepts ECDSA (ES256, ES256K, ES384, and ES512) JWS signatures of a non-canonical length. When verifying an ECDSA signature, `jose_jwk_kty_ec:verify/4` in `src/jwk/jose_jwk_kty_ec.erl` splits the raw signature in half by its actual byte length (`split_binary(Signature, byte_size(Signature) div 2)`) instead of enforcing the fixed length required by RFC 7518 \u00a73.4, and then decodes each half with `crypto:bytes_to_integer/1`, which ignores leading zero bytes.\n\nAs a result, an attacker who holds one valid token can prepend leading zero bytes to each of the R and S halves to produce longer signatures that still split evenly and decode to the same `(r, s)` pair, so many distinct signature byte strings all verify against the same key (signature malleability). This does not allow forging new payloads or impersonating a signer, because the underlying `(r, s)` values are unchanged. It does defeat any security control that assumes a valid token or its signature is unique, such as token-revocation-by-hash, replay or idempotency caches, and deduplication logic.\n\nThis issue affects jose: from 1.0.0 before 1.11.13."
}
],
"value": "The jose library accepts ECDSA (ES256, ES256K, ES384, and ES512) JWS signatures of a non-canonical length. When verifying an ECDSA signature, jose_jwk_kty_ec:verify/4 in src/jwk/jose_jwk_kty_ec.erl splits the raw signature in half by its actual byte length (split_binary(Signature, byte_size(Signature) div 2)) instead of enforcing the fixed length required by RFC 7518 \u00a73.4, and then decodes each half with crypto:bytes_to_integer/1, which ignores leading zero bytes.\n\nAs a result, an attacker who holds one valid token can prepend leading zero bytes to each of the R and S halves to produce longer signatures that still split evenly and decode to the same (r, s) pair, so many distinct signature byte strings all verify against the same key (signature malleability). This does not allow forging new payloads or impersonating a signer, because the underlying (r, s) values are unchanged. It does defeat any security control that assumes a valid token or its signature is unique, such as token-revocation-by-hash, replay or idempotency caches, and deduplication logic.\n\nThis issue affects jose: from 1.0.0 before 1.11.13."
}
],
"impacts": [
{
"capecId": "CAPEC-475",
"descriptions": [
{
"lang": "en",
"value": "CAPEC-475 Signature Spoofing by Improper Validation"
}
]
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "NONE",
"attackVector": "LOCAL",
"baseScore": 5.1,
"baseSeverity": "MEDIUM",
"privilegesRequired": "NONE",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N",
"version": "4.0",
"vulnAvailabilityImpact": "NONE",
"vulnConfidentialityImpact": "NONE",
"vulnIntegrityImpact": "LOW",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-347",
"description": "CWE-347 Improper Verification of Cryptographic Signature",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T19:53:56.649Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/security/advisories/GHSA-44hw-rpw9-mwg4"
},
{
"name": "EEF CNA record for CVE-2026-65632",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-65632.html"
},
{
"name": "OSV record EEF-CVE-2026-65632",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-65632"
},
{
"name": "Introducing commit a7746ec in potatosalad/erlang-jose",
"tags": [
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/a7746ecd4950f85a393136e449a91dac62b5c429"
},
{
"name": "Fix commit 72ce186 in potatosalad/erlang-jose",
"tags": [
"patch"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/72ce1866622b9329347dc52a94173ac0317bc9cf"
}
],
"source": {
"discovery": "EXTERNAL"
},
"title": "ECDSA signature length is not validated in jose, allowing signature malleability"
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-65632",
"datePublished": "2026-10-26T19:53:56.649Z",
"dateReserved": "2026-07-22T13:58:26.233Z",
"dateUpdated": "2026-10-26T19:53:56.649Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
CVE-2026-65631 (GCVE-0-2026-65631)
Vulnerability from nvd – Published: 2026-10-26 19:53 – Updated: 2026-10-26 19:53
VLAI
EPSS
VEX
Title
erlang-jose RSA JWK parsing attempts to factor an attacker-controlled modulus, enabling CPU-exhaustion denial of service
Summary
Inefficient Algorithmic Complexity in erlang-jose allows an unauthenticated remote attacker to cause a CPU-exhaustion denial of service by submitting a crafted RSA JSON Web Key.
When an application parses an untrusted JWK through the public jose_jwk:from_binary/1 or jose_jwk:from_map/1 API (or the Elixir wrappers JOSE.JWK.from_binary/1 and JOSE.JWK.from_map/1), an RSA private key that supplies d, e, and n but omits all Chinese Remainder Theorem parameters (p, q, dp, dq, qi) is routed into convert_sfm_to_crt/1, which tries to recover the missing primes by factoring the modulus. The three integers are read straight from the base64url input and are never validated as a real RSA key. When the modulus cannot be split into two factors (for example, when it is itself prime), the search loop convert_sfm_to_crt_find_p/6 performs a modular exponentiation over the attacker-sized modulus on every iteration and never succeeds. A single request of a few hundred bytes forces close to one CPU-second of work before an internal one-second watchdog kills the worker, and a larger modulus raises the cost further. By flooding such requests an attacker can saturate every scheduler and deny service, without credentials, a valid RSA key, or any special configuration.
This issue affects jose: from 1.7.7 before 1.11.13.
Severity
CWE
- CWE-407 - Inefficient Algorithmic Complexity
Assigner
References
5 references
| URL | Tags |
|---|---|
| https://github.com/potatosalad/erlang-jose/securi… | vendor-advisoryrelated |
| https://cna.erlef.org/cves/CVE-2026-65631.html | related |
| https://osv.dev/vulnerability/EEF-CVE-2026-65631 | related |
| https://github.com/potatosalad/erlang-jose/commit… | related |
| https://github.com/potatosalad/erlang-jose/commit… | patch |
Impacted products
2 products
| Vendor | Product | Version | |
|---|---|---|---|
| potatosalad | jose |
Affected:
1.7.7 , < 1.11.13
(semver)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
|
| potatosalad | jose |
Affected:
d19e1ba68d88c68d29aa942be2573a22dbafca1f , < bfd336c0062bff93e65d08c22361897e96afd956
(git)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
{
"containers": {
"cna": {
"affected": [
{
"collectionURL": "https://repo.hex.pm",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwk_kty_rsa",
"jose_jwk",
"\u0027Elixir.JOSE.JWK\u0027"
],
"packageName": "jose",
"packageURL": "pkg:hex/jose",
"product": "jose",
"programFiles": [
"src/jwk/jose_jwk_kty_rsa.erl",
"src/jwk/jose_jwk.erl",
"lib/jose/jwk.ex"
],
"programRoutines": [
{
"name": "jose_jwk_kty_rsa:from_map/1"
},
{
"name": "jose_jwk_kty_rsa:convert_sfm_to_crt/1"
},
{
"name": "jose_jwk_kty_rsa:convert_sfm_to_crt_find_p/6"
},
{
"name": "jose_jwk:from_binary/1"
},
{
"name": "jose_jwk:from_map/1"
},
{
"name": "\u0027Elixir.JOSE.JWK\u0027:from_binary/1"
},
{
"name": "\u0027Elixir.JOSE.JWK\u0027:from_map/1"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "1.11.13",
"status": "affected",
"version": "1.7.7",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwk_kty_rsa",
"jose_jwk",
"\u0027Elixir.JOSE.JWK\u0027"
],
"packageName": "potatosalad/erlang-jose",
"packageURL": "pkg:github/potatosalad/erlang-jose",
"product": "jose",
"programFiles": [
"src/jwk/jose_jwk_kty_rsa.erl",
"src/jwk/jose_jwk.erl",
"lib/jose/jwk.ex"
],
"programRoutines": [
{
"name": "jose_jwk_kty_rsa:from_map/1"
},
{
"name": "jose_jwk_kty_rsa:convert_sfm_to_crt/1"
},
{
"name": "jose_jwk_kty_rsa:convert_sfm_to_crt_find_p/6"
},
{
"name": "jose_jwk:from_binary/1"
},
{
"name": "jose_jwk:from_map/1"
},
{
"name": "\u0027Elixir.JOSE.JWK\u0027:from_binary/1"
},
{
"name": "\u0027Elixir.JOSE.JWK\u0027:from_map/1"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "bfd336c0062bff93e65d08c22361897e96afd956",
"status": "affected",
"version": "d19e1ba68d88c68d29aa942be2573a22dbafca1f",
"versionType": "git"
}
]
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.11.13",
"versionStartIncluding": "1.7.7",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "AND"
}
],
"credits": [
{
"lang": "en",
"type": "reporter",
"value": "Peter Ullrich"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Andrew Bennett"
},
{
"lang": "en",
"type": "analyst",
"value": "Jonatan M\u00e4nnchen / EEF"
}
],
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eInefficient Algorithmic Complexity in erlang-jose allows an unauthenticated remote attacker to cause a CPU-exhaustion denial of service by submitting a crafted RSA JSON Web Key.\u003c/p\u003e\n\u003cp\u003eWhen an application parses an untrusted JWK through the public \u003ccode\u003ejose_jwk:from_binary/1\u003c/code\u003e or \u003ccode\u003ejose_jwk:from_map/1\u003c/code\u003e API (or the Elixir wrappers \u003ccode\u003eJOSE.JWK.from_binary/1\u003c/code\u003e and \u003ccode\u003eJOSE.JWK.from_map/1\u003c/code\u003e), an RSA private key that supplies \u003ccode\u003ed\u003c/code\u003e, \u003ccode\u003ee\u003c/code\u003e, and \u003ccode\u003en\u003c/code\u003e but omits all Chinese Remainder Theorem parameters (\u003ccode\u003ep\u003c/code\u003e, \u003ccode\u003eq\u003c/code\u003e, \u003ccode\u003edp\u003c/code\u003e, \u003ccode\u003edq\u003c/code\u003e, \u003ccode\u003eqi\u003c/code\u003e) is routed into \u003ccode\u003econvert_sfm_to_crt/1\u003c/code\u003e, which tries to recover the missing primes by factoring the modulus. The three integers are read straight from the base64url input and are never validated as a real RSA key. When the modulus cannot be split into two factors (for example, when it is itself prime), the search loop \u003ccode\u003econvert_sfm_to_crt_find_p/6\u003c/code\u003e performs a modular exponentiation over the attacker-sized modulus on every iteration and never succeeds. A single request of a few hundred bytes forces close to one CPU-second of work before an internal one-second watchdog kills the worker, and a larger modulus raises the cost further. By flooding such requests an attacker can saturate every scheduler and deny service, without credentials, a valid RSA key, or any special configuration.\u003c/p\u003e\n\u003cp\u003eThis issue affects jose: from 1.7.7 before 1.11.13.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Inefficient Algorithmic Complexity in erlang-jose allows an unauthenticated remote attacker to cause a CPU-exhaustion denial of service by submitting a crafted RSA JSON Web Key.\n\nWhen an application parses an untrusted JWK through the public `jose_jwk:from_binary/1` or `jose_jwk:from_map/1` API (or the Elixir wrappers `JOSE.JWK.from_binary/1` and `JOSE.JWK.from_map/1`), an RSA private key that supplies `d`, `e`, and `n` but omits all Chinese Remainder Theorem parameters (`p`, `q`, `dp`, `dq`, `qi`) is routed into `convert_sfm_to_crt/1`, which tries to recover the missing primes by factoring the modulus. The three integers are read straight from the base64url input and are never validated as a real RSA key. When the modulus cannot be split into two factors (for example, when it is itself prime), the search loop `convert_sfm_to_crt_find_p/6` performs a modular exponentiation over the attacker-sized modulus on every iteration and never succeeds. A single request of a few hundred bytes forces close to one CPU-second of work before an internal one-second watchdog kills the worker, and a larger modulus raises the cost further. By flooding such requests an attacker can saturate every scheduler and deny service, without credentials, a valid RSA key, or any special configuration.\n\nThis issue affects jose: from 1.7.7 before 1.11.13."
}
],
"value": "Inefficient Algorithmic Complexity in erlang-jose allows an unauthenticated remote attacker to cause a CPU-exhaustion denial of service by submitting a crafted RSA JSON Web Key.\n\nWhen an application parses an untrusted JWK through the public jose_jwk:from_binary/1 or jose_jwk:from_map/1 API (or the Elixir wrappers JOSE.JWK.from_binary/1 and JOSE.JWK.from_map/1), an RSA private key that supplies d, e, and n but omits all Chinese Remainder Theorem parameters (p, q, dp, dq, qi) is routed into convert_sfm_to_crt/1, which tries to recover the missing primes by factoring the modulus. The three integers are read straight from the base64url input and are never validated as a real RSA key. When the modulus cannot be split into two factors (for example, when it is itself prime), the search loop convert_sfm_to_crt_find_p/6 performs a modular exponentiation over the attacker-sized modulus on every iteration and never succeeds. A single request of a few hundred bytes forces close to one CPU-second of work before an internal one-second watchdog kills the worker, and a larger modulus raises the cost further. By flooding such requests an attacker can saturate every scheduler and deny service, without credentials, a valid RSA key, or any special configuration.\n\nThis issue affects jose: from 1.7.7 before 1.11.13."
}
],
"impacts": [
{
"capecId": "CAPEC-130",
"descriptions": [
{
"lang": "en",
"value": "CAPEC-130 Excessive Allocation"
}
]
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "NONE",
"attackVector": "LOCAL",
"baseScore": 6.9,
"baseSeverity": "MEDIUM",
"privilegesRequired": "NONE",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N",
"version": "4.0",
"vulnAvailabilityImpact": "HIGH",
"vulnConfidentialityImpact": "NONE",
"vulnIntegrityImpact": "NONE",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-407",
"description": "CWE-407 Inefficient Algorithmic Complexity",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T19:53:45.204Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/security/advisories/GHSA-3m45-vrpj-xmrq"
},
{
"name": "EEF CNA record for CVE-2026-65631",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-65631.html"
},
{
"name": "OSV record EEF-CVE-2026-65631",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-65631"
},
{
"name": "Introducing commit d19e1ba in potatosalad/erlang-jose",
"tags": [
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/d19e1ba68d88c68d29aa942be2573a22dbafca1f"
},
{
"name": "Fix commit bfd336c in potatosalad/erlang-jose",
"tags": [
"patch"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/bfd336c0062bff93e65d08c22361897e96afd956"
}
],
"source": {
"discovery": "EXTERNAL"
},
"title": "erlang-jose RSA JWK parsing attempts to factor an attacker-controlled modulus, enabling CPU-exhaustion denial of service"
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-65631",
"datePublished": "2026-10-26T19:53:45.204Z",
"dateReserved": "2026-07-22T13:58:26.233Z",
"dateUpdated": "2026-10-26T19:53:45.204Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
CVE-2026-65630 (GCVE-0-2026-65630)
Vulnerability from nvd – Published: 2026-10-26 19:54 – Updated: 2026-10-26 19:54
VLAI
EPSS
VEX
Title
Timing side-channel in pure-Erlang X25519 scalar multiplication leaks the private key in jose
Summary
Observable Timing Discrepancy vulnerability in potatosalad jose allows recovery of a long-term X25519 private key through a timing side channel in the pure-Erlang Curve25519 fallback.
The pure-Erlang X25519 implementation performs scalar multiplication over the secret private key using a recursive Montgomery ladder (jose_jwa_x25519:curve25519/2) whose clauses branch on individual bits of the clamped private scalar, and whose per-step operations (jose_jwa_x25519:montgomery_add/3 and jose_jwa_x25519:montgomery_double/1) and field inversion are built from value-dependent Erlang bignum arithmetic (multiplication, remainder, and modular exponentiation). Although the ladder is operation-count balanced and fixed at 254 steps, the concrete integer values processed at each step, and therefore the running time, depend on the secret scalar. The execution time of the public entry points jose_jwa_x25519:scalarmult/2, jose_jwa_x25519:x25519/2, jose_jwa_x25519:x25519_base/1, and jose_jwa_x25519:sk_to_pk/1 is thus a function of the private key.
This path is reachable from the public API, most notably when a service decrypts attacker-supplied ECDH-ES (JWE) messages with a long-term X25519 key (for example through JOSE.JWK.box_decrypt_ecdh_es/2, which reaches jose_jwa_curve25519:x25519_shared_secret/2 and the ladder). An attacker who can submit ciphertexts and measure decryption timing can, in principle, recover the private key bit by bit, defeating the resistance X25519 was designed to provide. Recovery of the key compromises the confidentiality and authenticity of all data protected by it.
This issue affects jose: from 1.10.0 before 1.11.13.
Severity
CWE
- CWE-208 - Observable Timing Discrepancy
Assigner
References
5 references
| URL | Tags |
|---|---|
| https://github.com/potatosalad/erlang-jose/securi… | vendor-advisoryrelated |
| https://cna.erlef.org/cves/CVE-2026-65630.html | related |
| https://osv.dev/vulnerability/EEF-CVE-2026-65630 | related |
| https://github.com/potatosalad/erlang-jose/commit… | related |
| https://github.com/potatosalad/erlang-jose/commit… | patch |
Impacted products
2 products
| Vendor | Product | Version | |
|---|---|---|---|
| potatosalad | jose |
Affected:
1.10.0 , < 1.11.13
(semver)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
|
| potatosalad | jose |
Affected:
8e532095de114ef4bf88a9ec5d651fa251a972b3 , < 3670f873c274bba86fb7f5ee5727a7efa1322b79
(git)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
{
"containers": {
"cna": {
"affected": [
{
"collectionURL": "https://repo.hex.pm",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwa_x25519",
"jose_jwa_curve25519",
"jose_curve25519_fallback",
"jose_jwk_kty_okp_x25519"
],
"packageName": "jose",
"packageURL": "pkg:hex/jose",
"product": "jose",
"programFiles": [
"src/jwa/jose_jwa_x25519.erl",
"src/jwa/jose_jwa_curve25519.erl",
"src/jwa/curve25519/jose_curve25519_fallback.erl",
"src/jwk/jose_jwk_kty_okp_x25519.erl"
],
"programRoutines": [
{
"name": "jose_jwa_x25519:curve25519/2"
},
{
"name": "jose_jwa_x25519:scalarmult/2"
},
{
"name": "jose_jwa_x25519:scalarmult_base/1"
},
{
"name": "jose_jwa_x25519:x25519/2"
},
{
"name": "jose_jwa_x25519:x25519_base/1"
},
{
"name": "jose_jwa_x25519:sk_to_pk/1"
},
{
"name": "jose_jwa_x25519:montgomery_add/3"
},
{
"name": "jose_jwa_x25519:montgomery_double/1"
},
{
"name": "jose_jwa_curve25519:x25519_shared_secret/2"
},
{
"name": "jose_jwa_curve25519:x25519_secret_to_public/1"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "1.11.13",
"status": "affected",
"version": "1.10.0",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwa_x25519",
"jose_jwa_curve25519",
"jose_curve25519_fallback",
"jose_jwk_kty_okp_x25519"
],
"packageName": "potatosalad/erlang-jose",
"packageURL": "pkg:github/potatosalad/erlang-jose",
"product": "jose",
"programFiles": [
"src/jwa/jose_jwa_x25519.erl",
"src/jwa/jose_jwa_curve25519.erl",
"src/jwa/curve25519/jose_curve25519_fallback.erl",
"src/jwk/jose_jwk_kty_okp_x25519.erl"
],
"programRoutines": [
{
"name": "jose_jwa_x25519:curve25519/2"
},
{
"name": "jose_jwa_x25519:scalarmult/2"
},
{
"name": "jose_jwa_x25519:scalarmult_base/1"
},
{
"name": "jose_jwa_x25519:x25519/2"
},
{
"name": "jose_jwa_x25519:x25519_base/1"
},
{
"name": "jose_jwa_x25519:sk_to_pk/1"
},
{
"name": "jose_jwa_x25519:montgomery_add/3"
},
{
"name": "jose_jwa_x25519:montgomery_double/1"
},
{
"name": "jose_jwa_curve25519:x25519_shared_secret/2"
},
{
"name": "jose_jwa_curve25519:x25519_secret_to_public/1"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "3670f873c274bba86fb7f5ee5727a7efa1322b79",
"status": "affected",
"version": "8e532095de114ef4bf88a9ec5d651fa251a972b3",
"versionType": "git"
}
]
}
],
"configurations": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eThe vulnerability is only exploitable when X25519 private-key operations run through the pure-Erlang Curve25519 fallback, for example when the crypto fallback is enabled (\u003ccode\u003eJOSE.crypto_fallback(true)\u003c/code\u003e or \u003ccode\u003eJOSE.curve25519_module(:jose_jwa_curve25519)\u003c/code\u003e) or when no constant-time native X25519 implementation (a libsodium or libdecaf NIF, or the OTP \u003ccode\u003ecrypto\u003c/code\u003e application providing \u003ccode\u003ex25519\u003c/code\u003e) is available. Deployments that use a constant-time native X25519 are not affected.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "The vulnerability is only exploitable when X25519 private-key operations run through the pure-Erlang Curve25519 fallback, for example when the crypto fallback is enabled (`JOSE.crypto_fallback(true)` or `JOSE.curve25519_module(:jose_jwa_curve25519)`) or when no constant-time native X25519 implementation (a libsodium or libdecaf NIF, or the OTP `crypto` application providing `x25519`) is available. Deployments that use a constant-time native X25519 are not affected."
}
],
"value": "The vulnerability is only exploitable when X25519 private-key operations run through the pure-Erlang Curve25519 fallback, for example when the crypto fallback is enabled (JOSE.crypto_fallback(true) or JOSE.curve25519_module(:jose_jwa_curve25519)) or when no constant-time native X25519 implementation (a libsodium or libdecaf NIF, or the OTP crypto application providing x25519) is available. Deployments that use a constant-time native X25519 are not affected."
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.11.13",
"versionStartIncluding": "1.10.0",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "AND"
}
],
"credits": [
{
"lang": "en",
"type": "reporter",
"value": "Peter Ullrich"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Andrew Bennett"
},
{
"lang": "en",
"type": "analyst",
"value": "Jonatan M\u00e4nnchen / EEF"
}
],
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eObservable Timing Discrepancy vulnerability in potatosalad jose allows recovery of a long-term X25519 private key through a timing side channel in the pure-Erlang Curve25519 fallback.\u003c/p\u003e\n\u003cp\u003eThe pure-Erlang X25519 implementation performs scalar multiplication over the secret private key using a recursive Montgomery ladder (\u003ccode\u003ejose_jwa_x25519:curve25519/2\u003c/code\u003e) whose clauses branch on individual bits of the clamped private scalar, and whose per-step operations (\u003ccode\u003ejose_jwa_x25519:montgomery_add/3\u003c/code\u003e and \u003ccode\u003ejose_jwa_x25519:montgomery_double/1\u003c/code\u003e) and field inversion are built from value-dependent Erlang bignum arithmetic (multiplication, remainder, and modular exponentiation). Although the ladder is operation-count balanced and fixed at 254 steps, the concrete integer values processed at each step, and therefore the running time, depend on the secret scalar. The execution time of the public entry points \u003ccode\u003ejose_jwa_x25519:scalarmult/2\u003c/code\u003e, \u003ccode\u003ejose_jwa_x25519:x25519/2\u003c/code\u003e, \u003ccode\u003ejose_jwa_x25519:x25519_base/1\u003c/code\u003e, and \u003ccode\u003ejose_jwa_x25519:sk_to_pk/1\u003c/code\u003e is thus a function of the private key.\u003c/p\u003e\n\u003cp\u003eThis path is reachable from the public API, most notably when a service decrypts attacker-supplied ECDH-ES (JWE) messages with a long-term X25519 key (for example through \u003ccode\u003eJOSE.JWK.box_decrypt_ecdh_es/2\u003c/code\u003e, which reaches \u003ccode\u003ejose_jwa_curve25519:x25519_shared_secret/2\u003c/code\u003e and the ladder). An attacker who can submit ciphertexts and measure decryption timing can, in principle, recover the private key bit by bit, defeating the resistance X25519 was designed to provide. Recovery of the key compromises the confidentiality and authenticity of all data protected by it.\u003c/p\u003e\n\u003cp\u003eThis issue affects jose: from 1.10.0 before 1.11.13.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Observable Timing Discrepancy vulnerability in potatosalad jose allows recovery of a long-term X25519 private key through a timing side channel in the pure-Erlang Curve25519 fallback.\n\nThe pure-Erlang X25519 implementation performs scalar multiplication over the secret private key using a recursive Montgomery ladder (`jose_jwa_x25519:curve25519/2`) whose clauses branch on individual bits of the clamped private scalar, and whose per-step operations (`jose_jwa_x25519:montgomery_add/3` and `jose_jwa_x25519:montgomery_double/1`) and field inversion are built from value-dependent Erlang bignum arithmetic (multiplication, remainder, and modular exponentiation). Although the ladder is operation-count balanced and fixed at 254 steps, the concrete integer values processed at each step, and therefore the running time, depend on the secret scalar. The execution time of the public entry points `jose_jwa_x25519:scalarmult/2`, `jose_jwa_x25519:x25519/2`, `jose_jwa_x25519:x25519_base/1`, and `jose_jwa_x25519:sk_to_pk/1` is thus a function of the private key.\n\nThis path is reachable from the public API, most notably when a service decrypts attacker-supplied ECDH-ES (JWE) messages with a long-term X25519 key (for example through `JOSE.JWK.box_decrypt_ecdh_es/2`, which reaches `jose_jwa_curve25519:x25519_shared_secret/2` and the ladder). An attacker who can submit ciphertexts and measure decryption timing can, in principle, recover the private key bit by bit, defeating the resistance X25519 was designed to provide. Recovery of the key compromises the confidentiality and authenticity of all data protected by it.\n\nThis issue affects jose: from 1.10.0 before 1.11.13."
}
],
"value": "Observable Timing Discrepancy vulnerability in potatosalad jose allows recovery of a long-term X25519 private key through a timing side channel in the pure-Erlang Curve25519 fallback.\n\nThe pure-Erlang X25519 implementation performs scalar multiplication over the secret private key using a recursive Montgomery ladder (jose_jwa_x25519:curve25519/2) whose clauses branch on individual bits of the clamped private scalar, and whose per-step operations (jose_jwa_x25519:montgomery_add/3 and jose_jwa_x25519:montgomery_double/1) and field inversion are built from value-dependent Erlang bignum arithmetic (multiplication, remainder, and modular exponentiation). Although the ladder is operation-count balanced and fixed at 254 steps, the concrete integer values processed at each step, and therefore the running time, depend on the secret scalar. The execution time of the public entry points jose_jwa_x25519:scalarmult/2, jose_jwa_x25519:x25519/2, jose_jwa_x25519:x25519_base/1, and jose_jwa_x25519:sk_to_pk/1 is thus a function of the private key.\n\nThis path is reachable from the public API, most notably when a service decrypts attacker-supplied ECDH-ES (JWE) messages with a long-term X25519 key (for example through JOSE.JWK.box_decrypt_ecdh_es/2, which reaches jose_jwa_curve25519:x25519_shared_secret/2 and the ladder). An attacker who can submit ciphertexts and measure decryption timing can, in principle, recover the private key bit by bit, defeating the resistance X25519 was designed to provide. Recovery of the key compromises the confidentiality and authenticity of all data protected by it.\n\nThis issue affects jose: from 1.10.0 before 1.11.13."
}
],
"impacts": [
{
"capecId": "CAPEC-97",
"descriptions": [
{
"lang": "en",
"value": "CAPEC-97 Cryptanalysis"
}
]
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "HIGH",
"attackRequirements": "PRESENT",
"attackVector": "LOCAL",
"baseScore": 5.9,
"baseSeverity": "MEDIUM",
"privilegesRequired": "NONE",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:L/AC:H/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N",
"version": "4.0",
"vulnAvailabilityImpact": "NONE",
"vulnConfidentialityImpact": "HIGH",
"vulnIntegrityImpact": "NONE",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-208",
"description": "CWE-208 Observable Timing Discrepancy",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T19:54:07.686Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/security/advisories/GHSA-xvr2-gggj-h2pp"
},
{
"name": "EEF CNA record for CVE-2026-65630",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-65630.html"
},
{
"name": "OSV record EEF-CVE-2026-65630",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-65630"
},
{
"name": "Introducing commit 8e53209 in potatosalad/erlang-jose",
"tags": [
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/8e532095de114ef4bf88a9ec5d651fa251a972b3"
},
{
"name": "Fix commit 3670f87 in potatosalad/erlang-jose",
"tags": [
"patch"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/3670f873c274bba86fb7f5ee5727a7efa1322b79"
}
],
"source": {
"discovery": "EXTERNAL"
},
"title": "Timing side-channel in pure-Erlang X25519 scalar multiplication leaks the private key in jose",
"workarounds": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eUse a constant-time native X25519 implementation for private-key operations: install the libsodium or libdecaf NIF, or run on an OTP release whose \u003ccode\u003ecrypto\u003c/code\u003e application provides \u003ccode\u003ex25519\u003c/code\u003e, and do not force the pure-Erlang Curve25519 fallback (\u003ccode\u003eJOSE.crypto_fallback(true)\u003c/code\u003e or \u003ccode\u003eJOSE.curve25519_module(:jose_jwa_curve25519)\u003c/code\u003e) for long-lived keys.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Use a constant-time native X25519 implementation for private-key operations: install the libsodium or libdecaf NIF, or run on an OTP release whose `crypto` application provides `x25519`, and do not force the pure-Erlang Curve25519 fallback (`JOSE.crypto_fallback(true)` or `JOSE.curve25519_module(:jose_jwa_curve25519)`) for long-lived keys."
}
],
"value": "Use a constant-time native X25519 implementation for private-key operations: install the libsodium or libdecaf NIF, or run on an OTP release whose crypto application provides x25519, and do not force the pure-Erlang Curve25519 fallback (JOSE.crypto_fallback(true) or JOSE.curve25519_module(:jose_jwa_curve25519)) for long-lived keys."
}
]
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-65630",
"datePublished": "2026-10-26T19:54:07.686Z",
"dateReserved": "2026-07-22T13:58:26.233Z",
"dateUpdated": "2026-10-26T19:54:07.686Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
CVE-2026-65629 (GCVE-0-2026-65629)
Vulnerability from nvd – Published: 2026-10-26 19:53 – Updated: 2026-10-26 19:53
VLAI
EPSS
VEX
Title
Weak PBKDF2 parameters for password-encrypted private-key export in jose
Summary
Use of Password Hash With Insufficient Computational Effort in the jose library allows an attacker who obtains a password-encrypted private-key export to recover the private key through an offline password-cracking attack.
When jose exports a password-encrypted private key with jose_jwk:to_der/2 (JOSE.JWK.to_der/2), the jose_jwk_der:to_binary/3 function in src/jwk/jose_jwk_der.erl serializes the key as a PKCS#8 EncryptedPrivateKeyInfo using the PBES2 scheme with hardcoded key-derivation parameters: PBKDF2-HMAC-SHA256 with an iteration count of 2048 and an 8-byte (64-bit) random salt. Neither value can be overridden by the caller.
Both values are far below current guidance (OWASP recommends on the order of 600,000 iterations for PBKDF2-HMAC-SHA256, and NIST recommends salts of at least 128 bits), so the key-stretching work factor is roughly 300 times lower than intended and the short salt reduces the cost of precomputation across keys. The symmetric encryption (AES-256-CBC with a 16-byte random IV) is not affected; the weakness is entirely in the derivation strength. An attacker who obtains one of these exported blobs (for example from a backup, configuration repository, object storage, or logs) can mount a cheap offline dictionary or brute-force attack against the export password, and success yields the full private key.
This issue affects jose: from 1.10.0 before 1.11.13.
Severity
CWE
- CWE-916 - Use of Password Hash With Insufficient Computational Effort
Assigner
References
5 references
| URL | Tags |
|---|---|
| https://github.com/potatosalad/erlang-jose/securi… | vendor-advisoryrelated |
| https://cna.erlef.org/cves/CVE-2026-65629.html | related |
| https://osv.dev/vulnerability/EEF-CVE-2026-65629 | related |
| https://github.com/potatosalad/erlang-jose/commit… | related |
| https://github.com/potatosalad/erlang-jose/commit… | patch |
Impacted products
2 products
| Vendor | Product | Version | |
|---|---|---|---|
| potatosalad | jose |
Affected:
1.10.0 , < 1.11.13
(semver)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
|
| potatosalad | jose |
Affected:
85fddd89ee56b6f9c19eff7d9cfffeef62c330b9 , < 461b261902531ca016190e780bb70862d561a7e0
(git)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
{
"containers": {
"cna": {
"affected": [
{
"collectionURL": "https://repo.hex.pm",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwk_der",
"jose_jwk",
"\u0027Elixir.JOSE.JWK\u0027"
],
"packageName": "jose",
"packageURL": "pkg:hex/jose",
"product": "jose",
"programFiles": [
"src/jwk/jose_jwk_der.erl",
"src/jwk/jose_jwk.erl",
"lib/jose/jwk.ex"
],
"programRoutines": [
{
"name": "jose_jwk_der:to_binary/3"
},
{
"name": "jose_jwk:to_der/2"
},
{
"name": "\u0027Elixir.JOSE.JWK\u0027:to_der/2"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "1.11.13",
"status": "affected",
"version": "1.10.0",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwk_der",
"jose_jwk",
"\u0027Elixir.JOSE.JWK\u0027"
],
"packageName": "potatosalad/erlang-jose",
"packageURL": "pkg:github/potatosalad/erlang-jose",
"product": "jose",
"programFiles": [
"src/jwk/jose_jwk_der.erl",
"src/jwk/jose_jwk.erl",
"lib/jose/jwk.ex"
],
"programRoutines": [
{
"name": "jose_jwk_der:to_binary/3"
},
{
"name": "jose_jwk:to_der/2"
},
{
"name": "\u0027Elixir.JOSE.JWK\u0027:to_der/2"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "461b261902531ca016190e780bb70862d561a7e0",
"status": "affected",
"version": "85fddd89ee56b6f9c19eff7d9cfffeef62c330b9",
"versionType": "git"
}
]
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.11.13",
"versionStartIncluding": "1.10.0",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "AND"
}
],
"credits": [
{
"lang": "en",
"type": "reporter",
"value": "Peter Ullrich"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Andrew Bennett"
},
{
"lang": "en",
"type": "analyst",
"value": "Jonatan M\u00e4nnchen / EEF"
}
],
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eUse of Password Hash With Insufficient Computational Effort in the jose library allows an attacker who obtains a password-encrypted private-key export to recover the private key through an offline password-cracking attack.\u003c/p\u003e\n\u003cp\u003eWhen jose exports a password-encrypted private key with \u003ccode\u003ejose_jwk:to_der/2\u003c/code\u003e (\u003ccode\u003eJOSE.JWK.to_der/2\u003c/code\u003e), the \u003ccode\u003ejose_jwk_der:to_binary/3\u003c/code\u003e function in \u003ccode\u003esrc/jwk/jose_jwk_der.erl\u003c/code\u003e serializes the key as a \u003ccode\u003ePKCS#8\u003c/code\u003e \u003ccode\u003eEncryptedPrivateKeyInfo\u003c/code\u003e using the PBES2 scheme with hardcoded key-derivation parameters: PBKDF2-HMAC-SHA256 with an iteration count of 2048 and an 8-byte (64-bit) random salt. Neither value can be overridden by the caller.\u003c/p\u003e\n\u003cp\u003eBoth values are far below current guidance (OWASP recommends on the order of 600,000 iterations for PBKDF2-HMAC-SHA256, and NIST recommends salts of at least 128 bits), so the key-stretching work factor is roughly 300 times lower than intended and the short salt reduces the cost of precomputation across keys. The symmetric encryption (AES-256-CBC with a 16-byte random IV) is not affected; the weakness is entirely in the derivation strength. An attacker who obtains one of these exported blobs (for example from a backup, configuration repository, object storage, or logs) can mount a cheap offline dictionary or brute-force attack against the export password, and success yields the full private key.\u003c/p\u003e\n\u003cp\u003eThis issue affects jose: from 1.10.0 before 1.11.13.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Use of Password Hash With Insufficient Computational Effort in the jose library allows an attacker who obtains a password-encrypted private-key export to recover the private key through an offline password-cracking attack.\n\nWhen jose exports a password-encrypted private key with `jose_jwk:to_der/2` (`JOSE.JWK.to_der/2`), the `jose_jwk_der:to_binary/3` function in `src/jwk/jose_jwk_der.erl` serializes the key as a `PKCS#8` `EncryptedPrivateKeyInfo` using the PBES2 scheme with hardcoded key-derivation parameters: PBKDF2-HMAC-SHA256 with an iteration count of 2048 and an 8-byte (64-bit) random salt. Neither value can be overridden by the caller.\n\nBoth values are far below current guidance (OWASP recommends on the order of 600,000 iterations for PBKDF2-HMAC-SHA256, and NIST recommends salts of at least 128 bits), so the key-stretching work factor is roughly 300 times lower than intended and the short salt reduces the cost of precomputation across keys. The symmetric encryption (AES-256-CBC with a 16-byte random IV) is not affected; the weakness is entirely in the derivation strength. An attacker who obtains one of these exported blobs (for example from a backup, configuration repository, object storage, or logs) can mount a cheap offline dictionary or brute-force attack against the export password, and success yields the full private key.\n\nThis issue affects jose: from 1.10.0 before 1.11.13."
}
],
"value": "Use of Password Hash With Insufficient Computational Effort in the jose library allows an attacker who obtains a password-encrypted private-key export to recover the private key through an offline password-cracking attack.\n\nWhen jose exports a password-encrypted private key with jose_jwk:to_der/2 (JOSE.JWK.to_der/2), the jose_jwk_der:to_binary/3 function in src/jwk/jose_jwk_der.erl serializes the key as a PKCS#8 EncryptedPrivateKeyInfo using the PBES2 scheme with hardcoded key-derivation parameters: PBKDF2-HMAC-SHA256 with an iteration count of 2048 and an 8-byte (64-bit) random salt. Neither value can be overridden by the caller.\n\nBoth values are far below current guidance (OWASP recommends on the order of 600,000 iterations for PBKDF2-HMAC-SHA256, and NIST recommends salts of at least 128 bits), so the key-stretching work factor is roughly 300 times lower than intended and the short salt reduces the cost of precomputation across keys. The symmetric encryption (AES-256-CBC with a 16-byte random IV) is not affected; the weakness is entirely in the derivation strength. An attacker who obtains one of these exported blobs (for example from a backup, configuration repository, object storage, or logs) can mount a cheap offline dictionary or brute-force attack against the export password, and success yields the full private key.\n\nThis issue affects jose: from 1.10.0 before 1.11.13."
}
],
"impacts": [
{
"capecId": "CAPEC-16",
"descriptions": [
{
"lang": "en",
"value": "CAPEC-16 Dictionary-based Password Attack"
}
]
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "PRESENT",
"attackVector": "LOCAL",
"baseScore": 7.4,
"baseSeverity": "HIGH",
"privilegesRequired": "NONE",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N",
"version": "4.0",
"vulnAvailabilityImpact": "NONE",
"vulnConfidentialityImpact": "HIGH",
"vulnIntegrityImpact": "HIGH",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-916",
"description": "CWE-916 Use of Password Hash With Insufficient Computational Effort",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T19:53:35.646Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/security/advisories/GHSA-h4gx-8jq2-mfhc"
},
{
"name": "EEF CNA record for CVE-2026-65629",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-65629.html"
},
{
"name": "OSV record EEF-CVE-2026-65629",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-65629"
},
{
"name": "Introducing commit 85fddd8 in potatosalad/erlang-jose",
"tags": [
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/85fddd89ee56b6f9c19eff7d9cfffeef62c330b9"
},
{
"name": "Fix commit 461b261 in potatosalad/erlang-jose",
"tags": [
"patch"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/461b261902531ca016190e780bb70862d561a7e0"
}
],
"source": {
"discovery": "EXTERNAL"
},
"title": "Weak PBKDF2 parameters for password-encrypted private-key export in jose",
"workarounds": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eWhen exporting a password-encrypted private key with \u003ccode\u003ejose_jwk:to_der/2\u003c/code\u003e (\u003ccode\u003eJOSE.JWK.to_der/2\u003c/code\u003e), use a long, high-entropy passphrase, since the weak key-derivation work factor only meaningfully lowers the cost of cracking guessable passwords. Restrict access to exported \u003ccode\u003eEncryptedPrivateKeyInfo\u003c/code\u003e blobs and keep them out of backups, repositories, object storage, and logs that an attacker could read.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "When exporting a password-encrypted private key with `jose_jwk:to_der/2` (`JOSE.JWK.to_der/2`), use a long, high-entropy passphrase, since the weak key-derivation work factor only meaningfully lowers the cost of cracking guessable passwords. Restrict access to exported `EncryptedPrivateKeyInfo` blobs and keep them out of backups, repositories, object storage, and logs that an attacker could read."
}
],
"value": "When exporting a password-encrypted private key with jose_jwk:to_der/2 (JOSE.JWK.to_der/2), use a long, high-entropy passphrase, since the weak key-derivation work factor only meaningfully lowers the cost of cracking guessable passwords. Restrict access to exported EncryptedPrivateKeyInfo blobs and keep them out of backups, repositories, object storage, and logs that an attacker could read."
}
]
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-65629",
"datePublished": "2026-10-26T19:53:35.646Z",
"dateReserved": "2026-07-22T13:58:26.233Z",
"dateUpdated": "2026-10-26T19:53:35.646Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
CVE-2026-65628 (GCVE-0-2026-65628)
Vulnerability from nvd – Published: 2026-10-26 19:53 – Updated: 2026-10-26 19:53
VLAI
EPSS
VEX
Title
Infinite recursion (CPU denial-of-service) in JOSE.JWK.shared_secret/2 on mismatched key types
Summary
jose_jwk:shared_secret/2 (exposed in Elixir as JOSE.JWK.shared_secret/2) derives an ECDH shared secret from two JWKs. Its first function clause only matches when both JWKs carry the same key type (kty) module, and its fallback clause re-invokes itself as shared_secret(from(YourJWK), from(MyJWK)). Because from/1 returns an already-parsed jose_jwk record unchanged, passing two JWKs whose key types differ (for example an EC key and an RSA key) makes the fallback clause re-enter with identical arguments, producing an unbounded tail-recursive loop that never returns and never crashes.
An application that derives a shared secret from an externally supplied peer public key without first checking that the peer key's type and curve match its own key can be driven into this loop by an attacker-controlled JWK, pinning an Erlang scheduler at 100% CPU. Repeated requests exhaust the available schedulers, resulting in a denial of service.
This issue affects jose: from 1.5.0 before 1.11.13.
Severity
CWE
- CWE-674 - Uncontrolled Recursion
Assigner
References
5 references
| URL | Tags |
|---|---|
| https://github.com/potatosalad/erlang-jose/securi… | vendor-advisoryrelated |
| https://cna.erlef.org/cves/CVE-2026-65628.html | related |
| https://osv.dev/vulnerability/EEF-CVE-2026-65628 | related |
| https://github.com/potatosalad/erlang-jose/commit… | related |
| https://github.com/potatosalad/erlang-jose/commit… | patch |
Impacted products
2 products
| Vendor | Product | Version | |
|---|---|---|---|
| potatosalad | jose |
Affected:
1.5.0 , < 1.11.13
(semver)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
|
| potatosalad | jose |
Affected:
7b80b9f55b9898e1a6901ce136061b241b021d7c , < 26182a7de63b91550035d3f08741f7d17f1f675a
(git)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
{
"containers": {
"cna": {
"affected": [
{
"collectionURL": "https://repo.hex.pm",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwk"
],
"packageName": "jose",
"packageURL": "pkg:hex/jose",
"product": "jose",
"programFiles": [
"src/jwk/jose_jwk.erl"
],
"programRoutines": [
{
"name": "jose_jwk:shared_secret/2"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "1.11.13",
"status": "affected",
"version": "1.5.0",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwk"
],
"packageName": "potatosalad/erlang-jose",
"packageURL": "pkg:github/potatosalad/erlang-jose",
"product": "jose",
"programFiles": [
"src/jwk/jose_jwk.erl"
],
"programRoutines": [
{
"name": "jose_jwk:shared_secret/2"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "26182a7de63b91550035d3f08741f7d17f1f675a",
"status": "affected",
"version": "7b80b9f55b9898e1a6901ce136061b241b021d7c",
"versionType": "git"
}
]
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.11.13",
"versionStartIncluding": "1.5.0",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "AND"
}
],
"credits": [
{
"lang": "en",
"type": "reporter",
"value": "Peter Ullrich"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Andrew Bennett"
},
{
"lang": "en",
"type": "analyst",
"value": "Jonatan M\u00e4nnchen / EEF"
}
],
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003e\u003ccode\u003ejose_jwk:shared_secret/2\u003c/code\u003e (exposed in Elixir as \u003ccode\u003eJOSE.JWK.shared_secret/2\u003c/code\u003e) derives an ECDH shared secret from two JWKs. Its first function clause only matches when both JWKs carry the same key type (\u003ccode\u003ekty\u003c/code\u003e) module, and its fallback clause re-invokes itself as \u003ccode\u003eshared_secret(from(YourJWK), from(MyJWK))\u003c/code\u003e. Because \u003ccode\u003efrom/1\u003c/code\u003e returns an already-parsed \u003ccode\u003ejose_jwk\u003c/code\u003e record unchanged, passing two JWKs whose key types differ (for example an EC key and an RSA key) makes the fallback clause re-enter with identical arguments, producing an unbounded tail-recursive loop that never returns and never crashes.\u003c/p\u003e\n\u003cp\u003eAn application that derives a shared secret from an externally supplied peer public key without first checking that the peer key\u0027s type and curve match its own key can be driven into this loop by an attacker-controlled JWK, pinning an Erlang scheduler at 100% CPU. Repeated requests exhaust the available schedulers, resulting in a denial of service.\u003c/p\u003e\n\u003cp\u003eThis issue affects jose: from 1.5.0 before 1.11.13.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "`jose_jwk:shared_secret/2` (exposed in Elixir as `JOSE.JWK.shared_secret/2`) derives an ECDH shared secret from two JWKs. Its first function clause only matches when both JWKs carry the same key type (`kty`) module, and its fallback clause re-invokes itself as `shared_secret(from(YourJWK), from(MyJWK))`. Because `from/1` returns an already-parsed `jose_jwk` record unchanged, passing two JWKs whose key types differ (for example an EC key and an RSA key) makes the fallback clause re-enter with identical arguments, producing an unbounded tail-recursive loop that never returns and never crashes.\n\nAn application that derives a shared secret from an externally supplied peer public key without first checking that the peer key\u0027s type and curve match its own key can be driven into this loop by an attacker-controlled JWK, pinning an Erlang scheduler at 100% CPU. Repeated requests exhaust the available schedulers, resulting in a denial of service.\n\nThis issue affects jose: from 1.5.0 before 1.11.13."
}
],
"value": "jose_jwk:shared_secret/2 (exposed in Elixir as JOSE.JWK.shared_secret/2) derives an ECDH shared secret from two JWKs. Its first function clause only matches when both JWKs carry the same key type (kty) module, and its fallback clause re-invokes itself as shared_secret(from(YourJWK), from(MyJWK)). Because from/1 returns an already-parsed jose_jwk record unchanged, passing two JWKs whose key types differ (for example an EC key and an RSA key) makes the fallback clause re-enter with identical arguments, producing an unbounded tail-recursive loop that never returns and never crashes.\n\nAn application that derives a shared secret from an externally supplied peer public key without first checking that the peer key\u0027s type and curve match its own key can be driven into this loop by an attacker-controlled JWK, pinning an Erlang scheduler at 100% CPU. Repeated requests exhaust the available schedulers, resulting in a denial of service.\n\nThis issue affects jose: from 1.5.0 before 1.11.13."
}
],
"impacts": [
{
"capecId": "CAPEC-130",
"descriptions": [
{
"lang": "en",
"value": "CAPEC-130 Excessive Allocation"
}
]
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "PRESENT",
"attackVector": "LOCAL",
"baseScore": 5.9,
"baseSeverity": "MEDIUM",
"privilegesRequired": "NONE",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N",
"version": "4.0",
"vulnAvailabilityImpact": "HIGH",
"vulnConfidentialityImpact": "NONE",
"vulnIntegrityImpact": "NONE",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-674",
"description": "CWE-674 Uncontrolled Recursion",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T19:53:27.625Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/security/advisories/GHSA-fpj2-9h59-32pp"
},
{
"name": "EEF CNA record for CVE-2026-65628",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-65628.html"
},
{
"name": "OSV record EEF-CVE-2026-65628",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-65628"
},
{
"name": "Introducing commit 7b80b9f in potatosalad/erlang-jose",
"tags": [
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/7b80b9f55b9898e1a6901ce136061b241b021d7c"
},
{
"name": "Fix commit 26182a7 in potatosalad/erlang-jose",
"tags": [
"patch"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/26182a7de63b91550035d3f08741f7d17f1f675a"
}
],
"source": {
"discovery": "EXTERNAL"
},
"title": "Infinite recursion (CPU denial-of-service) in JOSE.JWK.shared_secret/2 on mismatched key types",
"workarounds": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eBefore calling \u003ccode\u003eJOSE.JWK.shared_secret/2\u003c/code\u003e, verify that the externally supplied peer key\u0027s type (\u003ccode\u003ekty\u003c/code\u003e) and curve match your own key, and reject any key whose type does not match before attempting derivation.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Before calling `JOSE.JWK.shared_secret/2`, verify that the externally supplied peer key\u0027s type (`kty`) and curve match your own key, and reject any key whose type does not match before attempting derivation."
}
],
"value": "Before calling JOSE.JWK.shared_secret/2, verify that the externally supplied peer key\u0027s type (kty) and curve match your own key, and reject any key whose type does not match before attempting derivation."
}
]
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-65628",
"datePublished": "2026-10-26T19:53:27.625Z",
"dateReserved": "2026-07-22T13:58:26.233Z",
"dateUpdated": "2026-10-26T19:53:27.625Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
CVE-2026-65627 (GCVE-0-2026-65627)
Vulnerability from nvd – Published: 2026-10-26 19:53 – Updated: 2026-10-26 19:53
VLAI
EPSS
VEX
Title
Decompression bomb via unbounded zlib:inflate in jose_jwe_zip:uncompress/2
Summary
Improper Handling of Highly Compressed Data (Data Amplification) vulnerability in potatosalad jose (erlang-jose) allows a remote attacker to exhaust a node's memory with a small crafted JWE token.
The jose_jwe_zip:uncompress/2 function in src/jwe/jose_jwe_zip.erl decompresses the DEFLATE-compressed plaintext of a JWE that carries the optional zip: DEF header by calling zlib:inflate/2 on the entire attacker-controlled stream, with no bound on the output size or the inflation ratio. Raw DEFLATE reaches ratios around 1000:1 on highly repetitive input, so a few-kilobyte token inflates to hundreds of megabytes or gigabytes in a single call.
Decompression runs automatically during decryption through jose_jwe:block_decrypt/2 (JOSE.JWE.block_decrypt/2 in Elixir), before the recipient can inspect or reject the payload. With the common asymmetric key-management algorithms (RSA-OAEP, ECDH-ES) an attacker needs only the recipient's public key to craft such a token, so no authentication or secret material is required. A single small token can exhaust the node's memory and crash the BEAM, denying service to all users.
This issue affects jose: from 1.0.0 before 1.11.13.
Severity
CWE
- CWE-409 - Improper Handling of Highly Compressed Data (Data Amplification)
Assigner
References
5 references
| URL | Tags |
|---|---|
| https://github.com/potatosalad/erlang-jose/securi… | vendor-advisoryrelated |
| https://cna.erlef.org/cves/CVE-2026-65627.html | related |
| https://osv.dev/vulnerability/EEF-CVE-2026-65627 | related |
| https://github.com/potatosalad/erlang-jose/commit… | related |
| https://github.com/potatosalad/erlang-jose/commit… | patch |
Impacted products
2 products
| Vendor | Product | Version | |
|---|---|---|---|
| potatosalad | jose |
Affected:
1.0.0 , < 1.11.13
(semver)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
|
| potatosalad | jose |
Affected:
a7746ecd4950f85a393136e449a91dac62b5c429 , < 857eb8e7f2d33e2c9ca2189e77226561cacaf2ad
(git)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
{
"containers": {
"cna": {
"affected": [
{
"collectionURL": "https://repo.hex.pm",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwe_zip",
"jose_jwe",
"\u0027Elixir.JOSE.JWE\u0027"
],
"packageName": "jose",
"packageURL": "pkg:hex/jose",
"product": "jose",
"programFiles": [
"src/jwe/jose_jwe_zip.erl",
"src/jwe/jose_jwe.erl",
"lib/jose/jwe.ex"
],
"programRoutines": [
{
"name": "jose_jwe_zip:uncompress/2"
},
{
"name": "jose_jwe:block_decrypt/2"
},
{
"name": "\u0027Elixir.JOSE.JWE\u0027:block_decrypt/2"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "1.11.13",
"status": "affected",
"version": "1.0.0",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwe_zip",
"jose_jwe",
"\u0027Elixir.JOSE.JWE\u0027"
],
"packageName": "potatosalad/erlang-jose",
"packageURL": "pkg:github/potatosalad/erlang-jose",
"product": "jose",
"programFiles": [
"src/jwe/jose_jwe_zip.erl",
"src/jwe/jose_jwe.erl",
"lib/jose/jwe.ex"
],
"programRoutines": [
{
"name": "jose_jwe_zip:uncompress/2"
},
{
"name": "jose_jwe:block_decrypt/2"
},
{
"name": "\u0027Elixir.JOSE.JWE\u0027:block_decrypt/2"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "857eb8e7f2d33e2c9ca2189e77226561cacaf2ad",
"status": "affected",
"version": "a7746ecd4950f85a393136e449a91dac62b5c429",
"versionType": "git"
}
]
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.11.13",
"versionStartIncluding": "1.0.0",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "AND"
}
],
"credits": [
{
"lang": "en",
"type": "reporter",
"value": "Peter Ullrich"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Andrew Bennett"
},
{
"lang": "en",
"type": "analyst",
"value": "Jonatan M\u00e4nnchen / EEF"
}
],
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eImproper Handling of Highly Compressed Data (Data Amplification) vulnerability in potatosalad jose (erlang-jose) allows a remote attacker to exhaust a node\u0027s memory with a small crafted JWE token.\u003c/p\u003e\n\u003cp\u003eThe \u003ccode\u003ejose_jwe_zip:uncompress/2\u003c/code\u003e function in \u003ccode\u003esrc/jwe/jose_jwe_zip.erl\u003c/code\u003e decompresses the DEFLATE-compressed plaintext of a JWE that carries the optional \u003ccode\u003ezip: DEF\u003c/code\u003e header by calling \u003ccode\u003ezlib:inflate/2\u003c/code\u003e on the entire attacker-controlled stream, with no bound on the output size or the inflation ratio. Raw DEFLATE reaches ratios around 1000:1 on highly repetitive input, so a few-kilobyte token inflates to hundreds of megabytes or gigabytes in a single call.\u003c/p\u003e\n\u003cp\u003eDecompression runs automatically during decryption through \u003ccode\u003ejose_jwe:block_decrypt/2\u003c/code\u003e (\u003ccode\u003eJOSE.JWE.block_decrypt/2\u003c/code\u003e in Elixir), before the recipient can inspect or reject the payload. With the common asymmetric key-management algorithms (RSA-OAEP, ECDH-ES) an attacker needs only the recipient\u0027s public key to craft such a token, so no authentication or secret material is required. A single small token can exhaust the node\u0027s memory and crash the BEAM, denying service to all users.\u003c/p\u003e\n\u003cp\u003eThis issue affects jose: from 1.0.0 before 1.11.13.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Improper Handling of Highly Compressed Data (Data Amplification) vulnerability in potatosalad jose (erlang-jose) allows a remote attacker to exhaust a node\u0027s memory with a small crafted JWE token.\n\nThe `jose_jwe_zip:uncompress/2` function in `src/jwe/jose_jwe_zip.erl` decompresses the DEFLATE-compressed plaintext of a JWE that carries the optional `zip: DEF` header by calling `zlib:inflate/2` on the entire attacker-controlled stream, with no bound on the output size or the inflation ratio. Raw DEFLATE reaches ratios around 1000:1 on highly repetitive input, so a few-kilobyte token inflates to hundreds of megabytes or gigabytes in a single call.\n\nDecompression runs automatically during decryption through `jose_jwe:block_decrypt/2` (`JOSE.JWE.block_decrypt/2` in Elixir), before the recipient can inspect or reject the payload. With the common asymmetric key-management algorithms (RSA-OAEP, ECDH-ES) an attacker needs only the recipient\u0027s public key to craft such a token, so no authentication or secret material is required. A single small token can exhaust the node\u0027s memory and crash the BEAM, denying service to all users.\n\nThis issue affects jose: from 1.0.0 before 1.11.13."
}
],
"value": "Improper Handling of Highly Compressed Data (Data Amplification) vulnerability in potatosalad jose (erlang-jose) allows a remote attacker to exhaust a node\u0027s memory with a small crafted JWE token.\n\nThe jose_jwe_zip:uncompress/2 function in src/jwe/jose_jwe_zip.erl decompresses the DEFLATE-compressed plaintext of a JWE that carries the optional zip: DEF header by calling zlib:inflate/2 on the entire attacker-controlled stream, with no bound on the output size or the inflation ratio. Raw DEFLATE reaches ratios around 1000:1 on highly repetitive input, so a few-kilobyte token inflates to hundreds of megabytes or gigabytes in a single call.\n\nDecompression runs automatically during decryption through jose_jwe:block_decrypt/2 (JOSE.JWE.block_decrypt/2 in Elixir), before the recipient can inspect or reject the payload. With the common asymmetric key-management algorithms (RSA-OAEP, ECDH-ES) an attacker needs only the recipient\u0027s public key to craft such a token, so no authentication or secret material is required. A single small token can exhaust the node\u0027s memory and crash the BEAM, denying service to all users.\n\nThis issue affects jose: from 1.0.0 before 1.11.13."
}
],
"impacts": [
{
"capecId": "CAPEC-130",
"descriptions": [
{
"lang": "en",
"value": "CAPEC-130 Excessive Allocation"
}
]
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "NONE",
"attackVector": "LOCAL",
"baseScore": 6.9,
"baseSeverity": "MEDIUM",
"privilegesRequired": "NONE",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N",
"version": "4.0",
"vulnAvailabilityImpact": "HIGH",
"vulnConfidentialityImpact": "NONE",
"vulnIntegrityImpact": "NONE",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-409",
"description": "CWE-409 Improper Handling of Highly Compressed Data (Data Amplification)",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T19:53:16.336Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/security/advisories/GHSA-wfpv-qxp8-x5gm"
},
{
"name": "EEF CNA record for CVE-2026-65627",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-65627.html"
},
{
"name": "OSV record EEF-CVE-2026-65627",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-65627"
},
{
"name": "Introducing commit a7746ec in potatosalad/erlang-jose",
"tags": [
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/a7746ecd4950f85a393136e449a91dac62b5c429"
},
{
"name": "Fix commit 857eb8e in potatosalad/erlang-jose",
"tags": [
"patch"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/857eb8e7f2d33e2c9ca2189e77226561cacaf2ad"
}
],
"source": {
"discovery": "EXTERNAL"
},
"title": "Decompression bomb via unbounded zlib:inflate in jose_jwe_zip:uncompress/2",
"workarounds": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eReject JWE tokens that carry a \u003ccode\u003ezip\u003c/code\u003e header before passing them to \u003ccode\u003ejose_jwe:block_decrypt/2\u003c/code\u003e. DEFLATE compression is rarely used in legitimate JWE traffic, so untrusted tokens whose protected header contains \u003ccode\u003ezip: DEF\u003c/code\u003e can be inspected and filtered out before decryption.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Reject JWE tokens that carry a `zip` header before passing them to `jose_jwe:block_decrypt/2`. DEFLATE compression is rarely used in legitimate JWE traffic, so untrusted tokens whose protected header contains `zip: DEF` can be inspected and filtered out before decryption."
}
],
"value": "Reject JWE tokens that carry a zip header before passing them to jose_jwe:block_decrypt/2. DEFLATE compression is rarely used in legitimate JWE traffic, so untrusted tokens whose protected header contains zip: DEF can be inspected and filtered out before decryption."
}
]
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-65627",
"datePublished": "2026-10-26T19:53:16.336Z",
"dateReserved": "2026-07-22T13:58:26.233Z",
"dateUpdated": "2026-10-26T19:53:16.336Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
CVE-2026-65626 (GCVE-0-2026-65626)
Vulnerability from nvd – Published: 2026-10-26 19:53 – Updated: 2026-10-26 19:53
VLAI
EPSS
VEX
Title
Bleichenbacher padding oracle in RSAES-PKCS1-v1_5 decryption in jose
Summary
The pure-Erlang RSAES-PKCS1-v1_5 decryption in the jose_jwa_pkcs1 module is a Bleichenbacher padding oracle. eme_pkcs1_decode/2 returns the recovered message when a decrypted block has valid PKCS#1 v1.5 padding (a leading 0x00 0x02, a padding string of at least eight non-zero bytes, and a 0x00 separator) and returns a distinct error result otherwise, and rsaes_pkcs1_decrypt/2 additionally returns {error, {badsize, _}} when the length check fails. The implementation applies no implicit-rejection countermeasure (RFC 8017 §7.2.2): it does not substitute a deterministic pseudo-random plaintext on a padding failure, so a one-bit padding-conformance signal leaks to the caller. Because the underlying modular exponentiation in dp/2 is a raw, non-blinded crypto:mod_pow/3, the padding check also stays distinguishable by timing even when an application normalizes every failure to a single error value.
An unauthenticated attacker who knows only the public RSA key and can submit ciphertexts to a decryption endpoint that unwraps RSA1_5 JWE keys (or otherwise calls decrypt_private/3 with rsa_pkcs1_padding) can use this oracle to recover the plaintext of intercepted ciphertexts, such as content-encryption keys and thus the protected message, or to forge signatures, through roughly 10^4 to 10^6 adaptive chosen-ciphertext queries.
This issue affects jose: from 1.3.0 before 1.11.13.
Severity
CWE
- CWE-203 - Observable Discrepancy
Assigner
References
5 references
| URL | Tags |
|---|---|
| https://github.com/potatosalad/erlang-jose/securi… | vendor-advisoryrelated |
| https://cna.erlef.org/cves/CVE-2026-65626.html | related |
| https://osv.dev/vulnerability/EEF-CVE-2026-65626 | related |
| https://github.com/potatosalad/erlang-jose/commit… | related |
| https://github.com/potatosalad/erlang-jose/commit… | patch |
Impacted products
2 products
| Vendor | Product | Version | |
|---|---|---|---|
| potatosalad | jose |
Affected:
1.3.0 , < 1.11.13
(semver)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
|
| potatosalad | jose |
Affected:
853c5d4c4c0bd2a7ecb055b237f4284184e176c8 , < 0eac8cef9aaa48fb6846f4e47a0002dc4a73966d
(git)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
{
"containers": {
"cna": {
"affected": [
{
"collectionURL": "https://repo.hex.pm",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwa_pkcs1"
],
"packageName": "jose",
"packageURL": "pkg:hex/jose",
"product": "jose",
"programFiles": [
"src/jwa/jose_jwa_pkcs1.erl"
],
"programRoutines": [
{
"name": "jose_jwa_pkcs1:decrypt_private/3"
},
{
"name": "jose_jwa_pkcs1:rsaes_pkcs1_decrypt/2"
},
{
"name": "jose_jwa_pkcs1:eme_pkcs1_decode/2"
},
{
"name": "jose_jwa_pkcs1:dp/2"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "1.11.13",
"status": "affected",
"version": "1.3.0",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwa_pkcs1"
],
"packageName": "potatosalad/erlang-jose",
"packageURL": "pkg:github/potatosalad/erlang-jose",
"product": "jose",
"programFiles": [
"src/jwa/jose_jwa_pkcs1.erl"
],
"programRoutines": [
{
"name": "jose_jwa_pkcs1:decrypt_private/3"
},
{
"name": "jose_jwa_pkcs1:rsaes_pkcs1_decrypt/2"
},
{
"name": "jose_jwa_pkcs1:eme_pkcs1_decode/2"
},
{
"name": "jose_jwa_pkcs1:dp/2"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "0eac8cef9aaa48fb6846f4e47a0002dc4a73966d",
"status": "affected",
"version": "853c5d4c4c0bd2a7ecb055b237f4284184e176c8",
"versionType": "git"
}
]
}
],
"configurations": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eThe vulnerable code path is only reached when jose performs RSAES-PKCS1-v1_5 decryption with its pure-Erlang fallback (the \u003ccode\u003ejose_jwa_pkcs1\u003c/code\u003e module) instead of the native OTP \u003ccode\u003epublic_key\u003c/code\u003e implementation. This requires the crypto_fallback option to be enabled (\u003ccode\u003eapplication:set_env(jose, crypto_fallback, true)\u003c/code\u003e, or \u003ccode\u003eJOSE.crypto_fallback(true)\u003c/code\u003e in Elixir) and the OTP runtime not to provide native RSA1_5 decryption. When native OTP RSA support is selected, decryption does not go through \u003ccode\u003ejose_jwa_pkcs1\u003c/code\u003e.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "The vulnerable code path is only reached when jose performs RSAES-PKCS1-v1_5 decryption with its pure-Erlang fallback (the `jose_jwa_pkcs1` module) instead of the native OTP `public_key` implementation. This requires the crypto_fallback option to be enabled (`application:set_env(jose, crypto_fallback, true)`, or `JOSE.crypto_fallback(true)` in Elixir) and the OTP runtime not to provide native RSA1_5 decryption. When native OTP RSA support is selected, decryption does not go through `jose_jwa_pkcs1`."
}
],
"value": "The vulnerable code path is only reached when jose performs RSAES-PKCS1-v1_5 decryption with its pure-Erlang fallback (the jose_jwa_pkcs1 module) instead of the native OTP public_key implementation. This requires the crypto_fallback option to be enabled (application:set_env(jose, crypto_fallback, true), or JOSE.crypto_fallback(true) in Elixir) and the OTP runtime not to provide native RSA1_5 decryption. When native OTP RSA support is selected, decryption does not go through jose_jwa_pkcs1."
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.11.13",
"versionStartIncluding": "1.3.0",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "AND"
}
],
"credits": [
{
"lang": "en",
"type": "reporter",
"value": "Peter Ullrich"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Andrew Bennett"
},
{
"lang": "en",
"type": "analyst",
"value": "Jonatan M\u00e4nnchen / EEF"
}
],
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eThe pure-Erlang RSAES-PKCS1-v1_5 decryption in the \u003ccode\u003ejose_jwa_pkcs1\u003c/code\u003e module is a Bleichenbacher padding oracle. \u003ccode\u003eeme_pkcs1_decode/2\u003c/code\u003e returns the recovered message when a decrypted block has valid \u003ccode\u003ePKCS#1\u003c/code\u003e v1.5 padding (a leading \u003ccode\u003e0x00 0x02\u003c/code\u003e, a padding string of at least eight non-zero bytes, and a \u003ccode\u003e0x00\u003c/code\u003e separator) and returns a distinct error result otherwise, and \u003ccode\u003ersaes_pkcs1_decrypt/2\u003c/code\u003e additionally returns \u003ccode\u003e{error, {badsize, _}}\u003c/code\u003e when the length check fails. The implementation applies no implicit-rejection countermeasure (RFC 8017 \u00a77.2.2): it does not substitute a deterministic pseudo-random plaintext on a padding failure, so a one-bit padding-conformance signal leaks to the caller. Because the underlying modular exponentiation in \u003ccode\u003edp/2\u003c/code\u003e is a raw, non-blinded \u003ccode\u003ecrypto:mod_pow/3\u003c/code\u003e, the padding check also stays distinguishable by timing even when an application normalizes every failure to a single error value.\u003c/p\u003e\n\u003cp\u003eAn unauthenticated attacker who knows only the public RSA key and can submit ciphertexts to a decryption endpoint that unwraps RSA1_5 JWE keys (or otherwise calls \u003ccode\u003edecrypt_private/3\u003c/code\u003e with \u003ccode\u003ersa_pkcs1_padding\u003c/code\u003e) can use this oracle to recover the plaintext of intercepted ciphertexts, such as content-encryption keys and thus the protected message, or to forge signatures, through roughly 10^4 to 10^6 adaptive chosen-ciphertext queries.\u003c/p\u003e\n\u003cp\u003eThis issue affects jose: from 1.3.0 before 1.11.13.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "The pure-Erlang RSAES-PKCS1-v1_5 decryption in the `jose_jwa_pkcs1` module is a Bleichenbacher padding oracle. `eme_pkcs1_decode/2` returns the recovered message when a decrypted block has valid `PKCS#1` v1.5 padding (a leading `0x00 0x02`, a padding string of at least eight non-zero bytes, and a `0x00` separator) and returns a distinct error result otherwise, and `rsaes_pkcs1_decrypt/2` additionally returns `{error, {badsize, _}}` when the length check fails. The implementation applies no implicit-rejection countermeasure (RFC 8017 \u00a77.2.2): it does not substitute a deterministic pseudo-random plaintext on a padding failure, so a one-bit padding-conformance signal leaks to the caller. Because the underlying modular exponentiation in `dp/2` is a raw, non-blinded `crypto:mod_pow/3`, the padding check also stays distinguishable by timing even when an application normalizes every failure to a single error value.\n\nAn unauthenticated attacker who knows only the public RSA key and can submit ciphertexts to a decryption endpoint that unwraps RSA1_5 JWE keys (or otherwise calls `decrypt_private/3` with `rsa_pkcs1_padding`) can use this oracle to recover the plaintext of intercepted ciphertexts, such as content-encryption keys and thus the protected message, or to forge signatures, through roughly 10^4 to 10^6 adaptive chosen-ciphertext queries.\n\nThis issue affects jose: from 1.3.0 before 1.11.13."
}
],
"value": "The pure-Erlang RSAES-PKCS1-v1_5 decryption in the jose_jwa_pkcs1 module is a Bleichenbacher padding oracle. eme_pkcs1_decode/2 returns the recovered message when a decrypted block has valid PKCS#1 v1.5 padding (a leading 0x00 0x02, a padding string of at least eight non-zero bytes, and a 0x00 separator) and returns a distinct error result otherwise, and rsaes_pkcs1_decrypt/2 additionally returns {error, {badsize, _}} when the length check fails. The implementation applies no implicit-rejection countermeasure (RFC 8017 \u00a77.2.2): it does not substitute a deterministic pseudo-random plaintext on a padding failure, so a one-bit padding-conformance signal leaks to the caller. Because the underlying modular exponentiation in dp/2 is a raw, non-blinded crypto:mod_pow/3, the padding check also stays distinguishable by timing even when an application normalizes every failure to a single error value.\n\nAn unauthenticated attacker who knows only the public RSA key and can submit ciphertexts to a decryption endpoint that unwraps RSA1_5 JWE keys (or otherwise calls decrypt_private/3 with rsa_pkcs1_padding) can use this oracle to recover the plaintext of intercepted ciphertexts, such as content-encryption keys and thus the protected message, or to forge signatures, through roughly 10^4 to 10^6 adaptive chosen-ciphertext queries.\n\nThis issue affects jose: from 1.3.0 before 1.11.13."
}
],
"impacts": [
{
"capecId": "CAPEC-463",
"descriptions": [
{
"lang": "en",
"value": "CAPEC-463 Padding Oracle Crypto Attack"
}
]
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "PRESENT",
"attackVector": "LOCAL",
"baseScore": 5.9,
"baseSeverity": "MEDIUM",
"privilegesRequired": "NONE",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N",
"version": "4.0",
"vulnAvailabilityImpact": "NONE",
"vulnConfidentialityImpact": "HIGH",
"vulnIntegrityImpact": "NONE",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-203",
"description": "CWE-203 Observable Discrepancy",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T19:53:05.620Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/security/advisories/GHSA-vwvr-f994-6j9j"
},
{
"name": "EEF CNA record for CVE-2026-65626",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-65626.html"
},
{
"name": "OSV record EEF-CVE-2026-65626",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-65626"
},
{
"name": "Introducing commit 853c5d4 in potatosalad/erlang-jose",
"tags": [
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/853c5d4c4c0bd2a7ecb055b237f4284184e176c8"
},
{
"name": "Fix commit 0eac8ce in potatosalad/erlang-jose",
"tags": [
"patch"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/0eac8cef9aaa48fb6846f4e47a0002dc4a73966d"
}
],
"source": {
"discovery": "EXTERNAL"
},
"title": "Bleichenbacher padding oracle in RSAES-PKCS1-v1_5 decryption in jose"
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-65626",
"datePublished": "2026-10-26T19:53:05.620Z",
"dateReserved": "2026-07-22T13:55:59.401Z",
"dateUpdated": "2026-10-26T19:53:05.620Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
CVE-2026-65625 (GCVE-0-2026-65625)
Vulnerability from nvd – Published: 2026-10-26 19:52 – Updated: 2026-10-26 19:52
VLAI
EPSS
VEX
Title
Attacker-controlled AES-GCM authentication tag length allows tag forgery in jose
Summary
The pure-Erlang AES-GCM fallback in jose_jwa_aes derives the number of verified authentication tag bits from the attacker-supplied tag itself. In the {aes_gcm, Bits} clause of block_decrypt/4, the incoming tag is guarded only by is_binary/1, with no check on its length. Verification in gcm_block_decrypt/6 then computes TBits = bit_size(T) and compares only those bits of the real 128-bit tag. An attacker who controls a JWE token can truncate the authentication tag to as little as 8 bits, so only 8 bits are ever checked. This reduces forgery resistance from 2^-128 to 2^-8, and a forged ciphertext is reliably accepted as authentic within 256 attempts without knowledge of the key (an authentication tag forgery and integrity bypass). Supplying a tag longer than 128 bits instead causes a badmatch that crashes the decrypting process. The fallback is reached through the public JWE decryption path whenever AES-GCM is not provided by a native crypto NIF, for example on FIPS or stripped or older OTP builds.
This issue affects jose: from 1.2.0 before 1.11.13.
Severity
CWE
- CWE-354 - Improper Validation of Integrity Check Value
Assigner
References
5 references
| URL | Tags |
|---|---|
| https://github.com/potatosalad/erlang-jose/securi… | vendor-advisoryrelated |
| https://cna.erlef.org/cves/CVE-2026-65625.html | related |
| https://osv.dev/vulnerability/EEF-CVE-2026-65625 | related |
| https://github.com/potatosalad/erlang-jose/commit… | related |
| https://github.com/potatosalad/erlang-jose/commit… | patch |
Impacted products
2 products
| Vendor | Product | Version | |
|---|---|---|---|
| potatosalad | jose |
Affected:
1.2.0 , < 1.11.13
(semver)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
|
| potatosalad | jose |
Affected:
8848b172575fb7d7e1e2977e8ae0a21678d2157a , < 3fa1f8e3efda0da5ce6f4c9984789f979dc02740
(git)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
{
"containers": {
"cna": {
"affected": [
{
"collectionURL": "https://repo.hex.pm",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwa_aes"
],
"packageName": "jose",
"packageURL": "pkg:hex/jose",
"product": "jose",
"programFiles": [
"src/jwa/jose_jwa_aes.erl"
],
"programRoutines": [
{
"name": "jose_jwa_aes:block_decrypt/4"
},
{
"name": "jose_jwa_aes:gcm_block_decrypt/6"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "1.11.13",
"status": "affected",
"version": "1.2.0",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwa_aes"
],
"packageName": "potatosalad/erlang-jose",
"packageURL": "pkg:github/potatosalad/erlang-jose",
"product": "jose",
"programFiles": [
"src/jwa/jose_jwa_aes.erl"
],
"programRoutines": [
{
"name": "jose_jwa_aes:block_decrypt/4"
},
{
"name": "jose_jwa_aes:gcm_block_decrypt/6"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "3fa1f8e3efda0da5ce6f4c9984789f979dc02740",
"status": "affected",
"version": "8848b172575fb7d7e1e2977e8ae0a21678d2157a",
"versionType": "git"
}
]
}
],
"configurations": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eThis vulnerability is only exploitable when AES-GCM is handled by the pure-Erlang \u003ccode\u003ejose_jwa_aes\u003c/code\u003e fallback. That fallback is used on deployments where the Erlang/OTP \u003ccode\u003ecrypto\u003c/code\u003e NIF does not expose native AES-GCM (for example FIPS builds, or stripped or older OTP releases). Deployments with a native AES-GCM crypto provider dispatch GCM through \u003ccode\u003ecrypto\u003c/code\u003e and are not affected.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "This vulnerability is only exploitable when AES-GCM is handled by the pure-Erlang `jose_jwa_aes` fallback. That fallback is used on deployments where the Erlang/OTP `crypto` NIF does not expose native AES-GCM (for example FIPS builds, or stripped or older OTP releases). Deployments with a native AES-GCM crypto provider dispatch GCM through `crypto` and are not affected."
}
],
"value": "This vulnerability is only exploitable when AES-GCM is handled by the pure-Erlang jose_jwa_aes fallback. That fallback is used on deployments where the Erlang/OTP crypto NIF does not expose native AES-GCM (for example FIPS builds, or stripped or older OTP releases). Deployments with a native AES-GCM crypto provider dispatch GCM through crypto and are not affected."
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.11.13",
"versionStartIncluding": "1.2.0",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "AND"
}
],
"credits": [
{
"lang": "en",
"type": "reporter",
"value": "Peter Ullrich"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Andrew Bennett"
},
{
"lang": "en",
"type": "analyst",
"value": "Jonatan M\u00e4nnchen / EEF"
}
],
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eThe pure-Erlang AES-GCM fallback in \u003ccode\u003ejose_jwa_aes\u003c/code\u003e derives the number of verified authentication tag bits from the attacker-supplied tag itself. In the \u003ccode\u003e{aes_gcm, Bits}\u003c/code\u003e clause of \u003ccode\u003eblock_decrypt/4\u003c/code\u003e, the incoming tag is guarded only by \u003ccode\u003eis_binary/1\u003c/code\u003e, with no check on its length. Verification in \u003ccode\u003egcm_block_decrypt/6\u003c/code\u003e then computes \u003ccode\u003eTBits = bit_size(T)\u003c/code\u003e and compares only those bits of the real 128-bit tag. An attacker who controls a JWE token can truncate the authentication tag to as little as 8 bits, so only 8 bits are ever checked. This reduces forgery resistance from 2^-128 to 2^-8, and a forged ciphertext is reliably accepted as authentic within 256 attempts without knowledge of the key (an authentication tag forgery and integrity bypass). Supplying a tag longer than 128 bits instead causes a badmatch that crashes the decrypting process. The fallback is reached through the public JWE decryption path whenever AES-GCM is not provided by a native crypto NIF, for example on FIPS or stripped or older OTP builds.\u003c/p\u003e\n\u003cp\u003eThis issue affects jose: from 1.2.0 before 1.11.13.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "The pure-Erlang AES-GCM fallback in `jose_jwa_aes` derives the number of verified authentication tag bits from the attacker-supplied tag itself. In the `{aes_gcm, Bits}` clause of `block_decrypt/4`, the incoming tag is guarded only by `is_binary/1`, with no check on its length. Verification in `gcm_block_decrypt/6` then computes `TBits = bit_size(T)` and compares only those bits of the real 128-bit tag. An attacker who controls a JWE token can truncate the authentication tag to as little as 8 bits, so only 8 bits are ever checked. This reduces forgery resistance from 2^-128 to 2^-8, and a forged ciphertext is reliably accepted as authentic within 256 attempts without knowledge of the key (an authentication tag forgery and integrity bypass). Supplying a tag longer than 128 bits instead causes a badmatch that crashes the decrypting process. The fallback is reached through the public JWE decryption path whenever AES-GCM is not provided by a native crypto NIF, for example on FIPS or stripped or older OTP builds.\n\nThis issue affects jose: from 1.2.0 before 1.11.13."
}
],
"value": "The pure-Erlang AES-GCM fallback in jose_jwa_aes derives the number of verified authentication tag bits from the attacker-supplied tag itself. In the {aes_gcm, Bits} clause of block_decrypt/4, the incoming tag is guarded only by is_binary/1, with no check on its length. Verification in gcm_block_decrypt/6 then computes TBits = bit_size(T) and compares only those bits of the real 128-bit tag. An attacker who controls a JWE token can truncate the authentication tag to as little as 8 bits, so only 8 bits are ever checked. This reduces forgery resistance from 2^-128 to 2^-8, and a forged ciphertext is reliably accepted as authentic within 256 attempts without knowledge of the key (an authentication tag forgery and integrity bypass). Supplying a tag longer than 128 bits instead causes a badmatch that crashes the decrypting process. The fallback is reached through the public JWE decryption path whenever AES-GCM is not provided by a native crypto NIF, for example on FIPS or stripped or older OTP builds.\n\nThis issue affects jose: from 1.2.0 before 1.11.13."
}
],
"impacts": [
{
"capecId": "CAPEC-475",
"descriptions": [
{
"lang": "en",
"value": "CAPEC-475 Signature Spoofing by Improper Validation"
}
]
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "PRESENT",
"attackVector": "LOCAL",
"baseScore": 5.9,
"baseSeverity": "MEDIUM",
"privilegesRequired": "NONE",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:N/VC:N/VI:H/VA:L/SC:N/SI:N/SA:N",
"version": "4.0",
"vulnAvailabilityImpact": "LOW",
"vulnConfidentialityImpact": "NONE",
"vulnIntegrityImpact": "HIGH",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-354",
"description": "CWE-354 Improper Validation of Integrity Check Value",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T19:52:54.987Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/security/advisories/GHSA-6gxw-6f7r-cjr6"
},
{
"name": "EEF CNA record for CVE-2026-65625",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-65625.html"
},
{
"name": "OSV record EEF-CVE-2026-65625",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-65625"
},
{
"name": "Introducing commit 8848b17 in potatosalad/erlang-jose",
"tags": [
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/8848b172575fb7d7e1e2977e8ae0a21678d2157a"
},
{
"name": "Fix commit 3fa1f8e in potatosalad/erlang-jose",
"tags": [
"patch"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/3fa1f8e3efda0da5ce6f4c9984789f979dc02740"
}
],
"source": {
"discovery": "EXTERNAL"
},
"title": "Attacker-controlled AES-GCM authentication tag length allows tag forgery in jose",
"workarounds": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eEnsure the runtime provides a crypto provider with native AES-GCM support (a standard Erlang/OTP build linked against OpenSSL) so that JOSE dispatches AES-GCM to the native \u003ccode\u003ecrypto\u003c/code\u003e NIF instead of the \u003ccode\u003ejose_jwa_aes\u003c/code\u003e fallback.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Ensure the runtime provides a crypto provider with native AES-GCM support (a standard Erlang/OTP build linked against OpenSSL) so that JOSE dispatches AES-GCM to the native `crypto` NIF instead of the `jose_jwa_aes` fallback."
}
],
"value": "Ensure the runtime provides a crypto provider with native AES-GCM support (a standard Erlang/OTP build linked against OpenSSL) so that JOSE dispatches AES-GCM to the native crypto NIF instead of the jose_jwa_aes fallback."
}
]
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-65625",
"datePublished": "2026-10-26T19:52:54.987Z",
"dateReserved": "2026-07-22T13:55:59.401Z",
"dateUpdated": "2026-10-26T19:52:54.987Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
CVE-2026-65630 (GCVE-0-2026-65630)
Vulnerability from cvelistv5 – Published: 2026-10-26 19:54 – Updated: 2026-10-26 19:54
VLAI
EPSS
VEX
Title
Timing side-channel in pure-Erlang X25519 scalar multiplication leaks the private key in jose
Summary
Observable Timing Discrepancy vulnerability in potatosalad jose allows recovery of a long-term X25519 private key through a timing side channel in the pure-Erlang Curve25519 fallback.
The pure-Erlang X25519 implementation performs scalar multiplication over the secret private key using a recursive Montgomery ladder (jose_jwa_x25519:curve25519/2) whose clauses branch on individual bits of the clamped private scalar, and whose per-step operations (jose_jwa_x25519:montgomery_add/3 and jose_jwa_x25519:montgomery_double/1) and field inversion are built from value-dependent Erlang bignum arithmetic (multiplication, remainder, and modular exponentiation). Although the ladder is operation-count balanced and fixed at 254 steps, the concrete integer values processed at each step, and therefore the running time, depend on the secret scalar. The execution time of the public entry points jose_jwa_x25519:scalarmult/2, jose_jwa_x25519:x25519/2, jose_jwa_x25519:x25519_base/1, and jose_jwa_x25519:sk_to_pk/1 is thus a function of the private key.
This path is reachable from the public API, most notably when a service decrypts attacker-supplied ECDH-ES (JWE) messages with a long-term X25519 key (for example through JOSE.JWK.box_decrypt_ecdh_es/2, which reaches jose_jwa_curve25519:x25519_shared_secret/2 and the ladder). An attacker who can submit ciphertexts and measure decryption timing can, in principle, recover the private key bit by bit, defeating the resistance X25519 was designed to provide. Recovery of the key compromises the confidentiality and authenticity of all data protected by it.
This issue affects jose: from 1.10.0 before 1.11.13.
Severity
CWE
- CWE-208 - Observable Timing Discrepancy
Assigner
References
5 references
| URL | Tags |
|---|---|
| https://github.com/potatosalad/erlang-jose/securi… | vendor-advisoryrelated |
| https://cna.erlef.org/cves/CVE-2026-65630.html | related |
| https://osv.dev/vulnerability/EEF-CVE-2026-65630 | related |
| https://github.com/potatosalad/erlang-jose/commit… | related |
| https://github.com/potatosalad/erlang-jose/commit… | patch |
Impacted products
2 products
| Vendor | Product | Version | |
|---|---|---|---|
| potatosalad | jose |
Affected:
1.10.0 , < 1.11.13
(semver)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
|
| potatosalad | jose |
Affected:
8e532095de114ef4bf88a9ec5d651fa251a972b3 , < 3670f873c274bba86fb7f5ee5727a7efa1322b79
(git)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
{
"containers": {
"cna": {
"affected": [
{
"collectionURL": "https://repo.hex.pm",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwa_x25519",
"jose_jwa_curve25519",
"jose_curve25519_fallback",
"jose_jwk_kty_okp_x25519"
],
"packageName": "jose",
"packageURL": "pkg:hex/jose",
"product": "jose",
"programFiles": [
"src/jwa/jose_jwa_x25519.erl",
"src/jwa/jose_jwa_curve25519.erl",
"src/jwa/curve25519/jose_curve25519_fallback.erl",
"src/jwk/jose_jwk_kty_okp_x25519.erl"
],
"programRoutines": [
{
"name": "jose_jwa_x25519:curve25519/2"
},
{
"name": "jose_jwa_x25519:scalarmult/2"
},
{
"name": "jose_jwa_x25519:scalarmult_base/1"
},
{
"name": "jose_jwa_x25519:x25519/2"
},
{
"name": "jose_jwa_x25519:x25519_base/1"
},
{
"name": "jose_jwa_x25519:sk_to_pk/1"
},
{
"name": "jose_jwa_x25519:montgomery_add/3"
},
{
"name": "jose_jwa_x25519:montgomery_double/1"
},
{
"name": "jose_jwa_curve25519:x25519_shared_secret/2"
},
{
"name": "jose_jwa_curve25519:x25519_secret_to_public/1"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "1.11.13",
"status": "affected",
"version": "1.10.0",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwa_x25519",
"jose_jwa_curve25519",
"jose_curve25519_fallback",
"jose_jwk_kty_okp_x25519"
],
"packageName": "potatosalad/erlang-jose",
"packageURL": "pkg:github/potatosalad/erlang-jose",
"product": "jose",
"programFiles": [
"src/jwa/jose_jwa_x25519.erl",
"src/jwa/jose_jwa_curve25519.erl",
"src/jwa/curve25519/jose_curve25519_fallback.erl",
"src/jwk/jose_jwk_kty_okp_x25519.erl"
],
"programRoutines": [
{
"name": "jose_jwa_x25519:curve25519/2"
},
{
"name": "jose_jwa_x25519:scalarmult/2"
},
{
"name": "jose_jwa_x25519:scalarmult_base/1"
},
{
"name": "jose_jwa_x25519:x25519/2"
},
{
"name": "jose_jwa_x25519:x25519_base/1"
},
{
"name": "jose_jwa_x25519:sk_to_pk/1"
},
{
"name": "jose_jwa_x25519:montgomery_add/3"
},
{
"name": "jose_jwa_x25519:montgomery_double/1"
},
{
"name": "jose_jwa_curve25519:x25519_shared_secret/2"
},
{
"name": "jose_jwa_curve25519:x25519_secret_to_public/1"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "3670f873c274bba86fb7f5ee5727a7efa1322b79",
"status": "affected",
"version": "8e532095de114ef4bf88a9ec5d651fa251a972b3",
"versionType": "git"
}
]
}
],
"configurations": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eThe vulnerability is only exploitable when X25519 private-key operations run through the pure-Erlang Curve25519 fallback, for example when the crypto fallback is enabled (\u003ccode\u003eJOSE.crypto_fallback(true)\u003c/code\u003e or \u003ccode\u003eJOSE.curve25519_module(:jose_jwa_curve25519)\u003c/code\u003e) or when no constant-time native X25519 implementation (a libsodium or libdecaf NIF, or the OTP \u003ccode\u003ecrypto\u003c/code\u003e application providing \u003ccode\u003ex25519\u003c/code\u003e) is available. Deployments that use a constant-time native X25519 are not affected.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "The vulnerability is only exploitable when X25519 private-key operations run through the pure-Erlang Curve25519 fallback, for example when the crypto fallback is enabled (`JOSE.crypto_fallback(true)` or `JOSE.curve25519_module(:jose_jwa_curve25519)`) or when no constant-time native X25519 implementation (a libsodium or libdecaf NIF, or the OTP `crypto` application providing `x25519`) is available. Deployments that use a constant-time native X25519 are not affected."
}
],
"value": "The vulnerability is only exploitable when X25519 private-key operations run through the pure-Erlang Curve25519 fallback, for example when the crypto fallback is enabled (JOSE.crypto_fallback(true) or JOSE.curve25519_module(:jose_jwa_curve25519)) or when no constant-time native X25519 implementation (a libsodium or libdecaf NIF, or the OTP crypto application providing x25519) is available. Deployments that use a constant-time native X25519 are not affected."
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.11.13",
"versionStartIncluding": "1.10.0",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "AND"
}
],
"credits": [
{
"lang": "en",
"type": "reporter",
"value": "Peter Ullrich"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Andrew Bennett"
},
{
"lang": "en",
"type": "analyst",
"value": "Jonatan M\u00e4nnchen / EEF"
}
],
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eObservable Timing Discrepancy vulnerability in potatosalad jose allows recovery of a long-term X25519 private key through a timing side channel in the pure-Erlang Curve25519 fallback.\u003c/p\u003e\n\u003cp\u003eThe pure-Erlang X25519 implementation performs scalar multiplication over the secret private key using a recursive Montgomery ladder (\u003ccode\u003ejose_jwa_x25519:curve25519/2\u003c/code\u003e) whose clauses branch on individual bits of the clamped private scalar, and whose per-step operations (\u003ccode\u003ejose_jwa_x25519:montgomery_add/3\u003c/code\u003e and \u003ccode\u003ejose_jwa_x25519:montgomery_double/1\u003c/code\u003e) and field inversion are built from value-dependent Erlang bignum arithmetic (multiplication, remainder, and modular exponentiation). Although the ladder is operation-count balanced and fixed at 254 steps, the concrete integer values processed at each step, and therefore the running time, depend on the secret scalar. The execution time of the public entry points \u003ccode\u003ejose_jwa_x25519:scalarmult/2\u003c/code\u003e, \u003ccode\u003ejose_jwa_x25519:x25519/2\u003c/code\u003e, \u003ccode\u003ejose_jwa_x25519:x25519_base/1\u003c/code\u003e, and \u003ccode\u003ejose_jwa_x25519:sk_to_pk/1\u003c/code\u003e is thus a function of the private key.\u003c/p\u003e\n\u003cp\u003eThis path is reachable from the public API, most notably when a service decrypts attacker-supplied ECDH-ES (JWE) messages with a long-term X25519 key (for example through \u003ccode\u003eJOSE.JWK.box_decrypt_ecdh_es/2\u003c/code\u003e, which reaches \u003ccode\u003ejose_jwa_curve25519:x25519_shared_secret/2\u003c/code\u003e and the ladder). An attacker who can submit ciphertexts and measure decryption timing can, in principle, recover the private key bit by bit, defeating the resistance X25519 was designed to provide. Recovery of the key compromises the confidentiality and authenticity of all data protected by it.\u003c/p\u003e\n\u003cp\u003eThis issue affects jose: from 1.10.0 before 1.11.13.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Observable Timing Discrepancy vulnerability in potatosalad jose allows recovery of a long-term X25519 private key through a timing side channel in the pure-Erlang Curve25519 fallback.\n\nThe pure-Erlang X25519 implementation performs scalar multiplication over the secret private key using a recursive Montgomery ladder (`jose_jwa_x25519:curve25519/2`) whose clauses branch on individual bits of the clamped private scalar, and whose per-step operations (`jose_jwa_x25519:montgomery_add/3` and `jose_jwa_x25519:montgomery_double/1`) and field inversion are built from value-dependent Erlang bignum arithmetic (multiplication, remainder, and modular exponentiation). Although the ladder is operation-count balanced and fixed at 254 steps, the concrete integer values processed at each step, and therefore the running time, depend on the secret scalar. The execution time of the public entry points `jose_jwa_x25519:scalarmult/2`, `jose_jwa_x25519:x25519/2`, `jose_jwa_x25519:x25519_base/1`, and `jose_jwa_x25519:sk_to_pk/1` is thus a function of the private key.\n\nThis path is reachable from the public API, most notably when a service decrypts attacker-supplied ECDH-ES (JWE) messages with a long-term X25519 key (for example through `JOSE.JWK.box_decrypt_ecdh_es/2`, which reaches `jose_jwa_curve25519:x25519_shared_secret/2` and the ladder). An attacker who can submit ciphertexts and measure decryption timing can, in principle, recover the private key bit by bit, defeating the resistance X25519 was designed to provide. Recovery of the key compromises the confidentiality and authenticity of all data protected by it.\n\nThis issue affects jose: from 1.10.0 before 1.11.13."
}
],
"value": "Observable Timing Discrepancy vulnerability in potatosalad jose allows recovery of a long-term X25519 private key through a timing side channel in the pure-Erlang Curve25519 fallback.\n\nThe pure-Erlang X25519 implementation performs scalar multiplication over the secret private key using a recursive Montgomery ladder (jose_jwa_x25519:curve25519/2) whose clauses branch on individual bits of the clamped private scalar, and whose per-step operations (jose_jwa_x25519:montgomery_add/3 and jose_jwa_x25519:montgomery_double/1) and field inversion are built from value-dependent Erlang bignum arithmetic (multiplication, remainder, and modular exponentiation). Although the ladder is operation-count balanced and fixed at 254 steps, the concrete integer values processed at each step, and therefore the running time, depend on the secret scalar. The execution time of the public entry points jose_jwa_x25519:scalarmult/2, jose_jwa_x25519:x25519/2, jose_jwa_x25519:x25519_base/1, and jose_jwa_x25519:sk_to_pk/1 is thus a function of the private key.\n\nThis path is reachable from the public API, most notably when a service decrypts attacker-supplied ECDH-ES (JWE) messages with a long-term X25519 key (for example through JOSE.JWK.box_decrypt_ecdh_es/2, which reaches jose_jwa_curve25519:x25519_shared_secret/2 and the ladder). An attacker who can submit ciphertexts and measure decryption timing can, in principle, recover the private key bit by bit, defeating the resistance X25519 was designed to provide. Recovery of the key compromises the confidentiality and authenticity of all data protected by it.\n\nThis issue affects jose: from 1.10.0 before 1.11.13."
}
],
"impacts": [
{
"capecId": "CAPEC-97",
"descriptions": [
{
"lang": "en",
"value": "CAPEC-97 Cryptanalysis"
}
]
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "HIGH",
"attackRequirements": "PRESENT",
"attackVector": "LOCAL",
"baseScore": 5.9,
"baseSeverity": "MEDIUM",
"privilegesRequired": "NONE",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:L/AC:H/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N",
"version": "4.0",
"vulnAvailabilityImpact": "NONE",
"vulnConfidentialityImpact": "HIGH",
"vulnIntegrityImpact": "NONE",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-208",
"description": "CWE-208 Observable Timing Discrepancy",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T19:54:07.686Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/security/advisories/GHSA-xvr2-gggj-h2pp"
},
{
"name": "EEF CNA record for CVE-2026-65630",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-65630.html"
},
{
"name": "OSV record EEF-CVE-2026-65630",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-65630"
},
{
"name": "Introducing commit 8e53209 in potatosalad/erlang-jose",
"tags": [
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/8e532095de114ef4bf88a9ec5d651fa251a972b3"
},
{
"name": "Fix commit 3670f87 in potatosalad/erlang-jose",
"tags": [
"patch"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/3670f873c274bba86fb7f5ee5727a7efa1322b79"
}
],
"source": {
"discovery": "EXTERNAL"
},
"title": "Timing side-channel in pure-Erlang X25519 scalar multiplication leaks the private key in jose",
"workarounds": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eUse a constant-time native X25519 implementation for private-key operations: install the libsodium or libdecaf NIF, or run on an OTP release whose \u003ccode\u003ecrypto\u003c/code\u003e application provides \u003ccode\u003ex25519\u003c/code\u003e, and do not force the pure-Erlang Curve25519 fallback (\u003ccode\u003eJOSE.crypto_fallback(true)\u003c/code\u003e or \u003ccode\u003eJOSE.curve25519_module(:jose_jwa_curve25519)\u003c/code\u003e) for long-lived keys.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Use a constant-time native X25519 implementation for private-key operations: install the libsodium or libdecaf NIF, or run on an OTP release whose `crypto` application provides `x25519`, and do not force the pure-Erlang Curve25519 fallback (`JOSE.crypto_fallback(true)` or `JOSE.curve25519_module(:jose_jwa_curve25519)`) for long-lived keys."
}
],
"value": "Use a constant-time native X25519 implementation for private-key operations: install the libsodium or libdecaf NIF, or run on an OTP release whose crypto application provides x25519, and do not force the pure-Erlang Curve25519 fallback (JOSE.crypto_fallback(true) or JOSE.curve25519_module(:jose_jwa_curve25519)) for long-lived keys."
}
]
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-65630",
"datePublished": "2026-10-26T19:54:07.686Z",
"dateReserved": "2026-07-22T13:58:26.233Z",
"dateUpdated": "2026-10-26T19:54:07.686Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
CVE-2026-65632 (GCVE-0-2026-65632)
Vulnerability from cvelistv5 – Published: 2026-10-26 19:53 – Updated: 2026-10-26 19:53
VLAI
EPSS
VEX
Title
ECDSA signature length is not validated in jose, allowing signature malleability
Summary
The jose library accepts ECDSA (ES256, ES256K, ES384, and ES512) JWS signatures of a non-canonical length. When verifying an ECDSA signature, jose_jwk_kty_ec:verify/4 in src/jwk/jose_jwk_kty_ec.erl splits the raw signature in half by its actual byte length (split_binary(Signature, byte_size(Signature) div 2)) instead of enforcing the fixed length required by RFC 7518 §3.4, and then decodes each half with crypto:bytes_to_integer/1, which ignores leading zero bytes.
As a result, an attacker who holds one valid token can prepend leading zero bytes to each of the R and S halves to produce longer signatures that still split evenly and decode to the same (r, s) pair, so many distinct signature byte strings all verify against the same key (signature malleability). This does not allow forging new payloads or impersonating a signer, because the underlying (r, s) values are unchanged. It does defeat any security control that assumes a valid token or its signature is unique, such as token-revocation-by-hash, replay or idempotency caches, and deduplication logic.
This issue affects jose: from 1.0.0 before 1.11.13.
Severity
CWE
- CWE-347 - Improper Verification of Cryptographic Signature
Assigner
References
5 references
| URL | Tags |
|---|---|
| https://github.com/potatosalad/erlang-jose/securi… | vendor-advisoryrelated |
| https://cna.erlef.org/cves/CVE-2026-65632.html | related |
| https://osv.dev/vulnerability/EEF-CVE-2026-65632 | related |
| https://github.com/potatosalad/erlang-jose/commit… | related |
| https://github.com/potatosalad/erlang-jose/commit… | patch |
Impacted products
2 products
| Vendor | Product | Version | |
|---|---|---|---|
| potatosalad | jose |
Affected:
1.0.0 , < 1.11.13
(semver)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
|
| potatosalad | jose |
Affected:
a7746ecd4950f85a393136e449a91dac62b5c429 , < 72ce1866622b9329347dc52a94173ac0317bc9cf
(git)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
{
"containers": {
"cna": {
"affected": [
{
"collectionURL": "https://repo.hex.pm",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwk_kty_ec"
],
"packageName": "jose",
"packageURL": "pkg:hex/jose",
"product": "jose",
"programFiles": [
"src/jwk/jose_jwk_kty_ec.erl"
],
"programRoutines": [
{
"name": "jose_jwk_kty_ec:verify/4"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "1.11.13",
"status": "affected",
"version": "1.0.0",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwk_kty_ec"
],
"packageName": "potatosalad/erlang-jose",
"packageURL": "pkg:github/potatosalad/erlang-jose",
"product": "jose",
"programFiles": [
"src/jwk/jose_jwk_kty_ec.erl"
],
"programRoutines": [
{
"name": "jose_jwk_kty_ec:verify/4"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "72ce1866622b9329347dc52a94173ac0317bc9cf",
"status": "affected",
"version": "a7746ecd4950f85a393136e449a91dac62b5c429",
"versionType": "git"
}
]
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.11.13",
"versionStartIncluding": "1.0.0",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "AND"
}
],
"credits": [
{
"lang": "en",
"type": "reporter",
"value": "Peter Ullrich"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Andrew Bennett"
},
{
"lang": "en",
"type": "analyst",
"value": "Jonatan M\u00e4nnchen / EEF"
}
],
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eThe \u003ccode\u003ejose\u003c/code\u003e library accepts ECDSA (ES256, ES256K, ES384, and ES512) JWS signatures of a non-canonical length. When verifying an ECDSA signature, \u003ccode\u003ejose_jwk_kty_ec:verify/4\u003c/code\u003e in \u003ccode\u003esrc/jwk/jose_jwk_kty_ec.erl\u003c/code\u003e splits the raw signature in half by its actual byte length (\u003ccode\u003esplit_binary(Signature, byte_size(Signature) div 2)\u003c/code\u003e) instead of enforcing the fixed length required by RFC 7518 \u00a73.4, and then decodes each half with \u003ccode\u003ecrypto:bytes_to_integer/1\u003c/code\u003e, which ignores leading zero bytes.\u003c/p\u003e\n\u003cp\u003eAs a result, an attacker who holds one valid token can prepend leading zero bytes to each of the R and S halves to produce longer signatures that still split evenly and decode to the same \u003ccode\u003e(r, s)\u003c/code\u003e pair, so many distinct signature byte strings all verify against the same key (signature malleability). This does not allow forging new payloads or impersonating a signer, because the underlying \u003ccode\u003e(r, s)\u003c/code\u003e values are unchanged. It does defeat any security control that assumes a valid token or its signature is unique, such as token-revocation-by-hash, replay or idempotency caches, and deduplication logic.\u003c/p\u003e\n\u003cp\u003eThis issue affects jose: from 1.0.0 before 1.11.13.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "The `jose` library accepts ECDSA (ES256, ES256K, ES384, and ES512) JWS signatures of a non-canonical length. When verifying an ECDSA signature, `jose_jwk_kty_ec:verify/4` in `src/jwk/jose_jwk_kty_ec.erl` splits the raw signature in half by its actual byte length (`split_binary(Signature, byte_size(Signature) div 2)`) instead of enforcing the fixed length required by RFC 7518 \u00a73.4, and then decodes each half with `crypto:bytes_to_integer/1`, which ignores leading zero bytes.\n\nAs a result, an attacker who holds one valid token can prepend leading zero bytes to each of the R and S halves to produce longer signatures that still split evenly and decode to the same `(r, s)` pair, so many distinct signature byte strings all verify against the same key (signature malleability). This does not allow forging new payloads or impersonating a signer, because the underlying `(r, s)` values are unchanged. It does defeat any security control that assumes a valid token or its signature is unique, such as token-revocation-by-hash, replay or idempotency caches, and deduplication logic.\n\nThis issue affects jose: from 1.0.0 before 1.11.13."
}
],
"value": "The jose library accepts ECDSA (ES256, ES256K, ES384, and ES512) JWS signatures of a non-canonical length. When verifying an ECDSA signature, jose_jwk_kty_ec:verify/4 in src/jwk/jose_jwk_kty_ec.erl splits the raw signature in half by its actual byte length (split_binary(Signature, byte_size(Signature) div 2)) instead of enforcing the fixed length required by RFC 7518 \u00a73.4, and then decodes each half with crypto:bytes_to_integer/1, which ignores leading zero bytes.\n\nAs a result, an attacker who holds one valid token can prepend leading zero bytes to each of the R and S halves to produce longer signatures that still split evenly and decode to the same (r, s) pair, so many distinct signature byte strings all verify against the same key (signature malleability). This does not allow forging new payloads or impersonating a signer, because the underlying (r, s) values are unchanged. It does defeat any security control that assumes a valid token or its signature is unique, such as token-revocation-by-hash, replay or idempotency caches, and deduplication logic.\n\nThis issue affects jose: from 1.0.0 before 1.11.13."
}
],
"impacts": [
{
"capecId": "CAPEC-475",
"descriptions": [
{
"lang": "en",
"value": "CAPEC-475 Signature Spoofing by Improper Validation"
}
]
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "NONE",
"attackVector": "LOCAL",
"baseScore": 5.1,
"baseSeverity": "MEDIUM",
"privilegesRequired": "NONE",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N",
"version": "4.0",
"vulnAvailabilityImpact": "NONE",
"vulnConfidentialityImpact": "NONE",
"vulnIntegrityImpact": "LOW",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-347",
"description": "CWE-347 Improper Verification of Cryptographic Signature",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T19:53:56.649Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/security/advisories/GHSA-44hw-rpw9-mwg4"
},
{
"name": "EEF CNA record for CVE-2026-65632",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-65632.html"
},
{
"name": "OSV record EEF-CVE-2026-65632",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-65632"
},
{
"name": "Introducing commit a7746ec in potatosalad/erlang-jose",
"tags": [
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/a7746ecd4950f85a393136e449a91dac62b5c429"
},
{
"name": "Fix commit 72ce186 in potatosalad/erlang-jose",
"tags": [
"patch"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/72ce1866622b9329347dc52a94173ac0317bc9cf"
}
],
"source": {
"discovery": "EXTERNAL"
},
"title": "ECDSA signature length is not validated in jose, allowing signature malleability"
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-65632",
"datePublished": "2026-10-26T19:53:56.649Z",
"dateReserved": "2026-07-22T13:58:26.233Z",
"dateUpdated": "2026-10-26T19:53:56.649Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
CVE-2026-65631 (GCVE-0-2026-65631)
Vulnerability from cvelistv5 – Published: 2026-10-26 19:53 – Updated: 2026-10-26 19:53
VLAI
EPSS
VEX
Title
erlang-jose RSA JWK parsing attempts to factor an attacker-controlled modulus, enabling CPU-exhaustion denial of service
Summary
Inefficient Algorithmic Complexity in erlang-jose allows an unauthenticated remote attacker to cause a CPU-exhaustion denial of service by submitting a crafted RSA JSON Web Key.
When an application parses an untrusted JWK through the public jose_jwk:from_binary/1 or jose_jwk:from_map/1 API (or the Elixir wrappers JOSE.JWK.from_binary/1 and JOSE.JWK.from_map/1), an RSA private key that supplies d, e, and n but omits all Chinese Remainder Theorem parameters (p, q, dp, dq, qi) is routed into convert_sfm_to_crt/1, which tries to recover the missing primes by factoring the modulus. The three integers are read straight from the base64url input and are never validated as a real RSA key. When the modulus cannot be split into two factors (for example, when it is itself prime), the search loop convert_sfm_to_crt_find_p/6 performs a modular exponentiation over the attacker-sized modulus on every iteration and never succeeds. A single request of a few hundred bytes forces close to one CPU-second of work before an internal one-second watchdog kills the worker, and a larger modulus raises the cost further. By flooding such requests an attacker can saturate every scheduler and deny service, without credentials, a valid RSA key, or any special configuration.
This issue affects jose: from 1.7.7 before 1.11.13.
Severity
CWE
- CWE-407 - Inefficient Algorithmic Complexity
Assigner
References
5 references
| URL | Tags |
|---|---|
| https://github.com/potatosalad/erlang-jose/securi… | vendor-advisoryrelated |
| https://cna.erlef.org/cves/CVE-2026-65631.html | related |
| https://osv.dev/vulnerability/EEF-CVE-2026-65631 | related |
| https://github.com/potatosalad/erlang-jose/commit… | related |
| https://github.com/potatosalad/erlang-jose/commit… | patch |
Impacted products
2 products
| Vendor | Product | Version | |
|---|---|---|---|
| potatosalad | jose |
Affected:
1.7.7 , < 1.11.13
(semver)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
|
| potatosalad | jose |
Affected:
d19e1ba68d88c68d29aa942be2573a22dbafca1f , < bfd336c0062bff93e65d08c22361897e96afd956
(git)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
{
"containers": {
"cna": {
"affected": [
{
"collectionURL": "https://repo.hex.pm",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwk_kty_rsa",
"jose_jwk",
"\u0027Elixir.JOSE.JWK\u0027"
],
"packageName": "jose",
"packageURL": "pkg:hex/jose",
"product": "jose",
"programFiles": [
"src/jwk/jose_jwk_kty_rsa.erl",
"src/jwk/jose_jwk.erl",
"lib/jose/jwk.ex"
],
"programRoutines": [
{
"name": "jose_jwk_kty_rsa:from_map/1"
},
{
"name": "jose_jwk_kty_rsa:convert_sfm_to_crt/1"
},
{
"name": "jose_jwk_kty_rsa:convert_sfm_to_crt_find_p/6"
},
{
"name": "jose_jwk:from_binary/1"
},
{
"name": "jose_jwk:from_map/1"
},
{
"name": "\u0027Elixir.JOSE.JWK\u0027:from_binary/1"
},
{
"name": "\u0027Elixir.JOSE.JWK\u0027:from_map/1"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "1.11.13",
"status": "affected",
"version": "1.7.7",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwk_kty_rsa",
"jose_jwk",
"\u0027Elixir.JOSE.JWK\u0027"
],
"packageName": "potatosalad/erlang-jose",
"packageURL": "pkg:github/potatosalad/erlang-jose",
"product": "jose",
"programFiles": [
"src/jwk/jose_jwk_kty_rsa.erl",
"src/jwk/jose_jwk.erl",
"lib/jose/jwk.ex"
],
"programRoutines": [
{
"name": "jose_jwk_kty_rsa:from_map/1"
},
{
"name": "jose_jwk_kty_rsa:convert_sfm_to_crt/1"
},
{
"name": "jose_jwk_kty_rsa:convert_sfm_to_crt_find_p/6"
},
{
"name": "jose_jwk:from_binary/1"
},
{
"name": "jose_jwk:from_map/1"
},
{
"name": "\u0027Elixir.JOSE.JWK\u0027:from_binary/1"
},
{
"name": "\u0027Elixir.JOSE.JWK\u0027:from_map/1"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "bfd336c0062bff93e65d08c22361897e96afd956",
"status": "affected",
"version": "d19e1ba68d88c68d29aa942be2573a22dbafca1f",
"versionType": "git"
}
]
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.11.13",
"versionStartIncluding": "1.7.7",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "AND"
}
],
"credits": [
{
"lang": "en",
"type": "reporter",
"value": "Peter Ullrich"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Andrew Bennett"
},
{
"lang": "en",
"type": "analyst",
"value": "Jonatan M\u00e4nnchen / EEF"
}
],
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eInefficient Algorithmic Complexity in erlang-jose allows an unauthenticated remote attacker to cause a CPU-exhaustion denial of service by submitting a crafted RSA JSON Web Key.\u003c/p\u003e\n\u003cp\u003eWhen an application parses an untrusted JWK through the public \u003ccode\u003ejose_jwk:from_binary/1\u003c/code\u003e or \u003ccode\u003ejose_jwk:from_map/1\u003c/code\u003e API (or the Elixir wrappers \u003ccode\u003eJOSE.JWK.from_binary/1\u003c/code\u003e and \u003ccode\u003eJOSE.JWK.from_map/1\u003c/code\u003e), an RSA private key that supplies \u003ccode\u003ed\u003c/code\u003e, \u003ccode\u003ee\u003c/code\u003e, and \u003ccode\u003en\u003c/code\u003e but omits all Chinese Remainder Theorem parameters (\u003ccode\u003ep\u003c/code\u003e, \u003ccode\u003eq\u003c/code\u003e, \u003ccode\u003edp\u003c/code\u003e, \u003ccode\u003edq\u003c/code\u003e, \u003ccode\u003eqi\u003c/code\u003e) is routed into \u003ccode\u003econvert_sfm_to_crt/1\u003c/code\u003e, which tries to recover the missing primes by factoring the modulus. The three integers are read straight from the base64url input and are never validated as a real RSA key. When the modulus cannot be split into two factors (for example, when it is itself prime), the search loop \u003ccode\u003econvert_sfm_to_crt_find_p/6\u003c/code\u003e performs a modular exponentiation over the attacker-sized modulus on every iteration and never succeeds. A single request of a few hundred bytes forces close to one CPU-second of work before an internal one-second watchdog kills the worker, and a larger modulus raises the cost further. By flooding such requests an attacker can saturate every scheduler and deny service, without credentials, a valid RSA key, or any special configuration.\u003c/p\u003e\n\u003cp\u003eThis issue affects jose: from 1.7.7 before 1.11.13.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Inefficient Algorithmic Complexity in erlang-jose allows an unauthenticated remote attacker to cause a CPU-exhaustion denial of service by submitting a crafted RSA JSON Web Key.\n\nWhen an application parses an untrusted JWK through the public `jose_jwk:from_binary/1` or `jose_jwk:from_map/1` API (or the Elixir wrappers `JOSE.JWK.from_binary/1` and `JOSE.JWK.from_map/1`), an RSA private key that supplies `d`, `e`, and `n` but omits all Chinese Remainder Theorem parameters (`p`, `q`, `dp`, `dq`, `qi`) is routed into `convert_sfm_to_crt/1`, which tries to recover the missing primes by factoring the modulus. The three integers are read straight from the base64url input and are never validated as a real RSA key. When the modulus cannot be split into two factors (for example, when it is itself prime), the search loop `convert_sfm_to_crt_find_p/6` performs a modular exponentiation over the attacker-sized modulus on every iteration and never succeeds. A single request of a few hundred bytes forces close to one CPU-second of work before an internal one-second watchdog kills the worker, and a larger modulus raises the cost further. By flooding such requests an attacker can saturate every scheduler and deny service, without credentials, a valid RSA key, or any special configuration.\n\nThis issue affects jose: from 1.7.7 before 1.11.13."
}
],
"value": "Inefficient Algorithmic Complexity in erlang-jose allows an unauthenticated remote attacker to cause a CPU-exhaustion denial of service by submitting a crafted RSA JSON Web Key.\n\nWhen an application parses an untrusted JWK through the public jose_jwk:from_binary/1 or jose_jwk:from_map/1 API (or the Elixir wrappers JOSE.JWK.from_binary/1 and JOSE.JWK.from_map/1), an RSA private key that supplies d, e, and n but omits all Chinese Remainder Theorem parameters (p, q, dp, dq, qi) is routed into convert_sfm_to_crt/1, which tries to recover the missing primes by factoring the modulus. The three integers are read straight from the base64url input and are never validated as a real RSA key. When the modulus cannot be split into two factors (for example, when it is itself prime), the search loop convert_sfm_to_crt_find_p/6 performs a modular exponentiation over the attacker-sized modulus on every iteration and never succeeds. A single request of a few hundred bytes forces close to one CPU-second of work before an internal one-second watchdog kills the worker, and a larger modulus raises the cost further. By flooding such requests an attacker can saturate every scheduler and deny service, without credentials, a valid RSA key, or any special configuration.\n\nThis issue affects jose: from 1.7.7 before 1.11.13."
}
],
"impacts": [
{
"capecId": "CAPEC-130",
"descriptions": [
{
"lang": "en",
"value": "CAPEC-130 Excessive Allocation"
}
]
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "NONE",
"attackVector": "LOCAL",
"baseScore": 6.9,
"baseSeverity": "MEDIUM",
"privilegesRequired": "NONE",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N",
"version": "4.0",
"vulnAvailabilityImpact": "HIGH",
"vulnConfidentialityImpact": "NONE",
"vulnIntegrityImpact": "NONE",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-407",
"description": "CWE-407 Inefficient Algorithmic Complexity",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T19:53:45.204Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/security/advisories/GHSA-3m45-vrpj-xmrq"
},
{
"name": "EEF CNA record for CVE-2026-65631",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-65631.html"
},
{
"name": "OSV record EEF-CVE-2026-65631",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-65631"
},
{
"name": "Introducing commit d19e1ba in potatosalad/erlang-jose",
"tags": [
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/d19e1ba68d88c68d29aa942be2573a22dbafca1f"
},
{
"name": "Fix commit bfd336c in potatosalad/erlang-jose",
"tags": [
"patch"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/bfd336c0062bff93e65d08c22361897e96afd956"
}
],
"source": {
"discovery": "EXTERNAL"
},
"title": "erlang-jose RSA JWK parsing attempts to factor an attacker-controlled modulus, enabling CPU-exhaustion denial of service"
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-65631",
"datePublished": "2026-10-26T19:53:45.204Z",
"dateReserved": "2026-07-22T13:58:26.233Z",
"dateUpdated": "2026-10-26T19:53:45.204Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
CVE-2026-65629 (GCVE-0-2026-65629)
Vulnerability from cvelistv5 – Published: 2026-10-26 19:53 – Updated: 2026-10-26 19:53
VLAI
EPSS
VEX
Title
Weak PBKDF2 parameters for password-encrypted private-key export in jose
Summary
Use of Password Hash With Insufficient Computational Effort in the jose library allows an attacker who obtains a password-encrypted private-key export to recover the private key through an offline password-cracking attack.
When jose exports a password-encrypted private key with jose_jwk:to_der/2 (JOSE.JWK.to_der/2), the jose_jwk_der:to_binary/3 function in src/jwk/jose_jwk_der.erl serializes the key as a PKCS#8 EncryptedPrivateKeyInfo using the PBES2 scheme with hardcoded key-derivation parameters: PBKDF2-HMAC-SHA256 with an iteration count of 2048 and an 8-byte (64-bit) random salt. Neither value can be overridden by the caller.
Both values are far below current guidance (OWASP recommends on the order of 600,000 iterations for PBKDF2-HMAC-SHA256, and NIST recommends salts of at least 128 bits), so the key-stretching work factor is roughly 300 times lower than intended and the short salt reduces the cost of precomputation across keys. The symmetric encryption (AES-256-CBC with a 16-byte random IV) is not affected; the weakness is entirely in the derivation strength. An attacker who obtains one of these exported blobs (for example from a backup, configuration repository, object storage, or logs) can mount a cheap offline dictionary or brute-force attack against the export password, and success yields the full private key.
This issue affects jose: from 1.10.0 before 1.11.13.
Severity
CWE
- CWE-916 - Use of Password Hash With Insufficient Computational Effort
Assigner
References
5 references
| URL | Tags |
|---|---|
| https://github.com/potatosalad/erlang-jose/securi… | vendor-advisoryrelated |
| https://cna.erlef.org/cves/CVE-2026-65629.html | related |
| https://osv.dev/vulnerability/EEF-CVE-2026-65629 | related |
| https://github.com/potatosalad/erlang-jose/commit… | related |
| https://github.com/potatosalad/erlang-jose/commit… | patch |
Impacted products
2 products
| Vendor | Product | Version | |
|---|---|---|---|
| potatosalad | jose |
Affected:
1.10.0 , < 1.11.13
(semver)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
|
| potatosalad | jose |
Affected:
85fddd89ee56b6f9c19eff7d9cfffeef62c330b9 , < 461b261902531ca016190e780bb70862d561a7e0
(git)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
{
"containers": {
"cna": {
"affected": [
{
"collectionURL": "https://repo.hex.pm",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwk_der",
"jose_jwk",
"\u0027Elixir.JOSE.JWK\u0027"
],
"packageName": "jose",
"packageURL": "pkg:hex/jose",
"product": "jose",
"programFiles": [
"src/jwk/jose_jwk_der.erl",
"src/jwk/jose_jwk.erl",
"lib/jose/jwk.ex"
],
"programRoutines": [
{
"name": "jose_jwk_der:to_binary/3"
},
{
"name": "jose_jwk:to_der/2"
},
{
"name": "\u0027Elixir.JOSE.JWK\u0027:to_der/2"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "1.11.13",
"status": "affected",
"version": "1.10.0",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwk_der",
"jose_jwk",
"\u0027Elixir.JOSE.JWK\u0027"
],
"packageName": "potatosalad/erlang-jose",
"packageURL": "pkg:github/potatosalad/erlang-jose",
"product": "jose",
"programFiles": [
"src/jwk/jose_jwk_der.erl",
"src/jwk/jose_jwk.erl",
"lib/jose/jwk.ex"
],
"programRoutines": [
{
"name": "jose_jwk_der:to_binary/3"
},
{
"name": "jose_jwk:to_der/2"
},
{
"name": "\u0027Elixir.JOSE.JWK\u0027:to_der/2"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "461b261902531ca016190e780bb70862d561a7e0",
"status": "affected",
"version": "85fddd89ee56b6f9c19eff7d9cfffeef62c330b9",
"versionType": "git"
}
]
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.11.13",
"versionStartIncluding": "1.10.0",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "AND"
}
],
"credits": [
{
"lang": "en",
"type": "reporter",
"value": "Peter Ullrich"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Andrew Bennett"
},
{
"lang": "en",
"type": "analyst",
"value": "Jonatan M\u00e4nnchen / EEF"
}
],
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eUse of Password Hash With Insufficient Computational Effort in the jose library allows an attacker who obtains a password-encrypted private-key export to recover the private key through an offline password-cracking attack.\u003c/p\u003e\n\u003cp\u003eWhen jose exports a password-encrypted private key with \u003ccode\u003ejose_jwk:to_der/2\u003c/code\u003e (\u003ccode\u003eJOSE.JWK.to_der/2\u003c/code\u003e), the \u003ccode\u003ejose_jwk_der:to_binary/3\u003c/code\u003e function in \u003ccode\u003esrc/jwk/jose_jwk_der.erl\u003c/code\u003e serializes the key as a \u003ccode\u003ePKCS#8\u003c/code\u003e \u003ccode\u003eEncryptedPrivateKeyInfo\u003c/code\u003e using the PBES2 scheme with hardcoded key-derivation parameters: PBKDF2-HMAC-SHA256 with an iteration count of 2048 and an 8-byte (64-bit) random salt. Neither value can be overridden by the caller.\u003c/p\u003e\n\u003cp\u003eBoth values are far below current guidance (OWASP recommends on the order of 600,000 iterations for PBKDF2-HMAC-SHA256, and NIST recommends salts of at least 128 bits), so the key-stretching work factor is roughly 300 times lower than intended and the short salt reduces the cost of precomputation across keys. The symmetric encryption (AES-256-CBC with a 16-byte random IV) is not affected; the weakness is entirely in the derivation strength. An attacker who obtains one of these exported blobs (for example from a backup, configuration repository, object storage, or logs) can mount a cheap offline dictionary or brute-force attack against the export password, and success yields the full private key.\u003c/p\u003e\n\u003cp\u003eThis issue affects jose: from 1.10.0 before 1.11.13.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Use of Password Hash With Insufficient Computational Effort in the jose library allows an attacker who obtains a password-encrypted private-key export to recover the private key through an offline password-cracking attack.\n\nWhen jose exports a password-encrypted private key with `jose_jwk:to_der/2` (`JOSE.JWK.to_der/2`), the `jose_jwk_der:to_binary/3` function in `src/jwk/jose_jwk_der.erl` serializes the key as a `PKCS#8` `EncryptedPrivateKeyInfo` using the PBES2 scheme with hardcoded key-derivation parameters: PBKDF2-HMAC-SHA256 with an iteration count of 2048 and an 8-byte (64-bit) random salt. Neither value can be overridden by the caller.\n\nBoth values are far below current guidance (OWASP recommends on the order of 600,000 iterations for PBKDF2-HMAC-SHA256, and NIST recommends salts of at least 128 bits), so the key-stretching work factor is roughly 300 times lower than intended and the short salt reduces the cost of precomputation across keys. The symmetric encryption (AES-256-CBC with a 16-byte random IV) is not affected; the weakness is entirely in the derivation strength. An attacker who obtains one of these exported blobs (for example from a backup, configuration repository, object storage, or logs) can mount a cheap offline dictionary or brute-force attack against the export password, and success yields the full private key.\n\nThis issue affects jose: from 1.10.0 before 1.11.13."
}
],
"value": "Use of Password Hash With Insufficient Computational Effort in the jose library allows an attacker who obtains a password-encrypted private-key export to recover the private key through an offline password-cracking attack.\n\nWhen jose exports a password-encrypted private key with jose_jwk:to_der/2 (JOSE.JWK.to_der/2), the jose_jwk_der:to_binary/3 function in src/jwk/jose_jwk_der.erl serializes the key as a PKCS#8 EncryptedPrivateKeyInfo using the PBES2 scheme with hardcoded key-derivation parameters: PBKDF2-HMAC-SHA256 with an iteration count of 2048 and an 8-byte (64-bit) random salt. Neither value can be overridden by the caller.\n\nBoth values are far below current guidance (OWASP recommends on the order of 600,000 iterations for PBKDF2-HMAC-SHA256, and NIST recommends salts of at least 128 bits), so the key-stretching work factor is roughly 300 times lower than intended and the short salt reduces the cost of precomputation across keys. The symmetric encryption (AES-256-CBC with a 16-byte random IV) is not affected; the weakness is entirely in the derivation strength. An attacker who obtains one of these exported blobs (for example from a backup, configuration repository, object storage, or logs) can mount a cheap offline dictionary or brute-force attack against the export password, and success yields the full private key.\n\nThis issue affects jose: from 1.10.0 before 1.11.13."
}
],
"impacts": [
{
"capecId": "CAPEC-16",
"descriptions": [
{
"lang": "en",
"value": "CAPEC-16 Dictionary-based Password Attack"
}
]
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "PRESENT",
"attackVector": "LOCAL",
"baseScore": 7.4,
"baseSeverity": "HIGH",
"privilegesRequired": "NONE",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N",
"version": "4.0",
"vulnAvailabilityImpact": "NONE",
"vulnConfidentialityImpact": "HIGH",
"vulnIntegrityImpact": "HIGH",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-916",
"description": "CWE-916 Use of Password Hash With Insufficient Computational Effort",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T19:53:35.646Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/security/advisories/GHSA-h4gx-8jq2-mfhc"
},
{
"name": "EEF CNA record for CVE-2026-65629",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-65629.html"
},
{
"name": "OSV record EEF-CVE-2026-65629",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-65629"
},
{
"name": "Introducing commit 85fddd8 in potatosalad/erlang-jose",
"tags": [
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/85fddd89ee56b6f9c19eff7d9cfffeef62c330b9"
},
{
"name": "Fix commit 461b261 in potatosalad/erlang-jose",
"tags": [
"patch"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/461b261902531ca016190e780bb70862d561a7e0"
}
],
"source": {
"discovery": "EXTERNAL"
},
"title": "Weak PBKDF2 parameters for password-encrypted private-key export in jose",
"workarounds": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eWhen exporting a password-encrypted private key with \u003ccode\u003ejose_jwk:to_der/2\u003c/code\u003e (\u003ccode\u003eJOSE.JWK.to_der/2\u003c/code\u003e), use a long, high-entropy passphrase, since the weak key-derivation work factor only meaningfully lowers the cost of cracking guessable passwords. Restrict access to exported \u003ccode\u003eEncryptedPrivateKeyInfo\u003c/code\u003e blobs and keep them out of backups, repositories, object storage, and logs that an attacker could read.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "When exporting a password-encrypted private key with `jose_jwk:to_der/2` (`JOSE.JWK.to_der/2`), use a long, high-entropy passphrase, since the weak key-derivation work factor only meaningfully lowers the cost of cracking guessable passwords. Restrict access to exported `EncryptedPrivateKeyInfo` blobs and keep them out of backups, repositories, object storage, and logs that an attacker could read."
}
],
"value": "When exporting a password-encrypted private key with jose_jwk:to_der/2 (JOSE.JWK.to_der/2), use a long, high-entropy passphrase, since the weak key-derivation work factor only meaningfully lowers the cost of cracking guessable passwords. Restrict access to exported EncryptedPrivateKeyInfo blobs and keep them out of backups, repositories, object storage, and logs that an attacker could read."
}
]
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-65629",
"datePublished": "2026-10-26T19:53:35.646Z",
"dateReserved": "2026-07-22T13:58:26.233Z",
"dateUpdated": "2026-10-26T19:53:35.646Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
CVE-2026-65628 (GCVE-0-2026-65628)
Vulnerability from cvelistv5 – Published: 2026-10-26 19:53 – Updated: 2026-10-26 19:53
VLAI
EPSS
VEX
Title
Infinite recursion (CPU denial-of-service) in JOSE.JWK.shared_secret/2 on mismatched key types
Summary
jose_jwk:shared_secret/2 (exposed in Elixir as JOSE.JWK.shared_secret/2) derives an ECDH shared secret from two JWKs. Its first function clause only matches when both JWKs carry the same key type (kty) module, and its fallback clause re-invokes itself as shared_secret(from(YourJWK), from(MyJWK)). Because from/1 returns an already-parsed jose_jwk record unchanged, passing two JWKs whose key types differ (for example an EC key and an RSA key) makes the fallback clause re-enter with identical arguments, producing an unbounded tail-recursive loop that never returns and never crashes.
An application that derives a shared secret from an externally supplied peer public key without first checking that the peer key's type and curve match its own key can be driven into this loop by an attacker-controlled JWK, pinning an Erlang scheduler at 100% CPU. Repeated requests exhaust the available schedulers, resulting in a denial of service.
This issue affects jose: from 1.5.0 before 1.11.13.
Severity
CWE
- CWE-674 - Uncontrolled Recursion
Assigner
References
5 references
| URL | Tags |
|---|---|
| https://github.com/potatosalad/erlang-jose/securi… | vendor-advisoryrelated |
| https://cna.erlef.org/cves/CVE-2026-65628.html | related |
| https://osv.dev/vulnerability/EEF-CVE-2026-65628 | related |
| https://github.com/potatosalad/erlang-jose/commit… | related |
| https://github.com/potatosalad/erlang-jose/commit… | patch |
Impacted products
2 products
| Vendor | Product | Version | |
|---|---|---|---|
| potatosalad | jose |
Affected:
1.5.0 , < 1.11.13
(semver)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
|
| potatosalad | jose |
Affected:
7b80b9f55b9898e1a6901ce136061b241b021d7c , < 26182a7de63b91550035d3f08741f7d17f1f675a
(git)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
{
"containers": {
"cna": {
"affected": [
{
"collectionURL": "https://repo.hex.pm",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwk"
],
"packageName": "jose",
"packageURL": "pkg:hex/jose",
"product": "jose",
"programFiles": [
"src/jwk/jose_jwk.erl"
],
"programRoutines": [
{
"name": "jose_jwk:shared_secret/2"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "1.11.13",
"status": "affected",
"version": "1.5.0",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwk"
],
"packageName": "potatosalad/erlang-jose",
"packageURL": "pkg:github/potatosalad/erlang-jose",
"product": "jose",
"programFiles": [
"src/jwk/jose_jwk.erl"
],
"programRoutines": [
{
"name": "jose_jwk:shared_secret/2"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "26182a7de63b91550035d3f08741f7d17f1f675a",
"status": "affected",
"version": "7b80b9f55b9898e1a6901ce136061b241b021d7c",
"versionType": "git"
}
]
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.11.13",
"versionStartIncluding": "1.5.0",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "AND"
}
],
"credits": [
{
"lang": "en",
"type": "reporter",
"value": "Peter Ullrich"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Andrew Bennett"
},
{
"lang": "en",
"type": "analyst",
"value": "Jonatan M\u00e4nnchen / EEF"
}
],
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003e\u003ccode\u003ejose_jwk:shared_secret/2\u003c/code\u003e (exposed in Elixir as \u003ccode\u003eJOSE.JWK.shared_secret/2\u003c/code\u003e) derives an ECDH shared secret from two JWKs. Its first function clause only matches when both JWKs carry the same key type (\u003ccode\u003ekty\u003c/code\u003e) module, and its fallback clause re-invokes itself as \u003ccode\u003eshared_secret(from(YourJWK), from(MyJWK))\u003c/code\u003e. Because \u003ccode\u003efrom/1\u003c/code\u003e returns an already-parsed \u003ccode\u003ejose_jwk\u003c/code\u003e record unchanged, passing two JWKs whose key types differ (for example an EC key and an RSA key) makes the fallback clause re-enter with identical arguments, producing an unbounded tail-recursive loop that never returns and never crashes.\u003c/p\u003e\n\u003cp\u003eAn application that derives a shared secret from an externally supplied peer public key without first checking that the peer key\u0027s type and curve match its own key can be driven into this loop by an attacker-controlled JWK, pinning an Erlang scheduler at 100% CPU. Repeated requests exhaust the available schedulers, resulting in a denial of service.\u003c/p\u003e\n\u003cp\u003eThis issue affects jose: from 1.5.0 before 1.11.13.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "`jose_jwk:shared_secret/2` (exposed in Elixir as `JOSE.JWK.shared_secret/2`) derives an ECDH shared secret from two JWKs. Its first function clause only matches when both JWKs carry the same key type (`kty`) module, and its fallback clause re-invokes itself as `shared_secret(from(YourJWK), from(MyJWK))`. Because `from/1` returns an already-parsed `jose_jwk` record unchanged, passing two JWKs whose key types differ (for example an EC key and an RSA key) makes the fallback clause re-enter with identical arguments, producing an unbounded tail-recursive loop that never returns and never crashes.\n\nAn application that derives a shared secret from an externally supplied peer public key without first checking that the peer key\u0027s type and curve match its own key can be driven into this loop by an attacker-controlled JWK, pinning an Erlang scheduler at 100% CPU. Repeated requests exhaust the available schedulers, resulting in a denial of service.\n\nThis issue affects jose: from 1.5.0 before 1.11.13."
}
],
"value": "jose_jwk:shared_secret/2 (exposed in Elixir as JOSE.JWK.shared_secret/2) derives an ECDH shared secret from two JWKs. Its first function clause only matches when both JWKs carry the same key type (kty) module, and its fallback clause re-invokes itself as shared_secret(from(YourJWK), from(MyJWK)). Because from/1 returns an already-parsed jose_jwk record unchanged, passing two JWKs whose key types differ (for example an EC key and an RSA key) makes the fallback clause re-enter with identical arguments, producing an unbounded tail-recursive loop that never returns and never crashes.\n\nAn application that derives a shared secret from an externally supplied peer public key without first checking that the peer key\u0027s type and curve match its own key can be driven into this loop by an attacker-controlled JWK, pinning an Erlang scheduler at 100% CPU. Repeated requests exhaust the available schedulers, resulting in a denial of service.\n\nThis issue affects jose: from 1.5.0 before 1.11.13."
}
],
"impacts": [
{
"capecId": "CAPEC-130",
"descriptions": [
{
"lang": "en",
"value": "CAPEC-130 Excessive Allocation"
}
]
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "PRESENT",
"attackVector": "LOCAL",
"baseScore": 5.9,
"baseSeverity": "MEDIUM",
"privilegesRequired": "NONE",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N",
"version": "4.0",
"vulnAvailabilityImpact": "HIGH",
"vulnConfidentialityImpact": "NONE",
"vulnIntegrityImpact": "NONE",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-674",
"description": "CWE-674 Uncontrolled Recursion",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T19:53:27.625Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/security/advisories/GHSA-fpj2-9h59-32pp"
},
{
"name": "EEF CNA record for CVE-2026-65628",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-65628.html"
},
{
"name": "OSV record EEF-CVE-2026-65628",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-65628"
},
{
"name": "Introducing commit 7b80b9f in potatosalad/erlang-jose",
"tags": [
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/7b80b9f55b9898e1a6901ce136061b241b021d7c"
},
{
"name": "Fix commit 26182a7 in potatosalad/erlang-jose",
"tags": [
"patch"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/26182a7de63b91550035d3f08741f7d17f1f675a"
}
],
"source": {
"discovery": "EXTERNAL"
},
"title": "Infinite recursion (CPU denial-of-service) in JOSE.JWK.shared_secret/2 on mismatched key types",
"workarounds": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eBefore calling \u003ccode\u003eJOSE.JWK.shared_secret/2\u003c/code\u003e, verify that the externally supplied peer key\u0027s type (\u003ccode\u003ekty\u003c/code\u003e) and curve match your own key, and reject any key whose type does not match before attempting derivation.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Before calling `JOSE.JWK.shared_secret/2`, verify that the externally supplied peer key\u0027s type (`kty`) and curve match your own key, and reject any key whose type does not match before attempting derivation."
}
],
"value": "Before calling JOSE.JWK.shared_secret/2, verify that the externally supplied peer key\u0027s type (kty) and curve match your own key, and reject any key whose type does not match before attempting derivation."
}
]
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-65628",
"datePublished": "2026-10-26T19:53:27.625Z",
"dateReserved": "2026-07-22T13:58:26.233Z",
"dateUpdated": "2026-10-26T19:53:27.625Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
CVE-2026-65627 (GCVE-0-2026-65627)
Vulnerability from cvelistv5 – Published: 2026-10-26 19:53 – Updated: 2026-10-26 19:53
VLAI
EPSS
VEX
Title
Decompression bomb via unbounded zlib:inflate in jose_jwe_zip:uncompress/2
Summary
Improper Handling of Highly Compressed Data (Data Amplification) vulnerability in potatosalad jose (erlang-jose) allows a remote attacker to exhaust a node's memory with a small crafted JWE token.
The jose_jwe_zip:uncompress/2 function in src/jwe/jose_jwe_zip.erl decompresses the DEFLATE-compressed plaintext of a JWE that carries the optional zip: DEF header by calling zlib:inflate/2 on the entire attacker-controlled stream, with no bound on the output size or the inflation ratio. Raw DEFLATE reaches ratios around 1000:1 on highly repetitive input, so a few-kilobyte token inflates to hundreds of megabytes or gigabytes in a single call.
Decompression runs automatically during decryption through jose_jwe:block_decrypt/2 (JOSE.JWE.block_decrypt/2 in Elixir), before the recipient can inspect or reject the payload. With the common asymmetric key-management algorithms (RSA-OAEP, ECDH-ES) an attacker needs only the recipient's public key to craft such a token, so no authentication or secret material is required. A single small token can exhaust the node's memory and crash the BEAM, denying service to all users.
This issue affects jose: from 1.0.0 before 1.11.13.
Severity
CWE
- CWE-409 - Improper Handling of Highly Compressed Data (Data Amplification)
Assigner
References
5 references
| URL | Tags |
|---|---|
| https://github.com/potatosalad/erlang-jose/securi… | vendor-advisoryrelated |
| https://cna.erlef.org/cves/CVE-2026-65627.html | related |
| https://osv.dev/vulnerability/EEF-CVE-2026-65627 | related |
| https://github.com/potatosalad/erlang-jose/commit… | related |
| https://github.com/potatosalad/erlang-jose/commit… | patch |
Impacted products
2 products
| Vendor | Product | Version | |
|---|---|---|---|
| potatosalad | jose |
Affected:
1.0.0 , < 1.11.13
(semver)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
|
| potatosalad | jose |
Affected:
a7746ecd4950f85a393136e449a91dac62b5c429 , < 857eb8e7f2d33e2c9ca2189e77226561cacaf2ad
(git)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
{
"containers": {
"cna": {
"affected": [
{
"collectionURL": "https://repo.hex.pm",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwe_zip",
"jose_jwe",
"\u0027Elixir.JOSE.JWE\u0027"
],
"packageName": "jose",
"packageURL": "pkg:hex/jose",
"product": "jose",
"programFiles": [
"src/jwe/jose_jwe_zip.erl",
"src/jwe/jose_jwe.erl",
"lib/jose/jwe.ex"
],
"programRoutines": [
{
"name": "jose_jwe_zip:uncompress/2"
},
{
"name": "jose_jwe:block_decrypt/2"
},
{
"name": "\u0027Elixir.JOSE.JWE\u0027:block_decrypt/2"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "1.11.13",
"status": "affected",
"version": "1.0.0",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwe_zip",
"jose_jwe",
"\u0027Elixir.JOSE.JWE\u0027"
],
"packageName": "potatosalad/erlang-jose",
"packageURL": "pkg:github/potatosalad/erlang-jose",
"product": "jose",
"programFiles": [
"src/jwe/jose_jwe_zip.erl",
"src/jwe/jose_jwe.erl",
"lib/jose/jwe.ex"
],
"programRoutines": [
{
"name": "jose_jwe_zip:uncompress/2"
},
{
"name": "jose_jwe:block_decrypt/2"
},
{
"name": "\u0027Elixir.JOSE.JWE\u0027:block_decrypt/2"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "857eb8e7f2d33e2c9ca2189e77226561cacaf2ad",
"status": "affected",
"version": "a7746ecd4950f85a393136e449a91dac62b5c429",
"versionType": "git"
}
]
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.11.13",
"versionStartIncluding": "1.0.0",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "AND"
}
],
"credits": [
{
"lang": "en",
"type": "reporter",
"value": "Peter Ullrich"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Andrew Bennett"
},
{
"lang": "en",
"type": "analyst",
"value": "Jonatan M\u00e4nnchen / EEF"
}
],
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eImproper Handling of Highly Compressed Data (Data Amplification) vulnerability in potatosalad jose (erlang-jose) allows a remote attacker to exhaust a node\u0027s memory with a small crafted JWE token.\u003c/p\u003e\n\u003cp\u003eThe \u003ccode\u003ejose_jwe_zip:uncompress/2\u003c/code\u003e function in \u003ccode\u003esrc/jwe/jose_jwe_zip.erl\u003c/code\u003e decompresses the DEFLATE-compressed plaintext of a JWE that carries the optional \u003ccode\u003ezip: DEF\u003c/code\u003e header by calling \u003ccode\u003ezlib:inflate/2\u003c/code\u003e on the entire attacker-controlled stream, with no bound on the output size or the inflation ratio. Raw DEFLATE reaches ratios around 1000:1 on highly repetitive input, so a few-kilobyte token inflates to hundreds of megabytes or gigabytes in a single call.\u003c/p\u003e\n\u003cp\u003eDecompression runs automatically during decryption through \u003ccode\u003ejose_jwe:block_decrypt/2\u003c/code\u003e (\u003ccode\u003eJOSE.JWE.block_decrypt/2\u003c/code\u003e in Elixir), before the recipient can inspect or reject the payload. With the common asymmetric key-management algorithms (RSA-OAEP, ECDH-ES) an attacker needs only the recipient\u0027s public key to craft such a token, so no authentication or secret material is required. A single small token can exhaust the node\u0027s memory and crash the BEAM, denying service to all users.\u003c/p\u003e\n\u003cp\u003eThis issue affects jose: from 1.0.0 before 1.11.13.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Improper Handling of Highly Compressed Data (Data Amplification) vulnerability in potatosalad jose (erlang-jose) allows a remote attacker to exhaust a node\u0027s memory with a small crafted JWE token.\n\nThe `jose_jwe_zip:uncompress/2` function in `src/jwe/jose_jwe_zip.erl` decompresses the DEFLATE-compressed plaintext of a JWE that carries the optional `zip: DEF` header by calling `zlib:inflate/2` on the entire attacker-controlled stream, with no bound on the output size or the inflation ratio. Raw DEFLATE reaches ratios around 1000:1 on highly repetitive input, so a few-kilobyte token inflates to hundreds of megabytes or gigabytes in a single call.\n\nDecompression runs automatically during decryption through `jose_jwe:block_decrypt/2` (`JOSE.JWE.block_decrypt/2` in Elixir), before the recipient can inspect or reject the payload. With the common asymmetric key-management algorithms (RSA-OAEP, ECDH-ES) an attacker needs only the recipient\u0027s public key to craft such a token, so no authentication or secret material is required. A single small token can exhaust the node\u0027s memory and crash the BEAM, denying service to all users.\n\nThis issue affects jose: from 1.0.0 before 1.11.13."
}
],
"value": "Improper Handling of Highly Compressed Data (Data Amplification) vulnerability in potatosalad jose (erlang-jose) allows a remote attacker to exhaust a node\u0027s memory with a small crafted JWE token.\n\nThe jose_jwe_zip:uncompress/2 function in src/jwe/jose_jwe_zip.erl decompresses the DEFLATE-compressed plaintext of a JWE that carries the optional zip: DEF header by calling zlib:inflate/2 on the entire attacker-controlled stream, with no bound on the output size or the inflation ratio. Raw DEFLATE reaches ratios around 1000:1 on highly repetitive input, so a few-kilobyte token inflates to hundreds of megabytes or gigabytes in a single call.\n\nDecompression runs automatically during decryption through jose_jwe:block_decrypt/2 (JOSE.JWE.block_decrypt/2 in Elixir), before the recipient can inspect or reject the payload. With the common asymmetric key-management algorithms (RSA-OAEP, ECDH-ES) an attacker needs only the recipient\u0027s public key to craft such a token, so no authentication or secret material is required. A single small token can exhaust the node\u0027s memory and crash the BEAM, denying service to all users.\n\nThis issue affects jose: from 1.0.0 before 1.11.13."
}
],
"impacts": [
{
"capecId": "CAPEC-130",
"descriptions": [
{
"lang": "en",
"value": "CAPEC-130 Excessive Allocation"
}
]
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "NONE",
"attackVector": "LOCAL",
"baseScore": 6.9,
"baseSeverity": "MEDIUM",
"privilegesRequired": "NONE",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N",
"version": "4.0",
"vulnAvailabilityImpact": "HIGH",
"vulnConfidentialityImpact": "NONE",
"vulnIntegrityImpact": "NONE",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-409",
"description": "CWE-409 Improper Handling of Highly Compressed Data (Data Amplification)",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T19:53:16.336Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/security/advisories/GHSA-wfpv-qxp8-x5gm"
},
{
"name": "EEF CNA record for CVE-2026-65627",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-65627.html"
},
{
"name": "OSV record EEF-CVE-2026-65627",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-65627"
},
{
"name": "Introducing commit a7746ec in potatosalad/erlang-jose",
"tags": [
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/a7746ecd4950f85a393136e449a91dac62b5c429"
},
{
"name": "Fix commit 857eb8e in potatosalad/erlang-jose",
"tags": [
"patch"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/857eb8e7f2d33e2c9ca2189e77226561cacaf2ad"
}
],
"source": {
"discovery": "EXTERNAL"
},
"title": "Decompression bomb via unbounded zlib:inflate in jose_jwe_zip:uncompress/2",
"workarounds": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eReject JWE tokens that carry a \u003ccode\u003ezip\u003c/code\u003e header before passing them to \u003ccode\u003ejose_jwe:block_decrypt/2\u003c/code\u003e. DEFLATE compression is rarely used in legitimate JWE traffic, so untrusted tokens whose protected header contains \u003ccode\u003ezip: DEF\u003c/code\u003e can be inspected and filtered out before decryption.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Reject JWE tokens that carry a `zip` header before passing them to `jose_jwe:block_decrypt/2`. DEFLATE compression is rarely used in legitimate JWE traffic, so untrusted tokens whose protected header contains `zip: DEF` can be inspected and filtered out before decryption."
}
],
"value": "Reject JWE tokens that carry a zip header before passing them to jose_jwe:block_decrypt/2. DEFLATE compression is rarely used in legitimate JWE traffic, so untrusted tokens whose protected header contains zip: DEF can be inspected and filtered out before decryption."
}
]
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-65627",
"datePublished": "2026-10-26T19:53:16.336Z",
"dateReserved": "2026-07-22T13:58:26.233Z",
"dateUpdated": "2026-10-26T19:53:16.336Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
CVE-2026-65626 (GCVE-0-2026-65626)
Vulnerability from cvelistv5 – Published: 2026-10-26 19:53 – Updated: 2026-10-26 19:53
VLAI
EPSS
VEX
Title
Bleichenbacher padding oracle in RSAES-PKCS1-v1_5 decryption in jose
Summary
The pure-Erlang RSAES-PKCS1-v1_5 decryption in the jose_jwa_pkcs1 module is a Bleichenbacher padding oracle. eme_pkcs1_decode/2 returns the recovered message when a decrypted block has valid PKCS#1 v1.5 padding (a leading 0x00 0x02, a padding string of at least eight non-zero bytes, and a 0x00 separator) and returns a distinct error result otherwise, and rsaes_pkcs1_decrypt/2 additionally returns {error, {badsize, _}} when the length check fails. The implementation applies no implicit-rejection countermeasure (RFC 8017 §7.2.2): it does not substitute a deterministic pseudo-random plaintext on a padding failure, so a one-bit padding-conformance signal leaks to the caller. Because the underlying modular exponentiation in dp/2 is a raw, non-blinded crypto:mod_pow/3, the padding check also stays distinguishable by timing even when an application normalizes every failure to a single error value.
An unauthenticated attacker who knows only the public RSA key and can submit ciphertexts to a decryption endpoint that unwraps RSA1_5 JWE keys (or otherwise calls decrypt_private/3 with rsa_pkcs1_padding) can use this oracle to recover the plaintext of intercepted ciphertexts, such as content-encryption keys and thus the protected message, or to forge signatures, through roughly 10^4 to 10^6 adaptive chosen-ciphertext queries.
This issue affects jose: from 1.3.0 before 1.11.13.
Severity
CWE
- CWE-203 - Observable Discrepancy
Assigner
References
5 references
| URL | Tags |
|---|---|
| https://github.com/potatosalad/erlang-jose/securi… | vendor-advisoryrelated |
| https://cna.erlef.org/cves/CVE-2026-65626.html | related |
| https://osv.dev/vulnerability/EEF-CVE-2026-65626 | related |
| https://github.com/potatosalad/erlang-jose/commit… | related |
| https://github.com/potatosalad/erlang-jose/commit… | patch |
Impacted products
2 products
| Vendor | Product | Version | |
|---|---|---|---|
| potatosalad | jose |
Affected:
1.3.0 , < 1.11.13
(semver)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
|
| potatosalad | jose |
Affected:
853c5d4c4c0bd2a7ecb055b237f4284184e176c8 , < 0eac8cef9aaa48fb6846f4e47a0002dc4a73966d
(git)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
{
"containers": {
"cna": {
"affected": [
{
"collectionURL": "https://repo.hex.pm",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwa_pkcs1"
],
"packageName": "jose",
"packageURL": "pkg:hex/jose",
"product": "jose",
"programFiles": [
"src/jwa/jose_jwa_pkcs1.erl"
],
"programRoutines": [
{
"name": "jose_jwa_pkcs1:decrypt_private/3"
},
{
"name": "jose_jwa_pkcs1:rsaes_pkcs1_decrypt/2"
},
{
"name": "jose_jwa_pkcs1:eme_pkcs1_decode/2"
},
{
"name": "jose_jwa_pkcs1:dp/2"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "1.11.13",
"status": "affected",
"version": "1.3.0",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwa_pkcs1"
],
"packageName": "potatosalad/erlang-jose",
"packageURL": "pkg:github/potatosalad/erlang-jose",
"product": "jose",
"programFiles": [
"src/jwa/jose_jwa_pkcs1.erl"
],
"programRoutines": [
{
"name": "jose_jwa_pkcs1:decrypt_private/3"
},
{
"name": "jose_jwa_pkcs1:rsaes_pkcs1_decrypt/2"
},
{
"name": "jose_jwa_pkcs1:eme_pkcs1_decode/2"
},
{
"name": "jose_jwa_pkcs1:dp/2"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "0eac8cef9aaa48fb6846f4e47a0002dc4a73966d",
"status": "affected",
"version": "853c5d4c4c0bd2a7ecb055b237f4284184e176c8",
"versionType": "git"
}
]
}
],
"configurations": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eThe vulnerable code path is only reached when jose performs RSAES-PKCS1-v1_5 decryption with its pure-Erlang fallback (the \u003ccode\u003ejose_jwa_pkcs1\u003c/code\u003e module) instead of the native OTP \u003ccode\u003epublic_key\u003c/code\u003e implementation. This requires the crypto_fallback option to be enabled (\u003ccode\u003eapplication:set_env(jose, crypto_fallback, true)\u003c/code\u003e, or \u003ccode\u003eJOSE.crypto_fallback(true)\u003c/code\u003e in Elixir) and the OTP runtime not to provide native RSA1_5 decryption. When native OTP RSA support is selected, decryption does not go through \u003ccode\u003ejose_jwa_pkcs1\u003c/code\u003e.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "The vulnerable code path is only reached when jose performs RSAES-PKCS1-v1_5 decryption with its pure-Erlang fallback (the `jose_jwa_pkcs1` module) instead of the native OTP `public_key` implementation. This requires the crypto_fallback option to be enabled (`application:set_env(jose, crypto_fallback, true)`, or `JOSE.crypto_fallback(true)` in Elixir) and the OTP runtime not to provide native RSA1_5 decryption. When native OTP RSA support is selected, decryption does not go through `jose_jwa_pkcs1`."
}
],
"value": "The vulnerable code path is only reached when jose performs RSAES-PKCS1-v1_5 decryption with its pure-Erlang fallback (the jose_jwa_pkcs1 module) instead of the native OTP public_key implementation. This requires the crypto_fallback option to be enabled (application:set_env(jose, crypto_fallback, true), or JOSE.crypto_fallback(true) in Elixir) and the OTP runtime not to provide native RSA1_5 decryption. When native OTP RSA support is selected, decryption does not go through jose_jwa_pkcs1."
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.11.13",
"versionStartIncluding": "1.3.0",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "AND"
}
],
"credits": [
{
"lang": "en",
"type": "reporter",
"value": "Peter Ullrich"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Andrew Bennett"
},
{
"lang": "en",
"type": "analyst",
"value": "Jonatan M\u00e4nnchen / EEF"
}
],
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eThe pure-Erlang RSAES-PKCS1-v1_5 decryption in the \u003ccode\u003ejose_jwa_pkcs1\u003c/code\u003e module is a Bleichenbacher padding oracle. \u003ccode\u003eeme_pkcs1_decode/2\u003c/code\u003e returns the recovered message when a decrypted block has valid \u003ccode\u003ePKCS#1\u003c/code\u003e v1.5 padding (a leading \u003ccode\u003e0x00 0x02\u003c/code\u003e, a padding string of at least eight non-zero bytes, and a \u003ccode\u003e0x00\u003c/code\u003e separator) and returns a distinct error result otherwise, and \u003ccode\u003ersaes_pkcs1_decrypt/2\u003c/code\u003e additionally returns \u003ccode\u003e{error, {badsize, _}}\u003c/code\u003e when the length check fails. The implementation applies no implicit-rejection countermeasure (RFC 8017 \u00a77.2.2): it does not substitute a deterministic pseudo-random plaintext on a padding failure, so a one-bit padding-conformance signal leaks to the caller. Because the underlying modular exponentiation in \u003ccode\u003edp/2\u003c/code\u003e is a raw, non-blinded \u003ccode\u003ecrypto:mod_pow/3\u003c/code\u003e, the padding check also stays distinguishable by timing even when an application normalizes every failure to a single error value.\u003c/p\u003e\n\u003cp\u003eAn unauthenticated attacker who knows only the public RSA key and can submit ciphertexts to a decryption endpoint that unwraps RSA1_5 JWE keys (or otherwise calls \u003ccode\u003edecrypt_private/3\u003c/code\u003e with \u003ccode\u003ersa_pkcs1_padding\u003c/code\u003e) can use this oracle to recover the plaintext of intercepted ciphertexts, such as content-encryption keys and thus the protected message, or to forge signatures, through roughly 10^4 to 10^6 adaptive chosen-ciphertext queries.\u003c/p\u003e\n\u003cp\u003eThis issue affects jose: from 1.3.0 before 1.11.13.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "The pure-Erlang RSAES-PKCS1-v1_5 decryption in the `jose_jwa_pkcs1` module is a Bleichenbacher padding oracle. `eme_pkcs1_decode/2` returns the recovered message when a decrypted block has valid `PKCS#1` v1.5 padding (a leading `0x00 0x02`, a padding string of at least eight non-zero bytes, and a `0x00` separator) and returns a distinct error result otherwise, and `rsaes_pkcs1_decrypt/2` additionally returns `{error, {badsize, _}}` when the length check fails. The implementation applies no implicit-rejection countermeasure (RFC 8017 \u00a77.2.2): it does not substitute a deterministic pseudo-random plaintext on a padding failure, so a one-bit padding-conformance signal leaks to the caller. Because the underlying modular exponentiation in `dp/2` is a raw, non-blinded `crypto:mod_pow/3`, the padding check also stays distinguishable by timing even when an application normalizes every failure to a single error value.\n\nAn unauthenticated attacker who knows only the public RSA key and can submit ciphertexts to a decryption endpoint that unwraps RSA1_5 JWE keys (or otherwise calls `decrypt_private/3` with `rsa_pkcs1_padding`) can use this oracle to recover the plaintext of intercepted ciphertexts, such as content-encryption keys and thus the protected message, or to forge signatures, through roughly 10^4 to 10^6 adaptive chosen-ciphertext queries.\n\nThis issue affects jose: from 1.3.0 before 1.11.13."
}
],
"value": "The pure-Erlang RSAES-PKCS1-v1_5 decryption in the jose_jwa_pkcs1 module is a Bleichenbacher padding oracle. eme_pkcs1_decode/2 returns the recovered message when a decrypted block has valid PKCS#1 v1.5 padding (a leading 0x00 0x02, a padding string of at least eight non-zero bytes, and a 0x00 separator) and returns a distinct error result otherwise, and rsaes_pkcs1_decrypt/2 additionally returns {error, {badsize, _}} when the length check fails. The implementation applies no implicit-rejection countermeasure (RFC 8017 \u00a77.2.2): it does not substitute a deterministic pseudo-random plaintext on a padding failure, so a one-bit padding-conformance signal leaks to the caller. Because the underlying modular exponentiation in dp/2 is a raw, non-blinded crypto:mod_pow/3, the padding check also stays distinguishable by timing even when an application normalizes every failure to a single error value.\n\nAn unauthenticated attacker who knows only the public RSA key and can submit ciphertexts to a decryption endpoint that unwraps RSA1_5 JWE keys (or otherwise calls decrypt_private/3 with rsa_pkcs1_padding) can use this oracle to recover the plaintext of intercepted ciphertexts, such as content-encryption keys and thus the protected message, or to forge signatures, through roughly 10^4 to 10^6 adaptive chosen-ciphertext queries.\n\nThis issue affects jose: from 1.3.0 before 1.11.13."
}
],
"impacts": [
{
"capecId": "CAPEC-463",
"descriptions": [
{
"lang": "en",
"value": "CAPEC-463 Padding Oracle Crypto Attack"
}
]
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "PRESENT",
"attackVector": "LOCAL",
"baseScore": 5.9,
"baseSeverity": "MEDIUM",
"privilegesRequired": "NONE",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N",
"version": "4.0",
"vulnAvailabilityImpact": "NONE",
"vulnConfidentialityImpact": "HIGH",
"vulnIntegrityImpact": "NONE",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-203",
"description": "CWE-203 Observable Discrepancy",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T19:53:05.620Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/security/advisories/GHSA-vwvr-f994-6j9j"
},
{
"name": "EEF CNA record for CVE-2026-65626",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-65626.html"
},
{
"name": "OSV record EEF-CVE-2026-65626",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-65626"
},
{
"name": "Introducing commit 853c5d4 in potatosalad/erlang-jose",
"tags": [
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/853c5d4c4c0bd2a7ecb055b237f4284184e176c8"
},
{
"name": "Fix commit 0eac8ce in potatosalad/erlang-jose",
"tags": [
"patch"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/0eac8cef9aaa48fb6846f4e47a0002dc4a73966d"
}
],
"source": {
"discovery": "EXTERNAL"
},
"title": "Bleichenbacher padding oracle in RSAES-PKCS1-v1_5 decryption in jose"
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-65626",
"datePublished": "2026-10-26T19:53:05.620Z",
"dateReserved": "2026-07-22T13:55:59.401Z",
"dateUpdated": "2026-10-26T19:53:05.620Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
CVE-2026-65625 (GCVE-0-2026-65625)
Vulnerability from cvelistv5 – Published: 2026-10-26 19:52 – Updated: 2026-10-26 19:52
VLAI
EPSS
VEX
Title
Attacker-controlled AES-GCM authentication tag length allows tag forgery in jose
Summary
The pure-Erlang AES-GCM fallback in jose_jwa_aes derives the number of verified authentication tag bits from the attacker-supplied tag itself. In the {aes_gcm, Bits} clause of block_decrypt/4, the incoming tag is guarded only by is_binary/1, with no check on its length. Verification in gcm_block_decrypt/6 then computes TBits = bit_size(T) and compares only those bits of the real 128-bit tag. An attacker who controls a JWE token can truncate the authentication tag to as little as 8 bits, so only 8 bits are ever checked. This reduces forgery resistance from 2^-128 to 2^-8, and a forged ciphertext is reliably accepted as authentic within 256 attempts without knowledge of the key (an authentication tag forgery and integrity bypass). Supplying a tag longer than 128 bits instead causes a badmatch that crashes the decrypting process. The fallback is reached through the public JWE decryption path whenever AES-GCM is not provided by a native crypto NIF, for example on FIPS or stripped or older OTP builds.
This issue affects jose: from 1.2.0 before 1.11.13.
Severity
CWE
- CWE-354 - Improper Validation of Integrity Check Value
Assigner
References
5 references
| URL | Tags |
|---|---|
| https://github.com/potatosalad/erlang-jose/securi… | vendor-advisoryrelated |
| https://cna.erlef.org/cves/CVE-2026-65625.html | related |
| https://osv.dev/vulnerability/EEF-CVE-2026-65625 | related |
| https://github.com/potatosalad/erlang-jose/commit… | related |
| https://github.com/potatosalad/erlang-jose/commit… | patch |
Impacted products
2 products
| Vendor | Product | Version | |
|---|---|---|---|
| potatosalad | jose |
Affected:
1.2.0 , < 1.11.13
(semver)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
|
| potatosalad | jose |
Affected:
8848b172575fb7d7e1e2977e8ae0a21678d2157a , < 3fa1f8e3efda0da5ce6f4c9984789f979dc02740
(git)
cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:* |
{
"containers": {
"cna": {
"affected": [
{
"collectionURL": "https://repo.hex.pm",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwa_aes"
],
"packageName": "jose",
"packageURL": "pkg:hex/jose",
"product": "jose",
"programFiles": [
"src/jwa/jose_jwa_aes.erl"
],
"programRoutines": [
{
"name": "jose_jwa_aes:block_decrypt/4"
},
{
"name": "jose_jwa_aes:gcm_block_decrypt/6"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "1.11.13",
"status": "affected",
"version": "1.2.0",
"versionType": "semver"
}
]
},
{
"collectionURL": "https://github.com",
"cpes": [
"cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*"
],
"defaultStatus": "unaffected",
"modules": [
"jose_jwa_aes"
],
"packageName": "potatosalad/erlang-jose",
"packageURL": "pkg:github/potatosalad/erlang-jose",
"product": "jose",
"programFiles": [
"src/jwa/jose_jwa_aes.erl"
],
"programRoutines": [
{
"name": "jose_jwa_aes:block_decrypt/4"
},
{
"name": "jose_jwa_aes:gcm_block_decrypt/6"
}
],
"repo": "https://github.com/potatosalad/erlang-jose",
"vendor": "potatosalad",
"versions": [
{
"lessThan": "3fa1f8e3efda0da5ce6f4c9984789f979dc02740",
"status": "affected",
"version": "8848b172575fb7d7e1e2977e8ae0a21678d2157a",
"versionType": "git"
}
]
}
],
"configurations": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eThis vulnerability is only exploitable when AES-GCM is handled by the pure-Erlang \u003ccode\u003ejose_jwa_aes\u003c/code\u003e fallback. That fallback is used on deployments where the Erlang/OTP \u003ccode\u003ecrypto\u003c/code\u003e NIF does not expose native AES-GCM (for example FIPS builds, or stripped or older OTP releases). Deployments with a native AES-GCM crypto provider dispatch GCM through \u003ccode\u003ecrypto\u003c/code\u003e and are not affected.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "This vulnerability is only exploitable when AES-GCM is handled by the pure-Erlang `jose_jwa_aes` fallback. That fallback is used on deployments where the Erlang/OTP `crypto` NIF does not expose native AES-GCM (for example FIPS builds, or stripped or older OTP releases). Deployments with a native AES-GCM crypto provider dispatch GCM through `crypto` and are not affected."
}
],
"value": "This vulnerability is only exploitable when AES-GCM is handled by the pure-Erlang jose_jwa_aes fallback. That fallback is used on deployments where the Erlang/OTP crypto NIF does not expose native AES-GCM (for example FIPS builds, or stripped or older OTP releases). Deployments with a native AES-GCM crypto provider dispatch GCM through crypto and are not affected."
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:potatosalad:jose:*:*:*:*:*:*:*:*",
"versionEndExcluding": "1.11.13",
"versionStartIncluding": "1.2.0",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "AND"
}
],
"credits": [
{
"lang": "en",
"type": "reporter",
"value": "Peter Ullrich"
},
{
"lang": "en",
"type": "remediation developer",
"value": "Andrew Bennett"
},
{
"lang": "en",
"type": "analyst",
"value": "Jonatan M\u00e4nnchen / EEF"
}
],
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eThe pure-Erlang AES-GCM fallback in \u003ccode\u003ejose_jwa_aes\u003c/code\u003e derives the number of verified authentication tag bits from the attacker-supplied tag itself. In the \u003ccode\u003e{aes_gcm, Bits}\u003c/code\u003e clause of \u003ccode\u003eblock_decrypt/4\u003c/code\u003e, the incoming tag is guarded only by \u003ccode\u003eis_binary/1\u003c/code\u003e, with no check on its length. Verification in \u003ccode\u003egcm_block_decrypt/6\u003c/code\u003e then computes \u003ccode\u003eTBits = bit_size(T)\u003c/code\u003e and compares only those bits of the real 128-bit tag. An attacker who controls a JWE token can truncate the authentication tag to as little as 8 bits, so only 8 bits are ever checked. This reduces forgery resistance from 2^-128 to 2^-8, and a forged ciphertext is reliably accepted as authentic within 256 attempts without knowledge of the key (an authentication tag forgery and integrity bypass). Supplying a tag longer than 128 bits instead causes a badmatch that crashes the decrypting process. The fallback is reached through the public JWE decryption path whenever AES-GCM is not provided by a native crypto NIF, for example on FIPS or stripped or older OTP builds.\u003c/p\u003e\n\u003cp\u003eThis issue affects jose: from 1.2.0 before 1.11.13.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "The pure-Erlang AES-GCM fallback in `jose_jwa_aes` derives the number of verified authentication tag bits from the attacker-supplied tag itself. In the `{aes_gcm, Bits}` clause of `block_decrypt/4`, the incoming tag is guarded only by `is_binary/1`, with no check on its length. Verification in `gcm_block_decrypt/6` then computes `TBits = bit_size(T)` and compares only those bits of the real 128-bit tag. An attacker who controls a JWE token can truncate the authentication tag to as little as 8 bits, so only 8 bits are ever checked. This reduces forgery resistance from 2^-128 to 2^-8, and a forged ciphertext is reliably accepted as authentic within 256 attempts without knowledge of the key (an authentication tag forgery and integrity bypass). Supplying a tag longer than 128 bits instead causes a badmatch that crashes the decrypting process. The fallback is reached through the public JWE decryption path whenever AES-GCM is not provided by a native crypto NIF, for example on FIPS or stripped or older OTP builds.\n\nThis issue affects jose: from 1.2.0 before 1.11.13."
}
],
"value": "The pure-Erlang AES-GCM fallback in jose_jwa_aes derives the number of verified authentication tag bits from the attacker-supplied tag itself. In the {aes_gcm, Bits} clause of block_decrypt/4, the incoming tag is guarded only by is_binary/1, with no check on its length. Verification in gcm_block_decrypt/6 then computes TBits = bit_size(T) and compares only those bits of the real 128-bit tag. An attacker who controls a JWE token can truncate the authentication tag to as little as 8 bits, so only 8 bits are ever checked. This reduces forgery resistance from 2^-128 to 2^-8, and a forged ciphertext is reliably accepted as authentic within 256 attempts without knowledge of the key (an authentication tag forgery and integrity bypass). Supplying a tag longer than 128 bits instead causes a badmatch that crashes the decrypting process. The fallback is reached through the public JWE decryption path whenever AES-GCM is not provided by a native crypto NIF, for example on FIPS or stripped or older OTP builds.\n\nThis issue affects jose: from 1.2.0 before 1.11.13."
}
],
"impacts": [
{
"capecId": "CAPEC-475",
"descriptions": [
{
"lang": "en",
"value": "CAPEC-475 Signature Spoofing by Improper Validation"
}
]
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "PRESENT",
"attackVector": "LOCAL",
"baseScore": 5.9,
"baseSeverity": "MEDIUM",
"privilegesRequired": "NONE",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:N/VC:N/VI:H/VA:L/SC:N/SI:N/SA:N",
"version": "4.0",
"vulnAvailabilityImpact": "LOW",
"vulnConfidentialityImpact": "NONE",
"vulnIntegrityImpact": "HIGH",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-354",
"description": "CWE-354 Improper Validation of Integrity Check Value",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-26T19:52:54.987Z",
"orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"shortName": "EEF"
},
"references": [
{
"tags": [
"vendor-advisory",
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/security/advisories/GHSA-6gxw-6f7r-cjr6"
},
{
"name": "EEF CNA record for CVE-2026-65625",
"tags": [
"related"
],
"url": "https://cna.erlef.org/cves/CVE-2026-65625.html"
},
{
"name": "OSV record EEF-CVE-2026-65625",
"tags": [
"related"
],
"url": "https://osv.dev/vulnerability/EEF-CVE-2026-65625"
},
{
"name": "Introducing commit 8848b17 in potatosalad/erlang-jose",
"tags": [
"related"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/8848b172575fb7d7e1e2977e8ae0a21678d2157a"
},
{
"name": "Fix commit 3fa1f8e in potatosalad/erlang-jose",
"tags": [
"patch"
],
"url": "https://github.com/potatosalad/erlang-jose/commit/3fa1f8e3efda0da5ce6f4c9984789f979dc02740"
}
],
"source": {
"discovery": "EXTERNAL"
},
"title": "Attacker-controlled AES-GCM authentication tag length allows tag forgery in jose",
"workarounds": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eEnsure the runtime provides a crypto provider with native AES-GCM support (a standard Erlang/OTP build linked against OpenSSL) so that JOSE dispatches AES-GCM to the native \u003ccode\u003ecrypto\u003c/code\u003e NIF instead of the \u003ccode\u003ejose_jwa_aes\u003c/code\u003e fallback.\u003c/p\u003e"
},
{
"base64": false,
"type": "text/markdown",
"value": "Ensure the runtime provides a crypto provider with native AES-GCM support (a standard Erlang/OTP build linked against OpenSSL) so that JOSE dispatches AES-GCM to the native `crypto` NIF instead of the `jose_jwa_aes` fallback."
}
],
"value": "Ensure the runtime provides a crypto provider with native AES-GCM support (a standard Erlang/OTP build linked against OpenSSL) so that JOSE dispatches AES-GCM to the native crypto NIF instead of the jose_jwa_aes fallback."
}
]
}
},
"cveMetadata": {
"assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
"assignerShortName": "EEF",
"cveId": "CVE-2026-65625",
"datePublished": "2026-10-26T19:52:54.987Z",
"dateReserved": "2026-07-22T13:55:59.401Z",
"dateUpdated": "2026-10-26T19:52:54.987Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}