Safeguard
DevSecOps

node-jose Security: Using Cisco's JOSE Library Safely

node-jose is Cisco's JavaScript implementation of the JOSE standards for signing and encrypting tokens. Here is the CVE-2017-16007 invalid-curve flaw and how to use JWE and JWS defensively.

Priya Mehta
DevSecOps Engineer
6 min read

node-jose is Cisco's JavaScript implementation of the JOSE standards — JWS, JWE, JWK, and JWA — for signing and encrypting tokens, and using it safely means staying on a patched version (the invalid-curve attack CVE-2017-16007 was fixed in 0.9.3) and, more importantly, avoiding the algorithm-confusion mistakes that make JOSE cryptography so easy to get wrong. If you are minting or verifying JWTs, JWEs, or signed payloads in Node.js, node-jose gives you the full toolkit, but the same flexibility that makes it powerful is what makes misuse dangerous.

This guide covers the known CVE, the class of mistakes that bites JOSE users, and the defensive patterns that keep token handling sound.

What node-jose provides

node-jose implements the JOSE family of standards: JWS (JSON Web Signature) for signing, JWE (JSON Web Encryption) for encryption, JWK (JSON Web Key) for key representation, and JWA for the underlying algorithms. It handles key generation and import, keystore management, and the compact and JSON serializations. Compared to a minimal JWT library, it is a fuller cryptographic toolkit — which is exactly why it demands more care.

A basic sign-and-verify flow:

const jose = require('node-jose');

const keystore = jose.JWK.createKeyStore();
const key = await keystore.generate('EC', 'P-256');

const signed = await jose.JWS.createSign({ format: 'compact' }, key)
  .update(JSON.stringify({ sub: 'user-123' }))
  .final();

const result = await jose.JWS.createVerify(keystore).verify(signed);

CVE-2017-16007: the invalid-curve attack

The one documented CVE against node-jose worth knowing is CVE-2017-16007, an invalid-curve attack affecting versions earlier than 0.9.3. When JWE was used with ECDH-ES (Elliptic Curve Diffie-Hellman Ephemeral Static) key agreement, the library did not validate that the attacker-supplied public key in the JWE protected header actually lay on the expected curve. By submitting points from other curves or orders across repeated requests, an attacker could recover the recipient's private key.

What makes this instructive is its origin: the gap was partly in how the JWE specification (RFC 7516) described the process, so implementers who followed the spec faithfully inherited the flaw — node-jose was not alone. The fix added a validatePublic() check to confirm curve membership and wired it into every key-derivation path. The remedy is simply to run 0.9.3 or later, and any remotely current release is well past that.

The bigger risk: algorithm confusion

Patching the CVE is the easy part. The mistakes that actually compromise JOSE deployments are usage errors, and the most notorious is algorithm confusion.

JOSE tokens carry their algorithm in the header (alg). A naive verifier reads that header and uses whatever algorithm it names. Two classic attacks exploit this. In the alg: none attack, an attacker strips the signature and sets alg to none, and a verifier that honors it accepts an unsigned, forged token. In the RS256-to-HS256 confusion attack, an attacker takes a system that verifies with an RSA public key, switches the header to the symmetric HS256, and signs the token using the public key — which is not secret — as the HMAC secret; a verifier that trusts the header algorithm accepts it.

The defense is the same in both cases: never let the token dictate the algorithm. Decide out of band which algorithm and key you expect, and reject anything else. With node-jose, verify against a keystore that contains only the keys and algorithms you intend to accept, and treat an unexpected alg as a hard rejection rather than something to accommodate.

Defensive patterns for JOSE in general

Beyond algorithm pinning, a handful of habits keep token handling sound.

Always verify before you trust any claim. A signature check that you skip, or run after you have already used the payload, is no protection. Validate the standard claims too — expiry (exp), not-before (nbf), issuer, and audience — because a cryptographically valid token can still be expired or intended for a different service.

Separate signing keys from encryption keys, and rotate them. Reusing one key pair across JWS and JWE, or keeping a key in service indefinitely, widens the blast radius of any single compromise. Use a keystore with published key IDs so verifiers can select the right key without trusting attacker-controlled hints.

Prefer well-vetted, current algorithms. Stick to widely reviewed choices such as EdDSA or ES256 for signing and established AEAD schemes for encryption, and avoid exotic or deprecated options.

Is node-jose the right choice today?

node-jose is a capable, standards-complete library from Cisco, and its one historical CVE was handled responsibly. That said, its full-toolkit surface is more than many applications need. For plain JWT verification, a smaller, more opinionated library that refuses dangerous configurations by default can be a better fit precisely because it gives you fewer ways to shoot yourself in the foot. Choose node-jose when you genuinely need the breadth of JWE, JWK management, and multiple serializations; reach for something narrower when you only need to sign and verify JWTs. Whatever you pick, keep it current and let an SCA tool such as Safeguard flag it if the version you run ever picks up a new advisory. The Safeguard Academy has more on token security fundamentals.

FAQ

Is node-jose safe to use?

Yes, on a current version. The one documented CVE, CVE-2017-16007, was fixed in 0.9.3, and modern releases are well past it. The larger risk with any JOSE library is misuse — chiefly algorithm confusion — so safe usage depends more on how you verify tokens than on the library itself.

What was CVE-2017-16007 in node-jose?

It was an invalid-curve attack affecting versions before 0.9.3. When JWE used ECDH-ES key agreement, node-jose did not validate that the supplied public key lay on the expected curve, allowing an attacker to recover the private key over repeated requests. The fix added curve-membership validation.

What is the algorithm confusion attack?

It is a class of attack where a verifier trusts the algorithm named in the token header. Variants include the alg: none attack, which strips the signature, and RS256-to-HS256 confusion, which signs a token with the public RSA key used as an HMAC secret. The defense is to pin the expected algorithm and key rather than honoring the header.

Should I use node-jose or a smaller JWT library?

Use node-jose when you need its full breadth — JWE, JWK keystore management, and multiple serializations. For straightforward JWT signing and verification, a smaller, opinionated library that rejects unsafe configurations by default is often safer because it exposes fewer ways to misconfigure the cryptography.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.