Snyk has a proof-of-concept or detailed explanation of how to exploit this vulnerability.
The probability is the direct output of the EPSS model, and conveys an overall sense of the threat of exploitation in the wild. The percentile measures the EPSS probability relative to all known EPSS scores. Note: This data is updated daily, relying on the latest available EPSS model version. Check out the EPSS documentation for more details.
In a few clicks we can analyze your entire application and see what components are vulnerable in your application, and suggest you quick fixes.
Test your applicationsUpgrade jose to version 1.11.13 or higher.
Affected versions of this package are vulnerable to Use of Password Hash With Insufficient Computational Effort via the DER export path for password-encrypted private keys, which applies a PBKDF2 iteration count of only 2048 and an 8-byte (64-bit) salt when calling JOSE.JWK.to_der/2 with a secret password. An attacker who obtains the resulting EncryptedPrivateKeyInfo DER blob can recover the PBKDF2 parameters directly from the public structure of that blob, then mount an offline dictionary attack against the password using only the library's public decrypt path, recovering the private key at a work factor approximately 300 times below the OWASP-recommended 600,000 iterations with a 128-bit salt.
The attached script encodes an outside-attacker threat model in which the attacker holds nothing but the exported DER blob.
1. **Threat model.** A victim application calls the public entry point `JOSE.JWK.to_der(secret_password, jwk)` to export a password-encrypted RSA-2048 private key. The resulting `EncryptedPrivateKeyInfo` DER blob ends up somewhere readable — a backup, a config repository, object storage, or a log. The attacker obtains only that blob; they have no host access and make no internal function calls.
2. **Parameter recovery.** The script walks the DER structure by hand (a small tag/length/value parser) to pull the PBES2 → PBKDF2 parameters straight out of the public bytes, extracting the salt length and iteration count. It decodes them and prints, for example, an 8-byte (64-bit) salt and `iterationCount = 2048`, alongside the OWASP guidance of 600,000 iterations and ≥128-bit salt — demonstrating that the weak work factor is observable to anyone holding the blob.
3. **Offline crack.** The script then runs an offline dictionary attack using only the library's public decrypt path. Each candidate password is fed to `JOSE.JWK.from_der(candidate, der)`; a wrong password raises inside the cipher, and the correct one yields the private key. The real password is placed at the end of a 300-entry wordlist so the timing reflects many failed KDF evaluations — i.e. genuine cracking work. The crack is timed with `:timer.tc/1`, and the script reports elapsed time, cost per candidate, and the weakness factor (`600000 / iterations`, ≈300×).
4. **What proves the bug.** The script asserts `iterations < 600_000 and salt_bits < 128 and found == secret_password`. When all three hold it prints a `VERIFIED:` line stating the recovered parameters, the fact that the offline crack recovered the private key, and how far below the OWASP work factor the export sits. The full script is attached below under "Scripts and Logs" so the reader can run it themselves.
Note: The PoC section describes a script that demonstrates parameter recovery from a DER blob and an offline dictionary attack using the library's public decrypt path, but states no specific runtime, operating system, or non-default configuration.