| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -12,7 +12,7 @@ import javascript | |||
| 12 | 12 | abstract class CredentialsNode extends DataFlow::Node { | |
| 13 | 13 | /** | |
| 14 | 14 | * Gets a description of the kind of credential this expression is used as, | |
| 15 | - * such as `"user name"`, `"password"`, `"key"`. | ||
| 15 | + * such as `"user name"`, `"password"`, `"key"`, `"jwt key"`. | ||
| 16 | 16 | */ | |
| 17 | 17 | abstract string getCredentialsKind(); | |
| 18 | 18 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -40,11 +40,111 @@ private module JsonWebToken { | |||
| 40 | 40 | } | |
| 41 | 41 | ||
| 42 | 42 | /** | |
| 43 | - * The private key for a JWT as a `CredentialsNode`. | ||
| 43 | + * The secret or PrivateKey for a JWT as a `CredentialsNode`. | ||
| 44 | 44 | */ | |
| 45 | 45 | private class JwtKey extends CredentialsNode { | |
| 46 | - JwtKey() { this = DataFlow::moduleMember("jsonwebtoken", "sign").getACall().getArgument(1) } | ||
| 46 | + JwtKey() { | ||
| 47 | + this = | ||
| 48 | + API::moduleImport("jsonwebtoken").getMember(["sign", "verify"]).getParameter(1).asSink() | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + override string getCredentialsKind() { result = "jwt key" } | ||
| 52 | + } | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + /** | ||
| 56 | + * Provides classes and predicates modeling the `jose` library. | ||
| 57 | + */ | ||
| 58 | + private module Jose { | ||
| 59 | + /** | ||
| 60 | + * The asymmetric key or symmetric secret for verifying a JWT as a `CredentialsNode`. | ||
| 61 | + */ | ||
| 62 | + private class JwtVerifyKey extends CredentialsNode { | ||
| 63 | + JwtVerifyKey() { | ||
| 64 | + this = API::moduleImport("jose").getMember("jwtVerify").getParameter(1).asSink() | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + override string getCredentialsKind() { result = "jwt key" } | ||
| 68 | + } | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + /** | ||
| 72 | + * Provides classes and predicates modeling the `jwt-simple` library. | ||
| 73 | + */ | ||
| 74 | + private module JwtSimple { | ||
| 75 | + /** | ||
| 76 | + * The asymmetric key or symmetric secret for a JWT as a `CredentialsNode`. | ||
| 77 | + */ | ||
| 78 | + private class JwtKey extends CredentialsNode { | ||
| 79 | + JwtKey() { this = API::moduleImport("jwt-simple").getMember("decode").getParameter(1).asSink() } | ||
| 80 | + | ||
| 81 | + override string getCredentialsKind() { result = "jwt key" } | ||
| 82 | + } | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + /** | ||
| 86 | + * Provides classes and predicates modeling the `koa-jwt` library. | ||
| 87 | + */ | ||
| 88 | + private module KoaJwt { | ||
| 89 | + /** | ||
| 90 | + * The shared secret for a JWT as a `CredentialsNode`. | ||
| 91 | + */ | ||
| 92 | + private class SharedSecret extends CredentialsNode { | ||
| 93 | + SharedSecret() { | ||
| 94 | + this = API::moduleImport("koa-jwt").getParameter(0).getMember("secret").asSink() | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + override string getCredentialsKind() { result = "jwt key" } | ||
| 98 | + } | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + /** | ||
| 102 | + * Provides classes and predicates modeling the `express-jwt` library. | ||
| 103 | + */ | ||
| 104 | + private module ExpressJwt { | ||
| 105 | + /** | ||
| 106 | + * The shared secret for a JWT as a `CredentialsNode`. | ||
| 107 | + */ | ||
| 108 | + private class SharedSecret extends CredentialsNode { | ||
| 109 | + SharedSecret() { | ||
| 110 | + this = | ||
| 111 | + API::moduleImport("express-jwt") | ||
| 112 | + .getMember("expressjwt") | ||
| 113 | + .getParameter(0) | ||
| 114 | + .getMember("secret") | ||
| 115 | + .asSink() | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + override string getCredentialsKind() { result = "jwt key" } | ||
| 119 | + } | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + /** | ||
| 123 | + * Provides classes and predicates modeling the `passport-jwt` library. | ||
| 124 | + */ | ||
| 125 | + private module PassportJwt { | ||
| 126 | + /** | ||
| 127 | + * The secret (symmetric) or PEM-encoded public key (asymmetric) for a JWT as a `CredentialsNode`. | ||
| 128 | + */ | ||
| 129 | + private class JwtKey extends CredentialsNode { | ||
| 130 | + JwtKey() { | ||
| 131 | + this = | ||
| 132 | + API::moduleImport("passport-jwt") | ||
| 133 | + .getMember("Strategy") | ||
| 134 | + .getParameter(0) | ||
| 135 | + .getMember("secretOrKey") | ||
| 136 | + .asSink() | ||
| 137 | + or | ||
| 138 | + this = | ||
| 139 | + API::moduleImport("passport-jwt") | ||
| 140 | + .getMember("Strategy") | ||
| 141 | + .getParameter(0) | ||
| 142 | + .getMember("secretOrKeyProvider") | ||
| 143 | + .getParameter(2) | ||
| 144 | + .getParameter(1) | ||
| 145 | + .asSink() | ||
| 146 | + } | ||
| 47 | 147 | ||
| 48 | - override string getCredentialsKind() { result = "key" } | ||
| 148 | + override string getCredentialsKind() { result = "jwt key" } | ||
| 49 | 149 | } | |
| 50 | 150 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -255,4 +255,20 @@ module NextJS { | |||
| 255 | 255 | .getMember("router") | |
| 256 | 256 | .asSource() | |
| 257 | 257 | } | |
| 258 | + | ||
| 259 | + /** | ||
| 260 | + * Provides classes and predicates modeling the `next-auth` library. | ||
| 261 | + */ | ||
| 262 | + private module NextAuth { | ||
| 263 | + /** | ||
| 264 | + * A random string used to hash tokens, sign cookies and generate cryptographic keys as a `CredentialsNode`. | ||
| 265 | + */ | ||
| 266 | + private class SecretKey extends CredentialsNode { | ||
| 267 | + SecretKey() { | ||
| 268 | + this = API::moduleImport("next-auth").getParameter(0).getMember("secret").asSink() | ||
| 269 | + } | ||
| 270 | + | ||
| 271 | + override string getCredentialsKind() { result = "jwt key" } | ||
| 272 | + } | ||
| 273 | + } | ||
| 258 | 274 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4,6 +4,7 @@ | |||
| 4 | 4 | * own. | |
| 5 | 5 | */ | |
| 6 | 6 | ||
| 7 | + import semmle.javascript.filters.ClassifyFiles | ||
| 7 | 8 | import javascript | |
| 8 | 9 | private import semmle.javascript.security.SensitiveActions | |
| 9 | 10 | ||
@@ -38,5 +39,9 @@ module HardcodedCredentials { | |||
| 38 | 39 | */ | |
| 39 | 40 | class DefaultCredentialsSink extends Sink instanceof CredentialsNode { | |
| 40 | 41 | override string getKind() { result = super.getCredentialsKind() } | |
| 42 | + | ||
| 43 | + DefaultCredentialsSink() { | ||
| 44 | + not (super.getCredentialsKind() = "jwt key" and isTestFile(this.getFile())) | ||
| 45 | + } | ||
| 41 | 46 | } | |
| 42 | 47 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -35,5 +35,43 @@ class Configuration extends DataFlow::Configuration { | |||
| 35 | 35 | trg = bufferFrom and | |
| 36 | 36 | src = bufferFrom.getArgument(0) | |
| 37 | 37 | ) | |
| 38 | + or | ||
| 39 | + exists(API::Node n | | ||
| 40 | + n = API::moduleImport("jose").getMember(["importSPKI", "importPKCS8", "importX509"]) | ||
| 41 | + | | ||
| 42 | + src = n.getACall().getArgument(0) and | ||
| 43 | + trg = n.getReturn().getPromised().asSource() | ||
| 44 | + ) | ||
| 45 | + or | ||
| 46 | + exists(API::Node n | | ||
| 47 | + n = API::moduleImport("jose").getMember(["importSPKI", "importPKCS8", "importX509"]) | ||
| 48 | + | | ||
| 49 | + src = n.getACall().getArgument(0) and | ||
| 50 | + trg = n.getReturn().getPromised().asSource() | ||
| 51 | + ) | ||
| 52 | + or | ||
| 53 | + exists(API::Node n | n = API::moduleImport("jose").getMember("importJWK") | | ||
| 54 | + src = n.getParameter(0).getMember(["x", "y", "n"]).asSink() and | ||
| 55 | + trg = n.getReturn().getPromised().asSource() | ||
| 56 | + ) | ||
| 57 | + or | ||
| 58 | + exists(DataFlow::CallNode n | | ||
| 59 | + n = DataFlow::globalVarRef("TextEncoder").getAnInstantiation().getAMemberCall("encode") | ||
| 60 | + | | ||
| 61 | + src = n.getArgument(0) and | ||
| 62 | + trg = n | ||
| 63 | + ) | ||
| 64 | + or | ||
| 65 | + exists(DataFlow::CallNode n | n = DataFlow::globalVarRef("Buffer").getAMemberCall("from") | | ||
| 66 | + src = n.getArgument(0) and | ||
| 67 | + trg = [n, n.getAChainedMethodCall(["toString", "toJSON"])] | ||
| 68 | + ) | ||
| 69 | + or | ||
| 70 | + exists(API::Node n | | ||
| 71 | + n = API::moduleImport("jose").getMember("base64url").getMember(["decode", "encode"]) | ||
| 72 | + | | ||
| 73 | + src = n.getACall().getArgument(0) and | ||
| 74 | + trg = n.getACall() | ||
| 75 | + ) | ||
| 38 | 76 | } | |
| 39 | 77 | } | |
| Back | FazBrowse Home | New Git URL |
0 commit comments