From d296daaf1e423f1548b4641905857ac7012c75f0 Mon Sep 17 00:00:00 2001 From: Sakshis Date: Thu, 5 Dec 2024 07:27:01 +0000 Subject: [PATCH 1/3] jwt-simple-noverify-javascript --- .../jwt-simple-noverify-javascript.yml | 44 +++++++++ ...wt-simple-noverify-javascript-snapshot.yml | 68 ++++++++++++++ .../jwt-simple-noverify-javascript-test.yml | 91 +++++++++++++++++++ 3 files changed, 203 insertions(+) create mode 100644 rules/javascript/security/jwt-simple-noverify-javascript.yml create mode 100644 tests/__snapshots__/jwt-simple-noverify-javascript-snapshot.yml create mode 100644 tests/javascript/jwt-simple-noverify-javascript-test.yml diff --git a/rules/javascript/security/jwt-simple-noverify-javascript.yml b/rules/javascript/security/jwt-simple-noverify-javascript.yml new file mode 100644 index 00000000..1339d49a --- /dev/null +++ b/rules/javascript/security/jwt-simple-noverify-javascript.yml @@ -0,0 +1,44 @@ +id: jwt-simple-noverify-javascript +language: JavaScript +severity: warning +message: >- + "Detected the decoding of a JWT token without a verify step. JWT tokens + must be verified before use, otherwise the token's integrity is unknown. + This means a malicious actor could forge a JWT token with any claims. Set + 'verify' to `true` before using the token." +note: >- + [CWE-287] Improper Authentication + [CWE-345] Insufficient Verification of Data Authenticity + [CWE-347] Improper Verification of Cryptographic Signature + [REFERENCES] + - https://www.npmjs.com/package/jwt-simple + - https://cwe.mitre.org/data/definitions/287 + - https://cwe.mitre.org/data/definitions/345 + - https://cwe.mitre.org/data/definitions/347 +rule: + kind: call_expression + any: + - pattern: $JWT.decode($TOKEN, $SECRET, true $$$) + - pattern: $JWT.decode($TOKEN, $SECRET, "$$$" $$$) + - pattern: $JWT.decode($TOKEN, $SECRET, '$$$' $$$) + - pattern: $JWT.decode($TOKEN, $SECRET, `$$$` $$$) + inside: + stopBy: end + follows: + stopBy: end + any: + - kind: lexical_declaration + all: + - has: + stopBy: end + kind: identifier + pattern: $JWT + - has: + stopBy: end + kind: call_expression + pattern: require('jwt-simple') + - kind: expression_statement + has: + stopBy: end + kind: assignment_expression + pattern: $JWT = require('jwt-simple') diff --git a/tests/__snapshots__/jwt-simple-noverify-javascript-snapshot.yml b/tests/__snapshots__/jwt-simple-noverify-javascript-snapshot.yml new file mode 100644 index 00000000..d310e73c --- /dev/null +++ b/tests/__snapshots__/jwt-simple-noverify-javascript-snapshot.yml @@ -0,0 +1,68 @@ +id: jwt-simple-noverify-javascript +snapshots: + ? "const jwt = require('jwt-simple'); \n\napp.get('/protectedRoute1', (req, res) => {\n const token = req.headers.authorization;\n\n if (!token) {\n return res.status(401).json({ error: 'Unauthorized. Token missing.' });\n }\n\n try {\n // ruleid: jwt-simple-noverify \n const decoded = jwt.decode(token, secretKey, 'HS256', 12);\n res.json({ message: `Hello ${decoded.username}` });\n } catch (error) {\n res.status(401).json({ error: 'Unauthorized. Invalid token.' });\n }\n});\n" + : labels: + - source: jwt.decode(token, secretKey, 'HS256', 12) + style: primary + start: 287 + end: 328 + - source: jwt + style: secondary + start: 6 + end: 9 + - source: require('jwt-simple') + style: secondary + start: 12 + end: 33 + - source: const jwt = require('jwt-simple'); + style: secondary + start: 0 + end: 34 + - source: const jwt = require('jwt-simple'); + style: secondary + start: 0 + end: 34 + ? "const jwt = require('jwt-simple'); \n\napp.get('/protectedRoute2', (req, res) => {\n const token = req.headers.authorization;\n\n if (!token) {\n return res.status(401).json({ error: 'Unauthorized. Token missing.' });\n }\n\n try {\n // ruleid: jwt-simple-noverify \n const decoded = jwt.decode(token, secretKey, true);\n res.json({ message: `Hello ${decoded.username}` });\n } catch (error) {\n res.status(401).json({ error: 'Unauthorized. Invalid token.' });\n }\n});\n" + : labels: + - source: jwt.decode(token, secretKey, true) + style: primary + start: 289 + end: 323 + - source: jwt + style: secondary + start: 6 + end: 9 + - source: require('jwt-simple') + style: secondary + start: 12 + end: 33 + - source: const jwt = require('jwt-simple'); + style: secondary + start: 0 + end: 34 + - source: const jwt = require('jwt-simple'); + style: secondary + start: 0 + end: 34 + ? "const jwt = require('jwt-simple'); \n\napp.get('/protectedRoute3', (req, res) => {\n const token = req.headers.authorization;\n\n if (!token) {\n return res.status(401).json({ error: 'Unauthorized. Token missing.' });\n }\n\n try {\n // ruleid: jwt-simple-noverify \n const decoded = jwt.decode(token, secretKey, 'false');\n res.json({ message: `Hello ${decoded.username}` });\n } catch (error) {\n res.status(401).json({ error: 'Unauthorized. Invalid token.' });\n }\n});\n" + : labels: + - source: jwt.decode(token, secretKey, 'false') + style: primary + start: 290 + end: 327 + - source: jwt + style: secondary + start: 6 + end: 9 + - source: require('jwt-simple') + style: secondary + start: 12 + end: 33 + - source: const jwt = require('jwt-simple'); + style: secondary + start: 0 + end: 34 + - source: const jwt = require('jwt-simple'); + style: secondary + start: 0 + end: 34 diff --git a/tests/javascript/jwt-simple-noverify-javascript-test.yml b/tests/javascript/jwt-simple-noverify-javascript-test.yml new file mode 100644 index 00000000..26ca82f3 --- /dev/null +++ b/tests/javascript/jwt-simple-noverify-javascript-test.yml @@ -0,0 +1,91 @@ +id: jwt-simple-noverify-javascript +valid: + - | + const jwt = require('jwt-simple'); + app.get('/protectedRoute4', (req, res) => { + const token = req.headers.authorization; + + if (!token) { + return res.status(401).json({ error: 'Unauthorized. Token missing.' }); + } + + try { + // ok: jwt-simple-noverify + const decoded = jwt.decode(token, secretKey); + res.json({ message: `Hello ${decoded.username}` }); + } catch (error) { + res.status(401).json({ error: 'Unauthorized. Invalid token.' }); + } + }); + - | + const jwt = require('jwt-simple'); + app.get('/protectedRoute5', (req, res) => { + const token = req.headers.authorization; + + if (!token) { + return res.status(401).json({ error: 'Unauthorized. Token missing.' }); + } + + try { + // ok: jwt-simple-noverify + const decoded = jwt.decode(token, secretKey, false); + res.json({ message: `Hello ${decoded.username}` }); + } catch (error) { + res.status(401).json({ error: 'Unauthorized. Invalid token.' }); + } + }); +invalid: + - | + const jwt = require('jwt-simple'); + + app.get('/protectedRoute1', (req, res) => { + const token = req.headers.authorization; + + if (!token) { + return res.status(401).json({ error: 'Unauthorized. Token missing.' }); + } + + try { + // ruleid: jwt-simple-noverify + const decoded = jwt.decode(token, secretKey, 'HS256', 12); + res.json({ message: `Hello ${decoded.username}` }); + } catch (error) { + res.status(401).json({ error: 'Unauthorized. Invalid token.' }); + } + }); + - | + const jwt = require('jwt-simple'); + + app.get('/protectedRoute2', (req, res) => { + const token = req.headers.authorization; + + if (!token) { + return res.status(401).json({ error: 'Unauthorized. Token missing.' }); + } + + try { + // ruleid: jwt-simple-noverify + const decoded = jwt.decode(token, secretKey, true); + res.json({ message: `Hello ${decoded.username}` }); + } catch (error) { + res.status(401).json({ error: 'Unauthorized. Invalid token.' }); + } + }); + - | + const jwt = require('jwt-simple'); + + app.get('/protectedRoute3', (req, res) => { + const token = req.headers.authorization; + + if (!token) { + return res.status(401).json({ error: 'Unauthorized. Token missing.' }); + } + + try { + // ruleid: jwt-simple-noverify + const decoded = jwt.decode(token, secretKey, 'false'); + res.json({ message: `Hello ${decoded.username}` }); + } catch (error) { + res.status(401).json({ error: 'Unauthorized. Invalid token.' }); + } + }); From 06a72845d0fd4099ae14027c5d8a9fe52539427e Mon Sep 17 00:00:00 2001 From: Sakshis Date: Thu, 5 Dec 2024 09:15:32 +0000 Subject: [PATCH 2/3] node-rsa-weak-key-javascript --- .../security/node-rsa-weak-key-javascript.yml | 576 ++++++++++++++++++ .../node-rsa-weak-key-javascript-snapshot.yml | 498 +++++++++++++++ .../node-rsa-weak-key-javascript-test.yml | 24 + 3 files changed, 1098 insertions(+) create mode 100644 rules/javascript/security/node-rsa-weak-key-javascript.yml create mode 100644 tests/__snapshots__/node-rsa-weak-key-javascript-snapshot.yml create mode 100644 tests/javascript/node-rsa-weak-key-javascript-test.yml diff --git a/rules/javascript/security/node-rsa-weak-key-javascript.yml b/rules/javascript/security/node-rsa-weak-key-javascript.yml new file mode 100644 index 00000000..870c1de0 --- /dev/null +++ b/rules/javascript/security/node-rsa-weak-key-javascript.yml @@ -0,0 +1,576 @@ +id: node-rsa-weak-key-javascript +language: javascript +severity: warning +message: >- + Use of RSA-$BITS, which is considered weak. Based on NIST standards, + RSA keys should be at least 2048 bits. +note: >- + [CWE-326] Inadequate Encryption Strength. + [REFERENCES] + - https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#algorithms +utils: + MATCH_BITS_DIRECTLY_NODE_FORGE: + kind: number + pattern: $R + inside: + stopBy: end + kind: lexical_declaration + all: + - has: + stopBy: end + kind: variable_declarator + has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: end + kind: member_expression + has: + stopBy: end + kind: member_expression + all: + - has: + stopBy: end + kind: identifier + pattern: $A + - has: + stopBy: end + kind: property_identifier + regex: '^rsa$' + - has: + stopBy: end + kind: arguments + has: + stopBy: end + kind: number + pattern: $R + - any: + - follows: + stopBy: end + kind: lexical_declaration + has: + stopBy: end + kind: variable_declarator + all: + - has: + stopBy: end + kind: identifier + pattern: $A + - has: + stopBy: end + kind: member_expression + all: + - has: + stopBy: end + kind: identifier + - has: + stopBy: neighbor + kind: property_identifier + regex: '^pki$' + - any: + - follows: + stopBy: end + kind: lexical_declaration + has: + stopBy: end + kind: variable_declarator + all: + - has: + stopBy: end + kind: identifier + - has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: '^require$' + - has: + stopBy: neighbor + kind: arguments + has: + stopBy: neighbor + kind: string + has: + stopBy: neighbor + kind: string_fragment + regex: '^node-forge$' + - follows: + stopBy: end + kind: import_statement + all: + - has: + stopBy: neighbor + kind: import_clause + has: + stopBy: end + kind: namespace_import + has: + stopBy: neighbor + kind: identifier + - has: + stopBy: end + kind: string + has: + stopBy: neighbor + kind: string_fragment + regex: '^node-forge$' + - follows: + stopBy: end + kind: import_statement + all: + - has: + stopBy: neighbor + kind: import_clause + - has: + stopBy: neighbor + kind: string + has: + stopBy: neighbor + kind: string_fragment + regex: '^node-forge$' + MATCH_BITS_DIRECTLY_NODE_RSA: + kind: number + pattern: $R + inside: + stopBy: end + kind: lexical_declaration + all: + - has: + stopBy: end + kind: variable_declarator + has: + stopBy: end + kind: new_expression + all: + - has: + stopBy: neighbor + kind: identifier + - has: + stopBy: neighbor + kind: arguments + has: + stopBy: neighbor + kind: object + has: + stopBy: neighbor + kind: pair + all: + - has: + stopBy: neighbor + kind: property_identifier + - has: + stopBy: neighbor + kind: number + - any: + - follows: + stopBy: end + kind: lexical_declaration + has: + stopBy: end + kind: variable_declarator + all: + - has: + stopBy: end + kind: identifier + - has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: '^require$' + - has: + stopBy: neighbor + kind: arguments + has: + stopBy: neighbor + kind: string + has: + stopBy: neighbor + kind: string_fragment + regex: '^node-rsa$' + - follows: + stopBy: end + kind: import_statement + all: + - has: + stopBy: neighbor + kind: import_clause + has: + stopBy: end + kind: namespace_import + has: + stopBy: neighbor + kind: identifier + - has: + stopBy: end + kind: string + has: + stopBy: neighbor + kind: string_fragment + regex: '^node-rsa$' + - follows: + stopBy: end + kind: import_statement + all: + - has: + stopBy: neighbor + kind: import_clause + - has: + stopBy: neighbor + kind: string + has: + stopBy: neighbor + kind: string_fragment + regex: '^node-rsa$' + MATCH_BITS_WITHIN_FUNCTION_WITH_NODE_FORGE: + kind: number + pattern: $R + inside: + stopBy: end + kind: variable_declaration + all: + - has: + stopBy: end + kind: variable_declarator + has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: end + kind: member_expression + - has: + stopBy: end + kind: arguments + has: + stopBy: end + kind: object + has: + stopBy: end + kind: pair + all: + - has: + stopBy: end + kind: property_identifier + - has: + stopBy: end + kind: number + pattern: $R + - any: + - follows: + stopBy: end + kind: lexical_declaration + has: + stopBy: end + kind: variable_declarator + all: + - has: + stopBy: end + kind: identifier + - has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: '^require$' + - has: + stopBy: neighbor + kind: arguments + has: + stopBy: neighbor + kind: string + has: + stopBy: neighbor + kind: string_fragment + regex: '^node-forge$' + - follows: + stopBy: end + kind: import_statement + all: + - has: + stopBy: neighbor + kind: import_clause + has: + stopBy: end + kind: namespace_import + has: + stopBy: neighbor + kind: identifier + - has: + stopBy: end + kind: string + has: + stopBy: neighbor + kind: string_fragment + regex: '^node-forge$' + - follows: + stopBy: end + kind: import_statement + all: + - has: + stopBy: neighbor + kind: import_clause + - has: + stopBy: neighbor + kind: string + has: + stopBy: neighbor + kind: string_fragment + regex: '^node-forge$' + MATCH_BITS_WITHIN_FUNCTION_WITH_CRYPTO_AND_PROMISIFY: + kind: number + pattern: $R + inside: + stopBy: end + kind: lexical_declaration + all: + - has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: end + kind: member_expression + has: + stopBy: end + kind: property_identifier + regex: '^promisify$' + - has: + stopBy: end + kind: arguments + has: + stopBy: end + kind: member_expression + all: + - has: + stopBy: end + kind: identifier + pattern: $E + - has: + stopBy: end + kind: property_identifier + - has: + stopBy: end + kind: arguments + all: + - has: + stopBy: end + kind: string + has: + stopBy: neighbor + kind: string_fragment + regex: '^rsa$' + - has: + stopBy: end + kind: object + has: + stopBy: neighbor + kind: pair + all: + - has: + stopBy: end + kind: property_identifier + regex: '^modulusLength$' + - any: + - follows: + stopBy: end + kind: lexical_declaration + has: + stopBy: end + kind: variable_declarator + all: + - has: + stopBy: end + kind: identifier + pattern: $E + - has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: '^require$' + - has: + stopBy: neighbor + kind: arguments + has: + stopBy: neighbor + kind: string + has: + stopBy: neighbor + kind: string_fragment + regex: '^crypto$' + - follows: + stopBy: end + kind: import_statement + all: + - has: + stopBy: neighbor + kind: import_clause + has: + stopBy: end + kind: namespace_import + has: + stopBy: neighbor + kind: identifier + pattern: $E + - has: + stopBy: end + kind: string + has: + stopBy: neighbor + kind: string_fragment + regex: '^crypto$' + - follows: + stopBy: end + kind: import_statement + all: + - has: + stopBy: neighbor + kind: import_clause + - has: + stopBy: neighbor + kind: string + has: + stopBy: neighbor + kind: string_fragment + regex: '^crypto$' + MATCH_BITS_WITHIN_FUNCTION_WITH_CRYPTO: + kind: number + pattern: $R + inside: + stopBy: end + kind: lexical_declaration + all: + - has: + stopBy: end + kind: variable_declarator + has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: end + kind: member_expression + all: + - has: + stopBy: end + kind: identifier + pattern: $S + - has: + stopBy: end + kind: property_identifier + - has: + stopBy: end + kind: arguments + all: + - has: + stopBy: end + kind: string + has: + stopBy: end + kind: string_fragment + regex: '^rsa$' + - has: + stopBy: end + kind: object + has: + stopBy: end + kind: pair + all: + - has: + stopBy: end + kind: property_identifier + regex: '^modulusLength$' + - has: + stopBy: neighbor + kind: number + pattern: $R + - any: + - follows: + stopBy: end + kind: lexical_declaration + has: + stopBy: end + kind: variable_declarator + all: + - has: + stopBy: end + kind: identifier + pattern: $S + - has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: '^require$' + - has: + stopBy: neighbor + kind: arguments + has: + stopBy: neighbor + kind: string + has: + stopBy: neighbor + kind: string_fragment + regex: '^crypto$' + - follows: + stopBy: end + kind: import_statement + all: + - has: + stopBy: neighbor + kind: import_clause + has: + stopBy: end + kind: namespace_import + has: + stopBy: neighbor + kind: identifier + pattern: $S + - has: + stopBy: end + kind: string + has: + stopBy: neighbor + kind: string_fragment + regex: '^crypto$' + - follows: + stopBy: end + kind: import_statement + all: + - has: + stopBy: neighbor + kind: import_clause + - has: + stopBy: neighbor + kind: string + has: + stopBy: neighbor + kind: string_fragment + regex: '^crypto$' +rule: + kind: number + any: + - matches: MATCH_BITS_DIRECTLY_NODE_FORGE + - matches: MATCH_BITS_DIRECTLY_NODE_RSA + - matches: MATCH_BITS_WITHIN_FUNCTION_WITH_NODE_FORGE + - matches: MATCH_BITS_WITHIN_FUNCTION_WITH_CRYPTO_AND_PROMISIFY + - matches: MATCH_BITS_WITHIN_FUNCTION_WITH_CRYPTO +constraints: + R: + regex: '^(-?(0|[1-9][0-9]?|[1-9][0-9]{2}|1[0-9]{3}|20[0-3][0-9]|204[0-7])(\.[0-9]+)?|0|-[1-9][0-9]*|-[1-9][0-9]{2,}|-1[0-9]{3}|-20[0-3][0-9]|-204[0-7])$' diff --git a/tests/__snapshots__/node-rsa-weak-key-javascript-snapshot.yml b/tests/__snapshots__/node-rsa-weak-key-javascript-snapshot.yml new file mode 100644 index 00000000..294f6721 --- /dev/null +++ b/tests/__snapshots__/node-rsa-weak-key-javascript-snapshot.yml @@ -0,0 +1,498 @@ +id: node-rsa-weak-key-javascript +snapshots: + ? | + const NodeRSA = require('node-rsa'); + const key = new NodeRSA({b: 204}); + : labels: + - source: '204' + style: primary + start: 65 + end: 68 + - source: NodeRSA + style: secondary + start: 53 + end: 60 + - source: b + style: secondary + start: 62 + end: 63 + - source: '204' + style: secondary + start: 65 + end: 68 + - source: 'b: 204' + style: secondary + start: 62 + end: 68 + - source: '{b: 204}' + style: secondary + start: 61 + end: 69 + - source: '({b: 204})' + style: secondary + start: 60 + end: 70 + - source: 'new NodeRSA({b: 204})' + style: secondary + start: 49 + end: 70 + - source: 'key = new NodeRSA({b: 204})' + style: secondary + start: 43 + end: 70 + - source: NodeRSA + style: secondary + start: 6 + end: 13 + - source: require + style: secondary + start: 16 + end: 23 + - source: node-rsa + style: secondary + start: 25 + end: 33 + - source: '''node-rsa''' + style: secondary + start: 24 + end: 34 + - source: ('node-rsa') + style: secondary + start: 23 + end: 35 + - source: require('node-rsa') + style: secondary + start: 16 + end: 35 + - source: NodeRSA = require('node-rsa') + style: secondary + start: 6 + end: 35 + - source: const NodeRSA = require('node-rsa'); + style: secondary + start: 0 + end: 36 + - source: 'const key = new NodeRSA({b: 204});' + style: secondary + start: 37 + end: 71 + ? | + const NodeRSA = require('node-rsa'); + const key = new NodeRSA({b: 512}); + : labels: + - source: '512' + style: primary + start: 65 + end: 68 + - source: NodeRSA + style: secondary + start: 53 + end: 60 + - source: b + style: secondary + start: 62 + end: 63 + - source: '512' + style: secondary + start: 65 + end: 68 + - source: 'b: 512' + style: secondary + start: 62 + end: 68 + - source: '{b: 512}' + style: secondary + start: 61 + end: 69 + - source: '({b: 512})' + style: secondary + start: 60 + end: 70 + - source: 'new NodeRSA({b: 512})' + style: secondary + start: 49 + end: 70 + - source: 'key = new NodeRSA({b: 512})' + style: secondary + start: 43 + end: 70 + - source: NodeRSA + style: secondary + start: 6 + end: 13 + - source: require + style: secondary + start: 16 + end: 23 + - source: node-rsa + style: secondary + start: 25 + end: 33 + - source: '''node-rsa''' + style: secondary + start: 24 + end: 34 + - source: ('node-rsa') + style: secondary + start: 23 + end: 35 + - source: require('node-rsa') + style: secondary + start: 16 + end: 35 + - source: NodeRSA = require('node-rsa') + style: secondary + start: 6 + end: 35 + - source: const NodeRSA = require('node-rsa'); + style: secondary + start: 0 + end: 36 + - source: 'const key = new NodeRSA({b: 512});' + style: secondary + start: 37 + end: 71 + ? | + const crypto = require("crypto"); + const keypair2 = await util.promisify(crypto.generateKeyPair)("rsa", { + modulusLength: 512, + }); + : labels: + - source: '512' + style: primary + start: 120 + end: 123 + - source: promisify + style: secondary + start: 62 + end: 71 + - source: util.promisify + style: secondary + start: 57 + end: 71 + - source: crypto + style: secondary + start: 72 + end: 78 + - source: generateKeyPair + style: secondary + start: 79 + end: 94 + - source: crypto.generateKeyPair + style: secondary + start: 72 + end: 94 + - source: (crypto.generateKeyPair) + style: secondary + start: 71 + end: 95 + - source: util.promisify(crypto.generateKeyPair) + style: secondary + start: 57 + end: 95 + - source: rsa + style: secondary + start: 97 + end: 100 + - source: '"rsa"' + style: secondary + start: 96 + end: 101 + - source: modulusLength + style: secondary + start: 105 + end: 118 + - source: 'modulusLength: 512' + style: secondary + start: 105 + end: 123 + - source: |- + { + modulusLength: 512, + } + style: secondary + start: 103 + end: 126 + - source: |- + ("rsa", { + modulusLength: 512, + }) + style: secondary + start: 95 + end: 127 + - source: |- + util.promisify(crypto.generateKeyPair)("rsa", { + modulusLength: 512, + }) + style: secondary + start: 57 + end: 127 + - source: crypto + style: secondary + start: 6 + end: 12 + - source: require + style: secondary + start: 15 + end: 22 + - source: crypto + style: secondary + start: 24 + end: 30 + - source: '"crypto"' + style: secondary + start: 23 + end: 31 + - source: ("crypto") + style: secondary + start: 22 + end: 32 + - source: require("crypto") + style: secondary + start: 15 + end: 32 + - source: crypto = require("crypto") + style: secondary + start: 6 + end: 32 + - source: const crypto = require("crypto"); + style: secondary + start: 0 + end: 33 + - source: |- + const keypair2 = await util.promisify(crypto.generateKeyPair)("rsa", { + modulusLength: 512, + }); + style: secondary + start: 34 + end: 128 + ? | + const crypto = require("crypto"); + const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", { + a: 123, + modulusLength: 512, + }); + : labels: + - source: '512' + style: primary + start: 127 + end: 130 + - source: crypto + style: secondary + start: 68 + end: 74 + - source: generateKeyPairSync + style: secondary + start: 75 + end: 94 + - source: crypto.generateKeyPairSync + style: secondary + start: 68 + end: 94 + - source: rsa + style: secondary + start: 96 + end: 99 + - source: '"rsa"' + style: secondary + start: 95 + end: 100 + - source: modulusLength + style: secondary + start: 112 + end: 125 + - source: '512' + style: secondary + start: 127 + end: 130 + - source: 'modulusLength: 512' + style: secondary + start: 112 + end: 130 + - source: |- + { + a: 123, + modulusLength: 512, + } + style: secondary + start: 102 + end: 133 + - source: |- + ("rsa", { + a: 123, + modulusLength: 512, + }) + style: secondary + start: 94 + end: 134 + - source: |- + crypto.generateKeyPairSync("rsa", { + a: 123, + modulusLength: 512, + }) + style: secondary + start: 68 + end: 134 + - source: |- + { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", { + a: 123, + modulusLength: 512, + }) + style: secondary + start: 40 + end: 134 + - source: crypto + style: secondary + start: 6 + end: 12 + - source: require + style: secondary + start: 15 + end: 22 + - source: crypto + style: secondary + start: 24 + end: 30 + - source: '"crypto"' + style: secondary + start: 23 + end: 31 + - source: ("crypto") + style: secondary + start: 22 + end: 32 + - source: require("crypto") + style: secondary + start: 15 + end: 32 + - source: crypto = require("crypto") + style: secondary + start: 6 + end: 32 + - source: const crypto = require("crypto"); + style: secondary + start: 0 + end: 33 + - source: |- + const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", { + a: 123, + modulusLength: 512, + }); + style: secondary + start: 34 + end: 135 + ? | + const util = require('util'); + const crypto = require("crypto"); + const keypair2 = await util.promisify(crypto.generateKeyPair)("rsa", { + modulusLength: 512, + }); + : labels: + - source: '512' + style: primary + start: 150 + end: 153 + - source: promisify + style: secondary + start: 92 + end: 101 + - source: util.promisify + style: secondary + start: 87 + end: 101 + - source: crypto + style: secondary + start: 102 + end: 108 + - source: generateKeyPair + style: secondary + start: 109 + end: 124 + - source: crypto.generateKeyPair + style: secondary + start: 102 + end: 124 + - source: (crypto.generateKeyPair) + style: secondary + start: 101 + end: 125 + - source: util.promisify(crypto.generateKeyPair) + style: secondary + start: 87 + end: 125 + - source: rsa + style: secondary + start: 127 + end: 130 + - source: '"rsa"' + style: secondary + start: 126 + end: 131 + - source: modulusLength + style: secondary + start: 135 + end: 148 + - source: 'modulusLength: 512' + style: secondary + start: 135 + end: 153 + - source: |- + { + modulusLength: 512, + } + style: secondary + start: 133 + end: 156 + - source: |- + ("rsa", { + modulusLength: 512, + }) + style: secondary + start: 125 + end: 157 + - source: |- + util.promisify(crypto.generateKeyPair)("rsa", { + modulusLength: 512, + }) + style: secondary + start: 87 + end: 157 + - source: crypto + style: secondary + start: 36 + end: 42 + - source: require + style: secondary + start: 45 + end: 52 + - source: crypto + style: secondary + start: 54 + end: 60 + - source: '"crypto"' + style: secondary + start: 53 + end: 61 + - source: ("crypto") + style: secondary + start: 52 + end: 62 + - source: require("crypto") + style: secondary + start: 45 + end: 62 + - source: crypto = require("crypto") + style: secondary + start: 36 + end: 62 + - source: const crypto = require("crypto"); + style: secondary + start: 30 + end: 63 + - source: |- + const keypair2 = await util.promisify(crypto.generateKeyPair)("rsa", { + modulusLength: 512, + }); + style: secondary + start: 64 + end: 158 diff --git a/tests/javascript/node-rsa-weak-key-javascript-test.yml b/tests/javascript/node-rsa-weak-key-javascript-test.yml new file mode 100644 index 00000000..35f3257f --- /dev/null +++ b/tests/javascript/node-rsa-weak-key-javascript-test.yml @@ -0,0 +1,24 @@ +id: node-rsa-weak-key-javascript +valid: + - | + const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", { + modulusLength: 2048, + }); +invalid: + - | + const crypto = require("crypto"); + const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", { + a: 123, + modulusLength: 512, + }); + - | + const NodeRSA = require('node-rsa'); + const key = new NodeRSA({b: 204}); + - | + const NodeRSA = require('node-rsa'); + const key = new NodeRSA({b: 512}); + - | + const crypto = require("crypto"); + const keypair2 = await util.promisify(crypto.generateKeyPair)("rsa", { + modulusLength: 512, + }); From adf53d2fed6051cd758d3778e599cd3506593492 Mon Sep 17 00:00:00 2001 From: Sakshis Date: Wed, 18 Dec 2024 06:53:46 +0000 Subject: [PATCH 3/3] modification in node-rsa-weak-key-javascript --- .../security/node-rsa-weak-key-javascript.yml | 11 ++++++++--- .../node-rsa-weak-key-javascript-snapshot.yml | 4 ++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/rules/javascript/security/node-rsa-weak-key-javascript.yml b/rules/javascript/security/node-rsa-weak-key-javascript.yml index 870c1de0..acd4b73a 100644 --- a/rules/javascript/security/node-rsa-weak-key-javascript.yml +++ b/rules/javascript/security/node-rsa-weak-key-javascript.yml @@ -162,7 +162,7 @@ utils: stopBy: neighbor kind: property_identifier - has: - stopBy: neighbor + stopBy: end kind: number - any: - follows: @@ -382,6 +382,9 @@ utils: stopBy: end kind: property_identifier regex: '^modulusLength$' + - has: + stopBy: end + kind: number - any: - follows: stopBy: end @@ -495,7 +498,7 @@ utils: kind: property_identifier regex: '^modulusLength$' - has: - stopBy: neighbor + stopBy: end kind: number pattern: $R - any: @@ -571,6 +574,8 @@ rule: - matches: MATCH_BITS_WITHIN_FUNCTION_WITH_NODE_FORGE - matches: MATCH_BITS_WITHIN_FUNCTION_WITH_CRYPTO_AND_PROMISIFY - matches: MATCH_BITS_WITHIN_FUNCTION_WITH_CRYPTO + + constraints: R: - regex: '^(-?(0|[1-9][0-9]?|[1-9][0-9]{2}|1[0-9]{3}|20[0-3][0-9]|204[0-7])(\.[0-9]+)?|0|-[1-9][0-9]*|-[1-9][0-9]{2,}|-1[0-9]{3}|-20[0-3][0-9]|-204[0-7])$' + regex: ^(-?(0|[1-9][0-9]{0,2}|1[0-9]{3}|20[0-3][0-9]|204[0-7])(\.[0-9]+)?)$ diff --git a/tests/__snapshots__/node-rsa-weak-key-javascript-snapshot.yml b/tests/__snapshots__/node-rsa-weak-key-javascript-snapshot.yml index 294f6721..6be84b43 100644 --- a/tests/__snapshots__/node-rsa-weak-key-javascript-snapshot.yml +++ b/tests/__snapshots__/node-rsa-weak-key-javascript-snapshot.yml @@ -202,6 +202,10 @@ snapshots: style: secondary start: 105 end: 118 + - source: '512' + style: secondary + start: 120 + end: 123 - source: 'modulusLength: 512' style: secondary start: 105