javascript.jwt-simple.security.jwt-simple-noverify.jwt-simple-noverify
semgrep
Author
unknown
Download Count*
License
Detected the decoding of a JWT token without a verify step. JWT tokens must be verified before use, otherwise the token's integrity is unknown. This means a malicious actor could forge a JWT token with any claims. Set 'verify' to true
before using the token.
Run Locally
Run in CI
Defintion
rules:
- id: jwt-simple-noverify
message: Detected the decoding of a JWT token without a verify step. JWT tokens
must be verified before use, otherwise the token's integrity is unknown.
This means a malicious actor could forge a JWT token with any claims. Set
'verify' to `true` before using the token.
severity: ERROR
metadata:
owasp:
- A05:2021 - Security Misconfiguration
- A07:2021 - Identification and Authentication Failures
cwe:
- "CWE-287: Improper Authentication"
- "CWE-345: Insufficient Verification of Data Authenticity"
- "CWE-347: Improper Verification of Cryptographic Signature"
category: security
subcategory:
- vuln
technology:
- jwt-simple
- jwt
confidence: HIGH
likelihood: MEDIUM
impact: HIGH
references:
- https://www.npmjs.com/package/jwt-simple
- https://cwe.mitre.org/data/definitions/287
- https://cwe.mitre.org/data/definitions/345
- https://cwe.mitre.org/data/definitions/347
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
vulnerability_class:
- Cryptographic Issues
- Improper Authentication
languages:
- javascript
- typescript
patterns:
- pattern-inside: |
$JWT = require('jwt-simple');
...
- pattern: $JWT.decode($TOKEN, $SECRET, $NOVERIFY, ...)
- metavariable-pattern:
metavariable: $NOVERIFY
patterns:
- pattern-either:
- pattern: |
true
- pattern: |
"..."
Examples
jwt-simple-noverify.js
const express = require('express');
const bcrypt = require('bcrypt');
const jwt = require('jwt-simple');
const mongoose = require('mongoose');
const mongoSanitize = require('express-mongo-sanitize');
const app = express();
app.use(express.json());
app.use(mongoSanitize());
const secretKey = process.env.JWT_SECRET;
// Sample MongoDB connection URI
const mongoURI = 'mongodb://localhost:27017/test';
// Connect to MongoDB using Mongoose
mongoose.connect(mongoURI, { useNewUrlParser: true, useUnifiedTopology: true });
const db = mongoose.connection;
// Create a user schema
const userSchema = new mongoose.Schema({
username: String,
password: String
});
// Create a user model
const User = mongoose.model('User', userSchema);
// Route for user login
app.post('/login', async (req, res) => {
const { username, password } = req.body;
try {
// Find user by username
const user = await User.findOne({ username });
if (!user) {
return res.status(401).json({ error: 'Authentication failed. User not found.' });
}
// Compare password with hashed password
const isPasswordValid = await bcrypt.compare(password, user.password);
if (!isPasswordValid) {
return res.status(401).json({ error: 'Authentication failed. Invalid password.' });
}
// Issue JWT token
const token = jwt.encode({ username }, secretKey,'HS256');
res.json({ token });
} catch (error) {
console.error('Error occurred during login:', error);
res.status(500).json({ error: 'Internal server error.' });
}
});
// Route that requires authentication
app.get('/protectedRoute1', (req, res) => {
const token = req.headers.authorization;
if (!token) {
return res.status(401).json({ error: 'Unauthorized. Token missing.' });
}
try {
// ruleid: jwt-simple-noverify
const decoded = jwt.decode(token, secretKey, 'HS256');
res.json({ message: `Hello ${decoded.username}` });
} catch (error) {
res.status(401).json({ error: 'Unauthorized. Invalid token.' });
}
});
// Route that requires authentication
app.get('/protectedRoute2', (req, res) => {
const token = req.headers.authorization;
if (!token) {
return res.status(401).json({ error: 'Unauthorized. Token missing.' });
}
try {
// ruleid: jwt-simple-noverify
const decoded = jwt.decode(token, secretKey, true);
res.json({ message: `Hello ${decoded.username}` });
} catch (error) {
res.status(401).json({ error: 'Unauthorized. Invalid token.' });
}
});
// Route that requires authentication
app.get('/protectedRoute3', (req, res) => {
const token = req.headers.authorization;
if (!token) {
return res.status(401).json({ error: 'Unauthorized. Token missing.' });
}
try {
// ruleid: jwt-simple-noverify
const decoded = jwt.decode(token, secretKey, 'false');
res.json({ message: `Hello ${decoded.username}` });
} catch (error) {
res.status(401).json({ error: 'Unauthorized. Invalid token.' });
}
});
// Route that requires authentication
app.get('/protectedRoute4', (req, res) => {
const token = req.headers.authorization;
if (!token) {
return res.status(401).json({ error: 'Unauthorized. Token missing.' });
}
try {
// ok: jwt-simple-noverify
const decoded = jwt.decode(token, secretKey);
res.json({ message: `Hello ${decoded.username}` });
} catch (error) {
res.status(401).json({ error: 'Unauthorized. Invalid token.' });
}
});
// Route that requires authentication
app.get('/protectedRoute5', (req, res) => {
const token = req.headers.authorization;
if (!token) {
return res.status(401).json({ error: 'Unauthorized. Token missing.' });
}
try {
// ok: jwt-simple-noverify
const decoded = jwt.decode(token, secretKey, false);
res.json({ message: `Hello ${decoded.username}` });
} catch (error) {
res.status(401).json({ error: 'Unauthorized. Invalid token.' });
}
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
Short Link: https://sg.run/zdjod