Skip to content

Commit 07dfa9b

Browse files
chanel-yCopilot
andcommitted
Add JWT none algorithm detection query for PowerShell
Detects usage of 'none' algorithm in JWT token creation via PowerShell modules (New-Jwt, etc.) and .NET JWT APIs (CreateToken, etc.). Covers: Cryptography.10033 (CWE-347) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent cccecc4 commit 07dfa9b

4 files changed

Lines changed: 83 additions & 0 deletions

File tree

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* @name JWT none algorithm usage
3+
* @description Using the "none" algorithm for JWT tokens disables signature verification,
4+
* allowing token forgery.
5+
* @kind problem
6+
* @problem.severity error
7+
* @security-severity 9.8
8+
* @precision medium
9+
* @id powershell/microsoft/security/jwt-none-algorithm
10+
* @tags security
11+
* external/cwe/cwe-347
12+
*/
13+
14+
import powershell
15+
import semmle.code.powershell.dataflow.DataFlow
16+
17+
// NOTE: PowerShell is a beta language for CodeQL and has no built-in JWT library modeling.
18+
// This query detects common patterns of JWT "none" algorithm usage in PowerShell modules
19+
// such as PSJwt, JWTPS, and direct .NET JWT library calls.
20+
// Coverage may be limited for less common JWT libraries.
21+
22+
/**
23+
* A string literal containing "none" used in a JWT-related cmdlet call.
24+
*/
25+
class JwtNoneAlgorithmLiteral extends StringConstExpr {
26+
JwtNoneAlgorithmLiteral() {
27+
this.getValueString().toLowerCase() = "none" and
28+
exists(CmdCall call |
29+
call.matchesName([
30+
"New-Jwt", "New-JsonWebToken", "ConvertTo-Jwt",
31+
"New-JWTToken", "ConvertTo-JWTToken"
32+
]) and
33+
this = call.getAnArgument()
34+
)
35+
}
36+
}
37+
38+
/**
39+
* A string literal "none" passed as an algorithm argument to .NET JWT methods.
40+
*/
41+
class JwtNoneInDotNetCall extends StringConstExpr {
42+
JwtNoneInDotNetCall() {
43+
this.getValueString().toLowerCase() = "none" and
44+
exists(InvokeMemberExpr call |
45+
call.matchesName([
46+
"CreateToken", "WriteToken", "CreateJwtSecurityToken", "CreateEncodedJwt"
47+
]) and
48+
this = call.getAnArgument()
49+
)
50+
}
51+
}
52+
53+
from StringConstExpr noneAlg, string msg
54+
where
55+
(
56+
noneAlg instanceof JwtNoneAlgorithmLiteral and
57+
msg = "JWT token created with 'none' algorithm, disabling signature verification."
58+
)
59+
or
60+
(
61+
noneAlg instanceof JwtNoneInDotNetCall and
62+
msg =
63+
"JWT token created with 'none' algorithm via .NET API, disabling signature verification."
64+
)
65+
select noneAlg, msg
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
| test.ps1:6:29:6:34 | none | JWT token created with 'none' algorithm, disabling signature verification. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
queries/security/cwe-347/JwtNoneAlgorithm.ql
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# ===================================================================
2+
# ========== TRUE POSITIVES (should trigger alert) ==================
3+
# ===================================================================
4+
5+
# --- Case 1: PSJwt module with "none" algorithm ---
6+
$token = New-Jwt -Algorithm "none" -Payload @{sub="user"} # BAD
7+
8+
# ===================================================================
9+
# ========== TRUE NEGATIVES (should NOT trigger alert) ==============
10+
# ===================================================================
11+
12+
# --- Safe: JWT with HS256 ---
13+
$token = New-Jwt -Algorithm "HS256" -Payload @{sub="user"} -Secret $key # GOOD
14+
15+
# --- Safe: Unrelated string "none" ---
16+
$value = "none" # GOOD

0 commit comments

Comments
 (0)