Skip to content

Commit 48a9b10

Browse files
committed
add query to detect strapi CVe too
1 parent 5cc4206 commit 48a9b10

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/**
2+
* @name JWT missing secret or public key verification
3+
* @description The application does not verify the JWT payload with a cryptographic secret or public key.
4+
* @kind path-problem
5+
* @problem.severity error
6+
* @security-severity 8.0
7+
* @precision high
8+
* @id js/jwt-missing-verification-jsonwebtoken
9+
* @tags security
10+
* external/cwe/cwe-347
11+
*/
12+
13+
import javascript
14+
import DataFlow::PathGraph
15+
16+
DataFlow::Node unverifiedDecode() {
17+
result = API::moduleImport("jsonwebtoken").getMember("decode").getParameter(0).asSink()
18+
or
19+
exists(API::Node verify | verify = API::moduleImport("jsonwebtoken").getMember("verify") |
20+
verify
21+
.getParameter(2)
22+
.getMember("algorithms")
23+
.getUnknownMember()
24+
.asSink()
25+
.mayHaveStringValue("none") and
26+
result = verify.getParameter(0).asSink()
27+
)
28+
}
29+
30+
DataFlow::Node verifiedDecode() {
31+
exists(API::Node verify | verify = API::moduleImport("jsonwebtoken").getMember("verify") |
32+
(
33+
not verify
34+
.getParameter(2)
35+
.getMember("algorithms")
36+
.getUnknownMember()
37+
.asSink()
38+
.mayHaveStringValue("none") or
39+
not exists(verify.getParameter(2).getMember("algorithms"))
40+
) and
41+
result = verify.getParameter(0).asSink()
42+
)
43+
}
44+
45+
class Configuration extends TaintTracking::Configuration {
46+
Configuration() { this = "jsonwebtoken without any signature verification" }
47+
48+
override predicate isSource(DataFlow::Node source) {
49+
source =
50+
API::moduleImport("jsonwebtoken")
51+
.getMember("decode")
52+
.getParameter(0)
53+
.asSink()
54+
.getALocalSource()
55+
}
56+
57+
override predicate isSink(DataFlow::Node sink) {
58+
sink = unverifiedDecode()
59+
or
60+
sink = verifiedDecode()
61+
}
62+
}
63+
64+
/** Holds if `source` flows to the first parameter of jsonwebtoken.verify */
65+
predicate isSafe(Configuration cfg, DataFlow::Node source) {
66+
exists(DataFlow::Node sink |
67+
cfg.hasFlow(source, sink) and
68+
sink = verifiedDecode()
69+
)
70+
}
71+
72+
/**
73+
* Holds if:
74+
* - `source` does not flow to the first parameter of `jsonwebtoken.verify`, and
75+
* - `source` flows to the first parameter of `jsonwebtoken.decode`
76+
*/
77+
predicate isVulnerable(Configuration cfg, DataFlow::Node source, DataFlow::Node sink) {
78+
not isSafe(cfg, source) and // i.e., source does not flow to a verify call
79+
cfg.hasFlow(source, sink) and // but it does flow to something else
80+
sink = unverifiedDecode() // and that something else is a call to decode.
81+
}
82+
83+
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
84+
where
85+
cfg.hasFlowPath(source, sink) and
86+
isVulnerable(cfg, source.getNode(), sink.getNode())
87+
select source.getNode(), source, sink, "Decoding JWT $@.", sink.getNode(),
88+
"without signature verification"

0 commit comments

Comments
 (0)