Skip to content

Commit dd8a525

Browse files
semgrep-dev-pr-bot[bot]mohamed-osama-aboelkheirinkz
authored
New Published Rules - ironclad.jwt-simple-noverify-copy-copy (#3326)
* add ironclad/jwt-simple-noverify-copy-copy.yaml * add ironclad/jwt-simple-noverify-copy-copy.jsx * move ironclad rules to javascript folder * remove old ironclad files * update ironclad jwt-simple-noverify meta --------- Co-authored-by: Mohamed AboElKheir <[email protected]> Co-authored-by: Vasilii <[email protected]>
1 parent 8ed07c2 commit dd8a525

File tree

2 files changed

+188
-0
lines changed

2 files changed

+188
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
const express = require('express');
2+
const bcrypt = require('bcrypt');
3+
const jwt = require('jwt-simple');
4+
const mongoose = require('mongoose');
5+
const mongoSanitize = require('express-mongo-sanitize');
6+
7+
const app = express();
8+
app.use(express.json());
9+
app.use(mongoSanitize());
10+
const secretKey = process.env.JWT_SECRET;
11+
12+
// Sample MongoDB connection URI
13+
const mongoURI = 'mongodb://localhost:27017/test';
14+
15+
// Connect to MongoDB using Mongoose
16+
mongoose.connect(mongoURI, { useNewUrlParser: true, useUnifiedTopology: true });
17+
const db = mongoose.connection;
18+
19+
// Create a user schema
20+
const userSchema = new mongoose.Schema({
21+
username: String,
22+
password: String
23+
});
24+
25+
// Create a user model
26+
const User = mongoose.model('User', userSchema);
27+
28+
// Route for user login
29+
app.post('/login', async (req, res) => {
30+
const { username, password } = req.body;
31+
32+
try {
33+
// Find user by username
34+
const user = await User.findOne({ username });
35+
36+
if (!user) {
37+
return res.status(401).json({ error: 'Authentication failed. User not found.' });
38+
}
39+
40+
// Compare password with hashed password
41+
const isPasswordValid = await bcrypt.compare(password, user.password);
42+
43+
if (!isPasswordValid) {
44+
return res.status(401).json({ error: 'Authentication failed. Invalid password.' });
45+
}
46+
47+
// Issue JWT token
48+
const token = jwt.encode({ username }, secretKey,'HS256');
49+
res.json({ token });
50+
} catch (error) {
51+
console.error('Error occurred during login:', error);
52+
res.status(500).json({ error: 'Internal server error.' });
53+
}
54+
});
55+
56+
// Route that requires authentication
57+
app.get('/protectedRoute1', (req, res) => {
58+
const token = req.headers.authorization;
59+
60+
if (!token) {
61+
return res.status(401).json({ error: 'Unauthorized. Token missing.' });
62+
}
63+
64+
try {
65+
// ruleid: jwt-simple-noverify
66+
const decoded = jwt.decode(token, secretKey, 'HS256');
67+
res.json({ message: `Hello ${decoded.username}` });
68+
} catch (error) {
69+
res.status(401).json({ error: 'Unauthorized. Invalid token.' });
70+
}
71+
});
72+
73+
// Route that requires authentication
74+
app.get('/protectedRoute2', (req, res) => {
75+
const token = req.headers.authorization;
76+
77+
if (!token) {
78+
return res.status(401).json({ error: 'Unauthorized. Token missing.' });
79+
}
80+
81+
try {
82+
// ruleid: jwt-simple-noverify
83+
const decoded = jwt.decode(token, secretKey, true);
84+
res.json({ message: `Hello ${decoded.username}` });
85+
} catch (error) {
86+
res.status(401).json({ error: 'Unauthorized. Invalid token.' });
87+
}
88+
});
89+
90+
// Route that requires authentication
91+
app.get('/protectedRoute3', (req, res) => {
92+
const token = req.headers.authorization;
93+
94+
if (!token) {
95+
return res.status(401).json({ error: 'Unauthorized. Token missing.' });
96+
}
97+
98+
try {
99+
// ruleid: jwt-simple-noverify
100+
const decoded = jwt.decode(token, secretKey, 'false');
101+
res.json({ message: `Hello ${decoded.username}` });
102+
} catch (error) {
103+
res.status(401).json({ error: 'Unauthorized. Invalid token.' });
104+
}
105+
});
106+
107+
// Route that requires authentication
108+
app.get('/protectedRoute4', (req, res) => {
109+
const token = req.headers.authorization;
110+
111+
if (!token) {
112+
return res.status(401).json({ error: 'Unauthorized. Token missing.' });
113+
}
114+
115+
try {
116+
// ok: jwt-simple-noverify
117+
const decoded = jwt.decode(token, secretKey);
118+
res.json({ message: `Hello ${decoded.username}` });
119+
} catch (error) {
120+
res.status(401).json({ error: 'Unauthorized. Invalid token.' });
121+
}
122+
});
123+
124+
// Route that requires authentication
125+
app.get('/protectedRoute5', (req, res) => {
126+
const token = req.headers.authorization;
127+
128+
if (!token) {
129+
return res.status(401).json({ error: 'Unauthorized. Token missing.' });
130+
}
131+
132+
try {
133+
// ok: jwt-simple-noverify
134+
const decoded = jwt.decode(token, secretKey, false);
135+
res.json({ message: `Hello ${decoded.username}` });
136+
} catch (error) {
137+
res.status(401).json({ error: 'Unauthorized. Invalid token.' });
138+
}
139+
});
140+
141+
const PORT = process.env.PORT || 3000;
142+
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
rules:
2+
- id: jwt-simple-noverify
3+
message: >-
4+
Detected the decoding of a JWT token without a verify step.
5+
JWT tokens must be verified before use, otherwise the token's
6+
integrity is unknown. This means a malicious actor could forge
7+
a JWT token with any claims. Set 'verify' to `true` before using the token.
8+
severity: ERROR
9+
metadata:
10+
owasp:
11+
- A05:2021 - Security Misconfiguration
12+
- A07:2021 - Identification and Authentication Failures
13+
cwe:
14+
- 'CWE-287: Improper Authentication'
15+
- 'CWE-345: Insufficient Verification of Data Authenticity'
16+
- 'CWE-347: Improper Verification of Cryptographic Signature'
17+
category: security
18+
subcategory:
19+
- vuln
20+
technology:
21+
- jwt-simple
22+
- jwt
23+
confidence: HIGH
24+
likelihood: MEDIUM
25+
impact: HIGH
26+
references:
27+
- https://www.npmjs.com/package/jwt-simple
28+
- https://cwe.mitre.org/data/definitions/287
29+
- https://cwe.mitre.org/data/definitions/345
30+
- https://cwe.mitre.org/data/definitions/347
31+
languages:
32+
- javascript
33+
- typescript
34+
patterns:
35+
- pattern-inside: |
36+
$JWT = require('jwt-simple');
37+
...
38+
- pattern: $JWT.decode($TOKEN, $SECRET, $NOVERIFY, ...)
39+
- metavariable-pattern:
40+
metavariable: $NOVERIFY
41+
patterns:
42+
- pattern-either:
43+
- pattern: |
44+
true
45+
- pattern: |
46+
"..."

0 commit comments

Comments
 (0)