jwt-security-scanner 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,186 @@
1
+ Metadata-Version: 2.4
2
+ Name: jwt-security-scanner
3
+ Version: 1.0.0
4
+ Summary: A tool to scan JWT tokens for security vulnerabilities
5
+ Home-page: https://github.com/tabassumfathima28/JWT-Security-Scanner
6
+ Author: Tabassum Fathima
7
+ Author-email: tabassumfathima2812@gmail.com
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Topic :: Security
12
+ Requires-Python: >=3.7
13
+ Description-Content-Type: text/markdown
14
+ Requires-Dist: pyjwt>=2.0.0
15
+ Requires-Dist: requests>=2.0.0
16
+ Requires-Dist: colorama>=0.4.0
17
+ Requires-Dist: rich>=10.0.0
18
+ Dynamic: author
19
+ Dynamic: author-email
20
+ Dynamic: classifier
21
+ Dynamic: description
22
+ Dynamic: description-content-type
23
+ Dynamic: home-page
24
+ Dynamic: requires-dist
25
+ Dynamic: requires-python
26
+ Dynamic: summary
27
+
28
+ # JWT Security Scanner 🔐
29
+
30
+ > A Python-based command-line tool that automatically scans JWT tokens for security vulnerabilities and generates professional security reports.
31
+
32
+ ---
33
+
34
+ ## What is This Tool?
35
+
36
+ JWT (JSON Web Token) is used by millions of websites to handle user authentication. But poorly configured JWT tokens can be exploited by hackers to bypass login, steal accounts, or gain admin access.
37
+
38
+ This tool acts like a **security doctor for JWT tokens** — you give it a token, it runs 5 security checks and tells you exactly what's wrong and how to fix it.
39
+
40
+ ---
41
+
42
+ ## Features
43
+
44
+ - Detects 5 critical JWT vulnerability categories
45
+ - Beautiful colored terminal output
46
+ - Generates professional HTML security report
47
+ - Generates text report for documentation
48
+ - Includes security recommendations
49
+ - Works on any JWT token
50
+
51
+ ---
52
+
53
+ ## Vulnerabilities Detected
54
+
55
+ | Check | What it detects | Risk Level |
56
+ |-------|----------------|------------|
57
+ | Algorithm Check | Dangerous 'none' algorithm usage | CRITICAL |
58
+ | Weak Secret Key | Guesses secret key from common passwords | CRITICAL |
59
+ | Token Expiry | Missing or expired expiry time | HIGH |
60
+ | Sensitive Data | Passwords or private data in payload | HIGH |
61
+ | Token Claims | Missing issuer, subject, audience | MEDIUM |
62
+
63
+ ---
64
+
65
+ ## Tools and Technologies
66
+
67
+ - **Python 3** — Core programming language
68
+ - **PyJWT** — JWT token decoding and validation
69
+ - **Rich** — Beautiful terminal formatting
70
+ - **Colorama** — Terminal color support
71
+
72
+ ---
73
+
74
+ ## Installation
75
+
76
+ ### Step 1 — Clone the repository
77
+ ```bash
78
+ git clone https://github.com/YOURUSERNAME/JWT-Security-Scanner.git
79
+ cd JWT-Security-Scanner
80
+ ```
81
+
82
+ ### Step 2 — Install dependencies
83
+ ```bash
84
+ pip install -r requirements.txt
85
+ ```
86
+
87
+ ---
88
+
89
+ ## Usage
90
+
91
+ ### Run the scanner
92
+ ```bash
93
+ python jwt_scanner.py
94
+ ```
95
+
96
+ ### Or pass token directly
97
+ ```bash
98
+ python jwt_scanner.py YOUR_JWT_TOKEN_HERE
99
+ ```
100
+
101
+ ### Generate a test vulnerable token
102
+ ```bash
103
+ python -c "import jwt; print(jwt.encode({'user': 'admin', 'password': 'secret123'}, 'secret', algorithm='HS256'))"
104
+ ```
105
+
106
+ ---
107
+
108
+ ## Example Output
109
+
110
+ ```
111
+ JWT Security Scanner
112
+ Finds vulnerabilities in JWT tokens
113
+
114
+ SECURITY FINDINGS
115
+ CRITICAL WEAK SECRET KEY FOUND: 'secret'
116
+ HIGH No expiry time found!
117
+ HIGH Sensitive fields found: password
118
+
119
+ SECURITY SUMMARY
120
+ CRITICAL 1
121
+ HIGH 2
122
+ MEDIUM 0
123
+ LOW 5
124
+
125
+ CRITICAL VULNERABILITIES FOUND! This token is DANGEROUS!
126
+ ```
127
+
128
+ ---
129
+
130
+ ## Reports Generated
131
+
132
+ After every scan the tool automatically generates:
133
+
134
+ ### 1. Text Report
135
+ Plain text file with all findings — perfect for documentation
136
+
137
+ ### 2. HTML Report
138
+ Professional security report with color coded risk levels, summary dashboard, findings table, recommendations and cybersecurity quotes
139
+
140
+ ---
141
+
142
+ ## What I Learned Building This
143
+
144
+ - JWT token structure — Header, Payload, Signature
145
+ - Common JWT vulnerabilities and how attackers exploit them
146
+ - Python security tool development
147
+ - Automated vulnerability scanning techniques
148
+ - Professional security report generation
149
+ - The difference between encoding and encryption
150
+
151
+ ---
152
+
153
+ ## Real World Application
154
+
155
+ This tool simulates what penetration testers and security engineers do when auditing web applications. JWT vulnerabilities are listed in the **OWASP Top 10** and are responsible for thousands of security breaches every year.
156
+
157
+ ---
158
+
159
+ ## Project Structure
160
+
161
+ ```
162
+ JWT-Security-Scanner/
163
+
164
+ ├── jwt_scanner.py Main scanner with all checks
165
+ ├── requirements.txt Python dependencies
166
+ └── README.md Project documentation
167
+ ```
168
+
169
+ ---
170
+
171
+ ## Also Check Out
172
+
173
+ My other cybersecurity project:
174
+ - [AI-Powered SIEM Home Lab](https://github.com/tabassumfathima28/SIEM-HOME-LAB-PROJECT) — Detects real cyber attacks using Elastic SIEM and Tines automation
175
+
176
+ ---
177
+
178
+ ## Connect With Me
179
+
180
+ Built by an aspiring SOC Analyst learning cybersecurity through hands-on projects.
181
+
182
+ Connect on [LinkedIn](#)
183
+
184
+ ---
185
+
186
+ > "Security is not a product, but a process." — Bruce Schneier
@@ -0,0 +1,159 @@
1
+ # JWT Security Scanner 🔐
2
+
3
+ > A Python-based command-line tool that automatically scans JWT tokens for security vulnerabilities and generates professional security reports.
4
+
5
+ ---
6
+
7
+ ## What is This Tool?
8
+
9
+ JWT (JSON Web Token) is used by millions of websites to handle user authentication. But poorly configured JWT tokens can be exploited by hackers to bypass login, steal accounts, or gain admin access.
10
+
11
+ This tool acts like a **security doctor for JWT tokens** — you give it a token, it runs 5 security checks and tells you exactly what's wrong and how to fix it.
12
+
13
+ ---
14
+
15
+ ## Features
16
+
17
+ - Detects 5 critical JWT vulnerability categories
18
+ - Beautiful colored terminal output
19
+ - Generates professional HTML security report
20
+ - Generates text report for documentation
21
+ - Includes security recommendations
22
+ - Works on any JWT token
23
+
24
+ ---
25
+
26
+ ## Vulnerabilities Detected
27
+
28
+ | Check | What it detects | Risk Level |
29
+ |-------|----------------|------------|
30
+ | Algorithm Check | Dangerous 'none' algorithm usage | CRITICAL |
31
+ | Weak Secret Key | Guesses secret key from common passwords | CRITICAL |
32
+ | Token Expiry | Missing or expired expiry time | HIGH |
33
+ | Sensitive Data | Passwords or private data in payload | HIGH |
34
+ | Token Claims | Missing issuer, subject, audience | MEDIUM |
35
+
36
+ ---
37
+
38
+ ## Tools and Technologies
39
+
40
+ - **Python 3** — Core programming language
41
+ - **PyJWT** — JWT token decoding and validation
42
+ - **Rich** — Beautiful terminal formatting
43
+ - **Colorama** — Terminal color support
44
+
45
+ ---
46
+
47
+ ## Installation
48
+
49
+ ### Step 1 — Clone the repository
50
+ ```bash
51
+ git clone https://github.com/YOURUSERNAME/JWT-Security-Scanner.git
52
+ cd JWT-Security-Scanner
53
+ ```
54
+
55
+ ### Step 2 — Install dependencies
56
+ ```bash
57
+ pip install -r requirements.txt
58
+ ```
59
+
60
+ ---
61
+
62
+ ## Usage
63
+
64
+ ### Run the scanner
65
+ ```bash
66
+ python jwt_scanner.py
67
+ ```
68
+
69
+ ### Or pass token directly
70
+ ```bash
71
+ python jwt_scanner.py YOUR_JWT_TOKEN_HERE
72
+ ```
73
+
74
+ ### Generate a test vulnerable token
75
+ ```bash
76
+ python -c "import jwt; print(jwt.encode({'user': 'admin', 'password': 'secret123'}, 'secret', algorithm='HS256'))"
77
+ ```
78
+
79
+ ---
80
+
81
+ ## Example Output
82
+
83
+ ```
84
+ JWT Security Scanner
85
+ Finds vulnerabilities in JWT tokens
86
+
87
+ SECURITY FINDINGS
88
+ CRITICAL WEAK SECRET KEY FOUND: 'secret'
89
+ HIGH No expiry time found!
90
+ HIGH Sensitive fields found: password
91
+
92
+ SECURITY SUMMARY
93
+ CRITICAL 1
94
+ HIGH 2
95
+ MEDIUM 0
96
+ LOW 5
97
+
98
+ CRITICAL VULNERABILITIES FOUND! This token is DANGEROUS!
99
+ ```
100
+
101
+ ---
102
+
103
+ ## Reports Generated
104
+
105
+ After every scan the tool automatically generates:
106
+
107
+ ### 1. Text Report
108
+ Plain text file with all findings — perfect for documentation
109
+
110
+ ### 2. HTML Report
111
+ Professional security report with color coded risk levels, summary dashboard, findings table, recommendations and cybersecurity quotes
112
+
113
+ ---
114
+
115
+ ## What I Learned Building This
116
+
117
+ - JWT token structure — Header, Payload, Signature
118
+ - Common JWT vulnerabilities and how attackers exploit them
119
+ - Python security tool development
120
+ - Automated vulnerability scanning techniques
121
+ - Professional security report generation
122
+ - The difference between encoding and encryption
123
+
124
+ ---
125
+
126
+ ## Real World Application
127
+
128
+ This tool simulates what penetration testers and security engineers do when auditing web applications. JWT vulnerabilities are listed in the **OWASP Top 10** and are responsible for thousands of security breaches every year.
129
+
130
+ ---
131
+
132
+ ## Project Structure
133
+
134
+ ```
135
+ JWT-Security-Scanner/
136
+
137
+ ├── jwt_scanner.py Main scanner with all checks
138
+ ├── requirements.txt Python dependencies
139
+ └── README.md Project documentation
140
+ ```
141
+
142
+ ---
143
+
144
+ ## Also Check Out
145
+
146
+ My other cybersecurity project:
147
+ - [AI-Powered SIEM Home Lab](https://github.com/tabassumfathima28/SIEM-HOME-LAB-PROJECT) — Detects real cyber attacks using Elastic SIEM and Tines automation
148
+
149
+ ---
150
+
151
+ ## Connect With Me
152
+
153
+ Built by an aspiring SOC Analyst learning cybersecurity through hands-on projects.
154
+
155
+ Connect on [LinkedIn](#)
156
+
157
+ ---
158
+
159
+ > "Security is not a product, but a process." — Bruce Schneier
@@ -0,0 +1,5 @@
1
+ from .scanner import main
2
+
3
+ __version__ = "1.0.0"
4
+ __author__ = "Tabassum Fathima"
5
+ __description__ = "JWT Security Scanner - Find vulnerabilities in JWT tokens"
@@ -0,0 +1,720 @@
1
+ import jwt
2
+ import json
3
+ import base64
4
+ import sys
5
+ from html import escape
6
+ from datetime import datetime
7
+ from colorama import init, Fore, Style
8
+ from rich.console import Console
9
+ from rich.table import Table
10
+ from rich.panel import Panel
11
+ from rich import print as rprint
12
+
13
+ # Initialize colorama
14
+ init()
15
+ console = Console()
16
+ # Common weak secret keys hackers try
17
+ WEAK_KEYS = [
18
+ "secret", "password", "123456", "key", "private",
19
+ "mysecret", "jwt_secret", "supersecret", "admin",
20
+ "test", "hello", "qwerty", "abc123", "password123",
21
+ "secretkey", "mykey", "token", "jwt", "auth"
22
+ ]
23
+
24
+ # Sensitive fields that should never be in JWT
25
+ SENSITIVE_FIELDS = [
26
+ "password", "passwd", "pwd", "credit_card", "ccv",
27
+ "ssn", "social_security", "bank_account", "private_key",
28
+ "secret", "api_key", "access_key", "pin"
29
+ ]
30
+
31
+
32
+ def print_banner():
33
+ """Print tool banner"""
34
+ console.print(Panel.fit(
35
+ "[bold cyan]JWT Security Scanner[/bold cyan]\n"
36
+ "[white]Finds vulnerabilities in JWT tokens[/white]\n"
37
+ "[dim]Built for cybersecurity portfolio[/dim]",
38
+ border_style="cyan"
39
+ ))
40
+
41
+
42
+ def decode_token_parts(token):
43
+ """Decode JWT token without verification"""
44
+ try:
45
+ parts = token.split('.')
46
+ if len(parts) != 3:
47
+ return None, None, "Invalid JWT format - must have 3 parts"
48
+
49
+ # Decode header
50
+ header_padded = parts[0] + '=' * (4 - len(parts[0]) % 4)
51
+ header = json.loads(base64.urlsafe_b64decode(header_padded))
52
+
53
+ # Decode payload
54
+ payload_padded = parts[1] + '=' * (4 - len(parts[1]) % 4)
55
+ payload = json.loads(base64.urlsafe_b64decode(payload_padded))
56
+
57
+ return header, payload, None
58
+ except Exception as e:
59
+ return None, None, str(e)
60
+
61
+
62
+ def check_algorithm(header):
63
+ """Check 1 - Algorithm Security"""
64
+ results = []
65
+ algorithm = header.get('alg', 'unknown').upper()
66
+
67
+ if algorithm == 'NONE':
68
+ results.append({
69
+ "status": "CRITICAL",
70
+ "finding": "Algorithm is set to 'none'!",
71
+ "detail": "Token has NO signature! Anyone can forge this token!",
72
+ "risk": "CRITICAL"
73
+ })
74
+ elif algorithm in ['HS256', 'HS384', 'HS512']:
75
+ results.append({
76
+ "status": "INFO",
77
+ "finding": f"Algorithm: {algorithm}",
78
+ "detail": "Symmetric algorithm — safe if secret key is strong",
79
+ "risk": "LOW"
80
+ })
81
+ elif algorithm in ['RS256', 'RS384', 'RS512']:
82
+ results.append({
83
+ "status": "PASS",
84
+ "finding": f"Algorithm: {algorithm}",
85
+ "detail": "Asymmetric algorithm — good choice!",
86
+ "risk": "LOW"
87
+ })
88
+ else:
89
+ results.append({
90
+ "status": "WARNING",
91
+ "finding": f"Unknown algorithm: {algorithm}",
92
+ "detail": "Unrecognized algorithm detected",
93
+ "risk": "MEDIUM"
94
+ })
95
+
96
+ return results
97
+
98
+
99
+ def check_expiry(payload):
100
+ """Check 2 - Token Expiry"""
101
+ results = []
102
+
103
+ if 'exp' not in payload:
104
+ results.append({
105
+ "status": "HIGH",
106
+ "finding": "No expiry time found!",
107
+ "detail": "Token never expires! Stolen token works forever!",
108
+ "risk": "HIGH"
109
+ })
110
+ else:
111
+ exp_time = datetime.fromtimestamp(payload['exp'])
112
+ now = datetime.now()
113
+
114
+ if now > exp_time:
115
+ results.append({
116
+ "status": "WARNING",
117
+ "finding": "Token is EXPIRED",
118
+ "detail": f"Expired at: {exp_time}",
119
+ "risk": "MEDIUM"
120
+ })
121
+ else:
122
+ diff = exp_time - now
123
+ results.append({
124
+ "status": "PASS",
125
+ "finding": "Token has valid expiry",
126
+ "detail": f"Expires at: {exp_time} ({diff.days} days remaining)",
127
+ "risk": "LOW"
128
+ })
129
+
130
+ if 'iat' not in payload:
131
+ results.append({
132
+ "status": "WARNING",
133
+ "finding": "No 'issued at' time found",
134
+ "detail": "Cannot verify when token was created",
135
+ "risk": "LOW"
136
+ })
137
+
138
+ return results
139
+
140
+
141
+ def check_weak_secret(token, header):
142
+ """Check 3 - Weak Secret Key"""
143
+ results = []
144
+ algorithm = header.get('alg', '').upper()
145
+
146
+ if algorithm.startswith('HS'):
147
+ cracked_key = None
148
+ for key in WEAK_KEYS:
149
+ try:
150
+ jwt.decode(token, key, algorithms=[algorithm])
151
+ cracked_key = key
152
+ break
153
+ except jwt.InvalidSignatureError:
154
+ continue
155
+ except Exception:
156
+ continue
157
+
158
+ if cracked_key:
159
+ results.append({
160
+ "status": "CRITICAL",
161
+ "finding": f"WEAK SECRET KEY FOUND: '{cracked_key}'",
162
+ "detail": "Secret key was guessed from common passwords list!",
163
+ "risk": "CRITICAL"
164
+ })
165
+ else:
166
+ results.append({
167
+ "status": "PASS",
168
+ "finding": "Secret key not found in common keys list",
169
+ "detail": "Key appears strong enough to resist basic attacks",
170
+ "risk": "LOW"
171
+ })
172
+ else:
173
+ results.append({
174
+ "status": "INFO",
175
+ "finding": "Asymmetric algorithm — secret key check skipped",
176
+ "detail": "RS/ES algorithms use public/private key pairs",
177
+ "risk": "LOW"
178
+ })
179
+
180
+ return results
181
+
182
+
183
+ def check_sensitive_data(payload):
184
+ """Check 4 - Sensitive Data in Payload"""
185
+ results = []
186
+ found_sensitive = []
187
+
188
+ for field in payload:
189
+ if field.lower() in SENSITIVE_FIELDS:
190
+ found_sensitive.append(field)
191
+
192
+ if found_sensitive:
193
+ results.append({
194
+ "status": "HIGH",
195
+ "finding": f"Sensitive fields found: {', '.join(found_sensitive)}",
196
+ "detail": "JWT payload is base64 encoded NOT encrypted! Anyone can read it!",
197
+ "risk": "HIGH"
198
+ })
199
+ else:
200
+ results.append({
201
+ "status": "PASS",
202
+ "finding": "No sensitive data found in payload",
203
+ "detail": "Payload looks clean",
204
+ "risk": "LOW"
205
+ })
206
+
207
+ return results
208
+
209
+
210
+ def check_claims(payload):
211
+ """Check 5 - Important Claims"""
212
+ results = []
213
+
214
+ if 'iss' not in payload:
215
+ results.append({
216
+ "status": "WARNING",
217
+ "finding": "No 'issuer' claim found",
218
+ "detail": "Cannot verify who created this token",
219
+ "risk": "LOW"
220
+ })
221
+
222
+ if 'sub' not in payload:
223
+ results.append({
224
+ "status": "WARNING",
225
+ "finding": "No 'subject' claim found",
226
+ "detail": "Token does not identify who it belongs to",
227
+ "risk": "LOW"
228
+ })
229
+
230
+ if 'aud' not in payload:
231
+ results.append({
232
+ "status": "INFO",
233
+ "finding": "No 'audience' claim found",
234
+ "detail": "Token can be used on any service",
235
+ "risk": "LOW"
236
+ })
237
+
238
+ return results
239
+
240
+
241
+ def print_results(all_results, header, payload):
242
+ """Print beautiful security report"""
243
+
244
+ # Count findings by risk
245
+ critical = sum(1 for r in all_results if r['risk'] == 'CRITICAL')
246
+ high = sum(1 for r in all_results if r['risk'] == 'HIGH')
247
+ medium = sum(1 for r in all_results if r['risk'] == 'MEDIUM')
248
+ low = sum(1 for r in all_results if r['risk'] == 'LOW')
249
+
250
+ # Print token info
251
+ console.print("\n[bold cyan]═══ TOKEN INFORMATION ═══[/bold cyan]")
252
+ info_table = Table(show_header=True, header_style="bold cyan")
253
+ info_table.add_column("Field", style="cyan")
254
+ info_table.add_column("Value", style="white")
255
+
256
+ info_table.add_row("Algorithm", header.get('alg', 'unknown'))
257
+ info_table.add_row("Token Type", header.get('typ', 'unknown'))
258
+
259
+ for key, value in payload.items():
260
+ if key == 'exp' or key == 'iat':
261
+ value = str(datetime.fromtimestamp(value))
262
+ info_table.add_row(key, str(value))
263
+
264
+ console.print(info_table)
265
+
266
+ # Print findings
267
+ console.print("\n[bold cyan]═══ SECURITY FINDINGS ═══[/bold cyan]")
268
+
269
+ findings_table = Table(show_header=True, header_style="bold cyan")
270
+ findings_table.add_column("Risk", style="bold", width=10)
271
+ findings_table.add_column("Finding", width=35)
272
+ findings_table.add_column("Detail", width=45)
273
+
274
+ for result in all_results:
275
+ risk = result['risk']
276
+ if risk == 'CRITICAL':
277
+ risk_style = "[bold red]CRITICAL[/bold red]"
278
+ elif risk == 'HIGH':
279
+ risk_style = "[red]HIGH[/red]"
280
+ elif risk == 'MEDIUM':
281
+ risk_style = "[yellow]MEDIUM[/yellow]"
282
+ else:
283
+ risk_style = "[green]LOW[/green]"
284
+
285
+ findings_table.add_row(
286
+ risk_style,
287
+ result['finding'],
288
+ result['detail']
289
+ )
290
+
291
+ console.print(findings_table)
292
+
293
+ # Print summary
294
+ console.print("\n[bold cyan]═══ SECURITY SUMMARY ═══[/bold cyan]")
295
+ summary_table = Table(show_header=False)
296
+ summary_table.add_column("Level", style="bold")
297
+ summary_table.add_column("Count")
298
+
299
+ summary_table.add_row("[bold red]CRITICAL[/bold red]", str(critical))
300
+ summary_table.add_row("[red]HIGH[/red]", str(high))
301
+ summary_table.add_row("[yellow]MEDIUM[/yellow]", str(medium))
302
+ summary_table.add_row("[green]LOW/INFO[/green]", str(low))
303
+
304
+ console.print(summary_table)
305
+
306
+ # Overall verdict
307
+ if critical > 0:
308
+ console.print(Panel("[bold red]⚠ CRITICAL VULNERABILITIES FOUND! This token is DANGEROUS![/bold red]", border_style="red"))
309
+ elif high > 0:
310
+ console.print(Panel("[red]⚠ HIGH RISK VULNERABILITIES FOUND! Immediate action needed![/red]", border_style="red"))
311
+ elif medium > 0:
312
+ console.print(Panel("[yellow]⚠ MEDIUM RISK FINDINGS. Review and fix recommended.[/yellow]", border_style="yellow"))
313
+ else:
314
+ console.print(Panel("[green]✓ No critical issues found. Token appears reasonably secure.[/green]", border_style="green"))
315
+
316
+
317
+ def scan_token(token):
318
+ """Main scanning function"""
319
+ console.print("\n[cyan]Scanning JWT token...[/cyan]\n")
320
+
321
+ # Decode token parts
322
+ header, payload, error = decode_token_parts(token)
323
+
324
+ if error:
325
+ console.print(f"[red]Error decoding token: {error}[/red]")
326
+ return
327
+
328
+ # Run all checks
329
+ all_results = []
330
+
331
+ console.print("[cyan]Running Check 1: Algorithm Security...[/cyan]")
332
+ all_results.extend(check_algorithm(header))
333
+
334
+ console.print("[cyan]Running Check 2: Token Expiry...[/cyan]")
335
+ all_results.extend(check_expiry(payload))
336
+
337
+ console.print("[cyan]Running Check 3: Weak Secret Key...[/cyan]")
338
+ all_results.extend(check_weak_secret(token, header))
339
+
340
+ console.print("[cyan]Running Check 4: Sensitive Data...[/cyan]")
341
+ all_results.extend(check_sensitive_data(payload))
342
+
343
+ console.print("[cyan]Running Check 5: Token Claims...[/cyan]")
344
+ all_results.extend(check_claims(payload))
345
+
346
+ # Print results
347
+ print_results(all_results, header, payload)
348
+ filename = save_report(token, all_results, header, payload)
349
+ console.print(f"\n[green]Text report saved to: {filename}[/green]")
350
+
351
+ html_filename = save_html_report(token, all_results, header, payload)
352
+ console.print(f"[green]HTML report saved to: {html_filename}[/green]")
353
+ console.print(f"\n[cyan]Open the HTML file in your browser to see the full report![/cyan]")
354
+
355
+
356
+ def main():
357
+ print_banner()
358
+
359
+ if len(sys.argv) > 1:
360
+ token = sys.argv[1]
361
+ else:
362
+ console.print("\n[cyan]Enter JWT token to scan:[/cyan]")
363
+ token = input("> ").strip()
364
+
365
+ if not token:
366
+ console.print("[red]No token provided![/red]")
367
+ return
368
+
369
+ scan_token(token)
370
+
371
+
372
+ def save_report(token, all_results, header, payload):
373
+ """Save scan results to a text report"""
374
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
375
+ filename = f"jwt_report_{timestamp}.txt"
376
+
377
+ with open(filename, 'w', encoding='utf-8') as f:
378
+ f.write("=" * 60 + "\n")
379
+ f.write("JWT SECURITY SCAN REPORT\n")
380
+ f.write(f"Generated: {datetime.now()}\n")
381
+ f.write("=" * 60 + "\n\n")
382
+
383
+ f.write("TOKEN INFORMATION\n")
384
+ f.write("-" * 40 + "\n")
385
+ f.write(f"Algorithm: {header.get('alg', 'unknown')}\n")
386
+ f.write(f"Token Type: {header.get('typ', 'unknown')}\n")
387
+ for key, value in payload.items():
388
+ if key in ['exp', 'iat']:
389
+ value = str(datetime.fromtimestamp(value))
390
+ f.write(f"{key}: {value}\n")
391
+
392
+ f.write("\nSECURITY FINDINGS\n")
393
+ f.write("-" * 40 + "\n")
394
+ for result in all_results:
395
+ f.write(f"[{result['risk']}] {result['finding']}\n")
396
+ f.write(f" Detail: {result['detail']}\n\n")
397
+
398
+ critical = sum(1 for r in all_results if r['risk'] == 'CRITICAL')
399
+ high = sum(1 for r in all_results if r['risk'] == 'HIGH')
400
+ medium = sum(1 for r in all_results if r['risk'] == 'MEDIUM')
401
+
402
+ f.write("\nSECURITY SUMMARY\n")
403
+ f.write("-" * 40 + "\n")
404
+ f.write(f"CRITICAL: {critical}\n")
405
+ f.write(f"HIGH: {high}\n")
406
+ f.write(f"MEDIUM: {medium}\n")
407
+
408
+ if critical > 0:
409
+ f.write("\nVERDICT: CRITICAL VULNERABILITIES FOUND!\n")
410
+ elif high > 0:
411
+ f.write("\nVERDICT: HIGH RISK VULNERABILITIES FOUND!\n")
412
+ else:
413
+ f.write("\nVERDICT: No critical issues found.\n")
414
+
415
+ return filename
416
+
417
+
418
+ def save_html_report(token, all_results, header, payload):
419
+ """Save scan results to an HTML report"""
420
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
421
+ filename = f"jwt_report_{timestamp}.html"
422
+
423
+ critical = sum(1 for r in all_results if r['risk'] == 'CRITICAL')
424
+ high = sum(1 for r in all_results if r['risk'] == 'HIGH')
425
+ medium = sum(1 for r in all_results if r['risk'] == 'MEDIUM')
426
+ low = sum(1 for r in all_results if r['risk'] == 'LOW')
427
+ total = len(all_results)
428
+
429
+ payload_html = []
430
+ for key, value in payload.items():
431
+ if key in ['exp', 'iat']:
432
+ value = str(datetime.fromtimestamp(value))
433
+ payload_html.append(
434
+ f"<tr><td style='color: #e91e63; font-weight: 700;'>{escape(str(key))}:</td><td>{escape(str(value))}</td></tr>"
435
+ )
436
+
437
+ findings_html = []
438
+ for idx, result in enumerate(all_results, 1):
439
+ risk = result['risk']
440
+ if risk == 'CRITICAL':
441
+ dot_color = '#dc2626'
442
+ elif risk == 'HIGH':
443
+ dot_color = '#ea580c'
444
+ elif risk == 'MEDIUM':
445
+ dot_color = '#b45309'
446
+ else:
447
+ dot_color = '#4b5563'
448
+
449
+ findings_html.append(
450
+ f"<tr>"
451
+ f"<td>{idx}</td>"
452
+ f"<td><span style='color: {dot_color}; font-weight: 700;'>● {escape(risk)}</span></td>"
453
+ f"<td>{escape(result.get('finding', ''))}</td>"
454
+ f"<td>{escape(result.get('detail', ''))}</td>"
455
+ f"</tr>"
456
+ )
457
+
458
+ html = f"""<!DOCTYPE html>
459
+ <html lang="en">
460
+ <head>
461
+ <meta charset="UTF-8" />
462
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
463
+ <title>JWT Security Assessment Report</title>
464
+ <style>
465
+ * {{ margin: 0; padding: 0; box-sizing: border-box; }}
466
+
467
+ body {{
468
+ font-family: Arial, sans-serif;
469
+ background: #fef5f9;
470
+ color: #333;
471
+ line-height: 1.6;
472
+ padding: 40px 20px;
473
+ }}
474
+
475
+ .container {{
476
+ max-width: 900px;
477
+ margin: 0 auto;
478
+ background: white;
479
+ padding: 40px;
480
+ }}
481
+
482
+ .header {{
483
+ text-align: center;
484
+ margin-bottom: 40px;
485
+ border-bottom: 2px solid #ffc0e3;
486
+ padding-bottom: 30px;
487
+ }}
488
+
489
+ h1 {{
490
+ color: #e91e63;
491
+ font-size: 32px;
492
+ margin-bottom: 8px;
493
+ font-weight: 700;
494
+ letter-spacing: 1px;
495
+ }}
496
+
497
+ .subtitle {{
498
+ color: #666;
499
+ font-size: 13px;
500
+ margin-bottom: 4px;
501
+ }}
502
+
503
+ .date {{
504
+ color: #999;
505
+ font-size: 12px;
506
+ margin-bottom: 20px;
507
+ }}
508
+
509
+ .heart {{
510
+ color: #e91e63;
511
+ font-size: 20px;
512
+ margin: 15px 0;
513
+ }}
514
+
515
+ .quote {{
516
+ font-style: italic;
517
+ color: #e91e63;
518
+ text-align: center;
519
+ margin: 20px 0;
520
+ font-size: 15px;
521
+ line-height: 1.8;
522
+ }}
523
+
524
+ .section-title {{
525
+ color: #e91e63;
526
+ font-size: 16px;
527
+ font-weight: 700;
528
+ text-transform: uppercase;
529
+ letter-spacing: 2px;
530
+ margin-top: 35px;
531
+ margin-bottom: 15px;
532
+ border-bottom: 1px solid #ffc0e3;
533
+ padding-bottom: 10px;
534
+ }}
535
+
536
+ .overview {{
537
+ background: #fef5f9;
538
+ padding: 20px;
539
+ border-radius: 8px;
540
+ margin-bottom: 20px;
541
+ line-height: 1.8;
542
+ font-size: 14px;
543
+ }}
544
+
545
+ .stats {{
546
+ display: grid;
547
+ grid-template-columns: repeat(5, 1fr);
548
+ gap: 15px;
549
+ margin-bottom: 30px;
550
+ }}
551
+
552
+ .stat {{
553
+ text-align: center;
554
+ padding: 15px;
555
+ background: #f9f9f9;
556
+ border-radius: 8px;
557
+ border-left: 3px solid #ffc0e3;
558
+ }}
559
+
560
+ .stat-label {{
561
+ color: #666;
562
+ font-size: 12px;
563
+ margin-bottom: 8px;
564
+ font-weight: 600;
565
+ }}
566
+
567
+ .stat-value {{
568
+ font-size: 28px;
569
+ font-weight: 700;
570
+ color: #e91e63;
571
+ }}
572
+
573
+ table {{
574
+ width: 100%;
575
+ border-collapse: collapse;
576
+ margin-bottom: 30px;
577
+ font-size: 14px;
578
+ }}
579
+
580
+ th {{
581
+ text-align: left;
582
+ padding: 12px 10px;
583
+ background: white;
584
+ border-bottom: 2px solid #ffc0e3;
585
+ color: #e91e63;
586
+ font-weight: 700;
587
+ text-transform: uppercase;
588
+ font-size: 12px;
589
+ letter-spacing: 1px;
590
+ }}
591
+
592
+ td {{
593
+ padding: 12px 10px;
594
+ border-bottom: 1px solid #f0f0f0;
595
+ vertical-align: top;
596
+ }}
597
+
598
+ tr:last-child td {{
599
+ border-bottom: none;
600
+ }}
601
+
602
+ .token-box {{
603
+ background: #f9f9f9;
604
+ border: 1px solid #ddd;
605
+ border-radius: 6px;
606
+ padding: 15px;
607
+ font-family: monospace;
608
+ font-size: 12px;
609
+ word-break: break-all;
610
+ color: #333;
611
+ max-height: 200px;
612
+ overflow-y: auto;
613
+ margin-bottom: 30px;
614
+ }}
615
+
616
+ ul {{
617
+ margin-left: 20px;
618
+ margin-bottom: 30px;
619
+ }}
620
+
621
+ li {{
622
+ margin-bottom: 8px;
623
+ color: #333;
624
+ }}
625
+
626
+ .footer {{
627
+ text-align: center;
628
+ color: #999;
629
+ font-size: 12px;
630
+ margin-top: 40px;
631
+ padding-top: 20px;
632
+ border-top: 1px solid #ffc0e3;
633
+ }}
634
+
635
+ .footer-icon {{
636
+ color: #e91e63;
637
+ font-size: 16px;
638
+ }}
639
+ </style>
640
+ </head>
641
+ <body>
642
+ <div class="container">
643
+ <div class="header">
644
+ <h1>JWT SECURITY ASSESSMENT REPORT</h1>
645
+ <p class="subtitle">Automated Vulnerability Scan | Confidential Security Document</p>
646
+ <p class="date">Report Generated: {datetime.now().strftime("%B %d, %Y at %H:%M:%S")}</p>
647
+ <div class="heart">💗</div>
648
+ <p class="quote">"The goal of security is not to eliminate risk,<br>but to bring it to an acceptable level."</p>
649
+ </div>
650
+
651
+ <h2 class="section-title">Report Overview</h2>
652
+ <div class="overview">
653
+ This report presents the results of an automated security assessment performed on the provided JSON Web Token (JWT). The scanner analyzed the token against multiple security best practices and identified potential vulnerabilities.
654
+ </div>
655
+
656
+ <div class="stats">
657
+ <div class="stat">
658
+ <div class="stat-label">Total Findings</div>
659
+ <div class="stat-value">{total}</div>
660
+ </div>
661
+ <div class="stat">
662
+ <div class="stat-label">Critical</div>
663
+ <div class="stat-value" style="color: #dc2626;">{critical}</div>
664
+ </div>
665
+ <div class="stat">
666
+ <div class="stat-label">High</div>
667
+ <div class="stat-value" style="color: #ea580c;">{high}</div>
668
+ </div>
669
+ <div class="stat">
670
+ <div class="stat-label">Medium</div>
671
+ <div class="stat-value" style="color: #b45309;">{medium}</div>
672
+ </div>
673
+ <div class="stat">
674
+ <div class="stat-label">Low</div>
675
+ <div class="stat-value" style="color: #4b5563;">{low}</div>
676
+ </div>
677
+ </div>
678
+
679
+ <h2 class="section-title">Security Findings</h2>
680
+ <table>
681
+ <tr>
682
+ <th style="width: 40px;">#</th>
683
+ <th style="width: 80px;">Severity</th>
684
+ <th style="width: 200px;">Category</th>
685
+ <th>Finding</th>
686
+ <th>Details</th>
687
+ </tr>
688
+ {''.join(findings_html)}
689
+ </table>
690
+
691
+ <h2 class="section-title">Token Details</h2>
692
+ <table>
693
+ {''.join(payload_html)}
694
+ </table>
695
+
696
+ <h2 class="section-title">Recommendations</h2>
697
+ <ul>
698
+ <li>Never use 'none' algorithm. Always use a secure algorithm like RS256 or HS256.</li>
699
+ <li>Always set an expiration time (exp) for tokens.</li>
700
+ <li>Avoid including sensitive information in the payload.</li>
701
+ <li>Use strong secret keys (minimum 32 characters for HS256).</li>
702
+ <li>Follow the principle of least privilege when assigning permissions.</li>
703
+ </ul>
704
+
705
+ <div class="footer">
706
+ Generated by <strong>JWT Security Scanner</strong><br>
707
+ Stay safe, stay pink, stay secure! <span class="footer-icon">🌸</span>
708
+ </div>
709
+ </div>
710
+ </body>
711
+ </html>"""
712
+
713
+ with open(filename, 'w', encoding='utf-8') as f:
714
+ f.write(html)
715
+
716
+ return filename
717
+
718
+
719
+ if __name__ == "__main__":
720
+ main()
@@ -0,0 +1,186 @@
1
+ Metadata-Version: 2.4
2
+ Name: jwt-security-scanner
3
+ Version: 1.0.0
4
+ Summary: A tool to scan JWT tokens for security vulnerabilities
5
+ Home-page: https://github.com/tabassumfathima28/JWT-Security-Scanner
6
+ Author: Tabassum Fathima
7
+ Author-email: tabassumfathima2812@gmail.com
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Topic :: Security
12
+ Requires-Python: >=3.7
13
+ Description-Content-Type: text/markdown
14
+ Requires-Dist: pyjwt>=2.0.0
15
+ Requires-Dist: requests>=2.0.0
16
+ Requires-Dist: colorama>=0.4.0
17
+ Requires-Dist: rich>=10.0.0
18
+ Dynamic: author
19
+ Dynamic: author-email
20
+ Dynamic: classifier
21
+ Dynamic: description
22
+ Dynamic: description-content-type
23
+ Dynamic: home-page
24
+ Dynamic: requires-dist
25
+ Dynamic: requires-python
26
+ Dynamic: summary
27
+
28
+ # JWT Security Scanner 🔐
29
+
30
+ > A Python-based command-line tool that automatically scans JWT tokens for security vulnerabilities and generates professional security reports.
31
+
32
+ ---
33
+
34
+ ## What is This Tool?
35
+
36
+ JWT (JSON Web Token) is used by millions of websites to handle user authentication. But poorly configured JWT tokens can be exploited by hackers to bypass login, steal accounts, or gain admin access.
37
+
38
+ This tool acts like a **security doctor for JWT tokens** — you give it a token, it runs 5 security checks and tells you exactly what's wrong and how to fix it.
39
+
40
+ ---
41
+
42
+ ## Features
43
+
44
+ - Detects 5 critical JWT vulnerability categories
45
+ - Beautiful colored terminal output
46
+ - Generates professional HTML security report
47
+ - Generates text report for documentation
48
+ - Includes security recommendations
49
+ - Works on any JWT token
50
+
51
+ ---
52
+
53
+ ## Vulnerabilities Detected
54
+
55
+ | Check | What it detects | Risk Level |
56
+ |-------|----------------|------------|
57
+ | Algorithm Check | Dangerous 'none' algorithm usage | CRITICAL |
58
+ | Weak Secret Key | Guesses secret key from common passwords | CRITICAL |
59
+ | Token Expiry | Missing or expired expiry time | HIGH |
60
+ | Sensitive Data | Passwords or private data in payload | HIGH |
61
+ | Token Claims | Missing issuer, subject, audience | MEDIUM |
62
+
63
+ ---
64
+
65
+ ## Tools and Technologies
66
+
67
+ - **Python 3** — Core programming language
68
+ - **PyJWT** — JWT token decoding and validation
69
+ - **Rich** — Beautiful terminal formatting
70
+ - **Colorama** — Terminal color support
71
+
72
+ ---
73
+
74
+ ## Installation
75
+
76
+ ### Step 1 — Clone the repository
77
+ ```bash
78
+ git clone https://github.com/YOURUSERNAME/JWT-Security-Scanner.git
79
+ cd JWT-Security-Scanner
80
+ ```
81
+
82
+ ### Step 2 — Install dependencies
83
+ ```bash
84
+ pip install -r requirements.txt
85
+ ```
86
+
87
+ ---
88
+
89
+ ## Usage
90
+
91
+ ### Run the scanner
92
+ ```bash
93
+ python jwt_scanner.py
94
+ ```
95
+
96
+ ### Or pass token directly
97
+ ```bash
98
+ python jwt_scanner.py YOUR_JWT_TOKEN_HERE
99
+ ```
100
+
101
+ ### Generate a test vulnerable token
102
+ ```bash
103
+ python -c "import jwt; print(jwt.encode({'user': 'admin', 'password': 'secret123'}, 'secret', algorithm='HS256'))"
104
+ ```
105
+
106
+ ---
107
+
108
+ ## Example Output
109
+
110
+ ```
111
+ JWT Security Scanner
112
+ Finds vulnerabilities in JWT tokens
113
+
114
+ SECURITY FINDINGS
115
+ CRITICAL WEAK SECRET KEY FOUND: 'secret'
116
+ HIGH No expiry time found!
117
+ HIGH Sensitive fields found: password
118
+
119
+ SECURITY SUMMARY
120
+ CRITICAL 1
121
+ HIGH 2
122
+ MEDIUM 0
123
+ LOW 5
124
+
125
+ CRITICAL VULNERABILITIES FOUND! This token is DANGEROUS!
126
+ ```
127
+
128
+ ---
129
+
130
+ ## Reports Generated
131
+
132
+ After every scan the tool automatically generates:
133
+
134
+ ### 1. Text Report
135
+ Plain text file with all findings — perfect for documentation
136
+
137
+ ### 2. HTML Report
138
+ Professional security report with color coded risk levels, summary dashboard, findings table, recommendations and cybersecurity quotes
139
+
140
+ ---
141
+
142
+ ## What I Learned Building This
143
+
144
+ - JWT token structure — Header, Payload, Signature
145
+ - Common JWT vulnerabilities and how attackers exploit them
146
+ - Python security tool development
147
+ - Automated vulnerability scanning techniques
148
+ - Professional security report generation
149
+ - The difference between encoding and encryption
150
+
151
+ ---
152
+
153
+ ## Real World Application
154
+
155
+ This tool simulates what penetration testers and security engineers do when auditing web applications. JWT vulnerabilities are listed in the **OWASP Top 10** and are responsible for thousands of security breaches every year.
156
+
157
+ ---
158
+
159
+ ## Project Structure
160
+
161
+ ```
162
+ JWT-Security-Scanner/
163
+
164
+ ├── jwt_scanner.py Main scanner with all checks
165
+ ├── requirements.txt Python dependencies
166
+ └── README.md Project documentation
167
+ ```
168
+
169
+ ---
170
+
171
+ ## Also Check Out
172
+
173
+ My other cybersecurity project:
174
+ - [AI-Powered SIEM Home Lab](https://github.com/tabassumfathima28/SIEM-HOME-LAB-PROJECT) — Detects real cyber attacks using Elastic SIEM and Tines automation
175
+
176
+ ---
177
+
178
+ ## Connect With Me
179
+
180
+ Built by an aspiring SOC Analyst learning cybersecurity through hands-on projects.
181
+
182
+ Connect on [LinkedIn](#)
183
+
184
+ ---
185
+
186
+ > "Security is not a product, but a process." — Bruce Schneier
@@ -0,0 +1,11 @@
1
+ README.md
2
+ pyproject.toml
3
+ setup.py
4
+ jwt_scanner/__init__.py
5
+ jwt_scanner/scanner.py
6
+ jwt_security_scanner.egg-info/PKG-INFO
7
+ jwt_security_scanner.egg-info/SOURCES.txt
8
+ jwt_security_scanner.egg-info/dependency_links.txt
9
+ jwt_security_scanner.egg-info/entry_points.txt
10
+ jwt_security_scanner.egg-info/requires.txt
11
+ jwt_security_scanner.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ jwt-scanner = jwt_scanner.scanner:main
@@ -0,0 +1,4 @@
1
+ pyjwt>=2.0.0
2
+ requests>=2.0.0
3
+ colorama>=0.4.0
4
+ rich>=10.0.0
@@ -0,0 +1,3 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,31 @@
1
+ from setuptools import setup, find_packages
2
+
3
+ setup(
4
+ name="jwt-security-scanner",
5
+ version="1.0.0",
6
+ author="Tabassum Fathima",
7
+ author_email="tabassumfathima2812@gmail.com",
8
+ description="A tool to scan JWT tokens for security vulnerabilities",
9
+ long_description=open("README.md", encoding="utf-8").read(),
10
+ long_description_content_type="text/markdown",
11
+ url="https://github.com/tabassumfathima28/JWT-Security-Scanner",
12
+ packages=find_packages(),
13
+ install_requires=[
14
+ "pyjwt>=2.0.0",
15
+ "requests>=2.0.0",
16
+ "colorama>=0.4.0",
17
+ "rich>=10.0.0",
18
+ ],
19
+ entry_points={
20
+ "console_scripts": [
21
+ "jwt-scanner=jwt_scanner.scanner:main",
22
+ ],
23
+ },
24
+ classifiers=[
25
+ "Programming Language :: Python :: 3",
26
+ "License :: OSI Approved :: MIT License",
27
+ "Operating System :: OS Independent",
28
+ "Topic :: Security",
29
+ ],
30
+ python_requires=">=3.7",
31
+ )