@trust-assurance-protocol/owaspscan 1.0.0

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.
Files changed (221) hide show
  1. package/dist/analysis/ast-analyzer.d.ts +13 -0
  2. package/dist/analysis/ast-analyzer.d.ts.map +1 -0
  3. package/dist/analysis/ast-analyzer.js +58 -0
  4. package/dist/analysis/ast-analyzer.js.map +1 -0
  5. package/dist/analysis/llm-verifier.d.ts +17 -0
  6. package/dist/analysis/llm-verifier.d.ts.map +1 -0
  7. package/dist/analysis/llm-verifier.js +152 -0
  8. package/dist/analysis/llm-verifier.js.map +1 -0
  9. package/dist/analysis/result-cache.d.ts +20 -0
  10. package/dist/analysis/result-cache.d.ts.map +1 -0
  11. package/dist/analysis/result-cache.js +70 -0
  12. package/dist/analysis/result-cache.js.map +1 -0
  13. package/dist/analysis/sinks.d.ts +12 -0
  14. package/dist/analysis/sinks.d.ts.map +1 -0
  15. package/dist/analysis/sinks.js +142 -0
  16. package/dist/analysis/sinks.js.map +1 -0
  17. package/dist/analysis/sources.d.ts +8 -0
  18. package/dist/analysis/sources.d.ts.map +1 -0
  19. package/dist/analysis/sources.js +114 -0
  20. package/dist/analysis/sources.js.map +1 -0
  21. package/dist/analysis/taint-engine.d.ts +5 -0
  22. package/dist/analysis/taint-engine.d.ts.map +1 -0
  23. package/dist/analysis/taint-engine.js +187 -0
  24. package/dist/analysis/taint-engine.js.map +1 -0
  25. package/dist/cli/index.d.ts +3 -0
  26. package/dist/cli/index.d.ts.map +1 -0
  27. package/dist/cli/index.js +227 -0
  28. package/dist/cli/index.js.map +1 -0
  29. package/dist/config/loader.d.ts +10 -0
  30. package/dist/config/loader.d.ts.map +1 -0
  31. package/dist/config/loader.js +81 -0
  32. package/dist/config/loader.js.map +1 -0
  33. package/dist/config/schema.d.ts +23 -0
  34. package/dist/config/schema.d.ts.map +1 -0
  35. package/dist/config/schema.js +17 -0
  36. package/dist/config/schema.js.map +1 -0
  37. package/dist/mcp/server.d.ts +2 -0
  38. package/dist/mcp/server.d.ts.map +1 -0
  39. package/dist/mcp/server.js +250 -0
  40. package/dist/mcp/server.js.map +1 -0
  41. package/dist/parsers/ast-parser.d.ts +38 -0
  42. package/dist/parsers/ast-parser.d.ts.map +1 -0
  43. package/dist/parsers/ast-parser.js +88 -0
  44. package/dist/parsers/ast-parser.js.map +1 -0
  45. package/dist/parsers/ast-queries.d.ts +63 -0
  46. package/dist/parsers/ast-queries.d.ts.map +1 -0
  47. package/dist/parsers/ast-queries.js +580 -0
  48. package/dist/parsers/ast-queries.js.map +1 -0
  49. package/dist/reporter/console.d.ts +8 -0
  50. package/dist/reporter/console.d.ts.map +1 -0
  51. package/dist/reporter/console.js +143 -0
  52. package/dist/reporter/console.js.map +1 -0
  53. package/dist/reporter/json.d.ts +3 -0
  54. package/dist/reporter/json.d.ts.map +1 -0
  55. package/dist/reporter/json.js +7 -0
  56. package/dist/reporter/json.js.map +1 -0
  57. package/dist/reporter/llm.d.ts +3 -0
  58. package/dist/reporter/llm.d.ts.map +1 -0
  59. package/dist/reporter/llm.js +66 -0
  60. package/dist/reporter/llm.js.map +1 -0
  61. package/dist/reporter/sarif.d.ts +3 -0
  62. package/dist/reporter/sarif.d.ts.map +1 -0
  63. package/dist/reporter/sarif.js +110 -0
  64. package/dist/reporter/sarif.js.map +1 -0
  65. package/dist/rules/owasp-a01/idor.d.ts +3 -0
  66. package/dist/rules/owasp-a01/idor.d.ts.map +1 -0
  67. package/dist/rules/owasp-a01/idor.js +48 -0
  68. package/dist/rules/owasp-a01/idor.js.map +1 -0
  69. package/dist/rules/owasp-a01/missing-auth-middleware.d.ts +3 -0
  70. package/dist/rules/owasp-a01/missing-auth-middleware.d.ts.map +1 -0
  71. package/dist/rules/owasp-a01/missing-auth-middleware.js +41 -0
  72. package/dist/rules/owasp-a01/missing-auth-middleware.js.map +1 -0
  73. package/dist/rules/owasp-a01/path-traversal.d.ts +3 -0
  74. package/dist/rules/owasp-a01/path-traversal.d.ts.map +1 -0
  75. package/dist/rules/owasp-a01/path-traversal.js +73 -0
  76. package/dist/rules/owasp-a01/path-traversal.js.map +1 -0
  77. package/dist/rules/owasp-a02/hardcoded-secrets.d.ts +3 -0
  78. package/dist/rules/owasp-a02/hardcoded-secrets.d.ts.map +1 -0
  79. package/dist/rules/owasp-a02/hardcoded-secrets.js +97 -0
  80. package/dist/rules/owasp-a02/hardcoded-secrets.js.map +1 -0
  81. package/dist/rules/owasp-a02/insecure-tls.d.ts +3 -0
  82. package/dist/rules/owasp-a02/insecure-tls.d.ts.map +1 -0
  83. package/dist/rules/owasp-a02/insecure-tls.js +75 -0
  84. package/dist/rules/owasp-a02/insecure-tls.js.map +1 -0
  85. package/dist/rules/owasp-a02/weak-hash.d.ts +3 -0
  86. package/dist/rules/owasp-a02/weak-hash.d.ts.map +1 -0
  87. package/dist/rules/owasp-a02/weak-hash.js +73 -0
  88. package/dist/rules/owasp-a02/weak-hash.js.map +1 -0
  89. package/dist/rules/owasp-a02/weak-random.d.ts +3 -0
  90. package/dist/rules/owasp-a02/weak-random.d.ts.map +1 -0
  91. package/dist/rules/owasp-a02/weak-random.js +70 -0
  92. package/dist/rules/owasp-a02/weak-random.js.map +1 -0
  93. package/dist/rules/owasp-a03/command-injection.d.ts +3 -0
  94. package/dist/rules/owasp-a03/command-injection.d.ts.map +1 -0
  95. package/dist/rules/owasp-a03/command-injection.js +79 -0
  96. package/dist/rules/owasp-a03/command-injection.js.map +1 -0
  97. package/dist/rules/owasp-a03/ldap-injection.d.ts +3 -0
  98. package/dist/rules/owasp-a03/ldap-injection.d.ts.map +1 -0
  99. package/dist/rules/owasp-a03/ldap-injection.js +56 -0
  100. package/dist/rules/owasp-a03/ldap-injection.js.map +1 -0
  101. package/dist/rules/owasp-a03/nosql-injection.d.ts +3 -0
  102. package/dist/rules/owasp-a03/nosql-injection.d.ts.map +1 -0
  103. package/dist/rules/owasp-a03/nosql-injection.js +61 -0
  104. package/dist/rules/owasp-a03/nosql-injection.js.map +1 -0
  105. package/dist/rules/owasp-a03/sql-injection.d.ts +3 -0
  106. package/dist/rules/owasp-a03/sql-injection.d.ts.map +1 -0
  107. package/dist/rules/owasp-a03/sql-injection.js +88 -0
  108. package/dist/rules/owasp-a03/sql-injection.js.map +1 -0
  109. package/dist/rules/owasp-a03/template-injection.d.ts +3 -0
  110. package/dist/rules/owasp-a03/template-injection.d.ts.map +1 -0
  111. package/dist/rules/owasp-a03/template-injection.js +64 -0
  112. package/dist/rules/owasp-a03/template-injection.js.map +1 -0
  113. package/dist/rules/owasp-a03/xss.d.ts +3 -0
  114. package/dist/rules/owasp-a03/xss.d.ts.map +1 -0
  115. package/dist/rules/owasp-a03/xss.js +74 -0
  116. package/dist/rules/owasp-a03/xss.js.map +1 -0
  117. package/dist/rules/owasp-a04/mass-assignment.d.ts +3 -0
  118. package/dist/rules/owasp-a04/mass-assignment.d.ts.map +1 -0
  119. package/dist/rules/owasp-a04/mass-assignment.js +63 -0
  120. package/dist/rules/owasp-a04/mass-assignment.js.map +1 -0
  121. package/dist/rules/owasp-a04/missing-rate-limit.d.ts +3 -0
  122. package/dist/rules/owasp-a04/missing-rate-limit.d.ts.map +1 -0
  123. package/dist/rules/owasp-a04/missing-rate-limit.js +48 -0
  124. package/dist/rules/owasp-a04/missing-rate-limit.js.map +1 -0
  125. package/dist/rules/owasp-a05/cors-wildcard.d.ts +3 -0
  126. package/dist/rules/owasp-a05/cors-wildcard.d.ts.map +1 -0
  127. package/dist/rules/owasp-a05/cors-wildcard.js +79 -0
  128. package/dist/rules/owasp-a05/cors-wildcard.js.map +1 -0
  129. package/dist/rules/owasp-a05/debug-mode.d.ts +3 -0
  130. package/dist/rules/owasp-a05/debug-mode.d.ts.map +1 -0
  131. package/dist/rules/owasp-a05/debug-mode.js +73 -0
  132. package/dist/rules/owasp-a05/debug-mode.js.map +1 -0
  133. package/dist/rules/owasp-a05/default-credentials.d.ts +3 -0
  134. package/dist/rules/owasp-a05/default-credentials.d.ts.map +1 -0
  135. package/dist/rules/owasp-a05/default-credentials.js +52 -0
  136. package/dist/rules/owasp-a05/default-credentials.js.map +1 -0
  137. package/dist/rules/owasp-a05/error-disclosure.d.ts +3 -0
  138. package/dist/rules/owasp-a05/error-disclosure.d.ts.map +1 -0
  139. package/dist/rules/owasp-a05/error-disclosure.js +70 -0
  140. package/dist/rules/owasp-a05/error-disclosure.js.map +1 -0
  141. package/dist/rules/owasp-a06/outdated-packages.d.ts +3 -0
  142. package/dist/rules/owasp-a06/outdated-packages.d.ts.map +1 -0
  143. package/dist/rules/owasp-a06/outdated-packages.js +75 -0
  144. package/dist/rules/owasp-a06/outdated-packages.js.map +1 -0
  145. package/dist/rules/owasp-a07/insecure-cookies.d.ts +3 -0
  146. package/dist/rules/owasp-a07/insecure-cookies.d.ts.map +1 -0
  147. package/dist/rules/owasp-a07/insecure-cookies.js +64 -0
  148. package/dist/rules/owasp-a07/insecure-cookies.js.map +1 -0
  149. package/dist/rules/owasp-a07/jwt-none-alg.d.ts +3 -0
  150. package/dist/rules/owasp-a07/jwt-none-alg.d.ts.map +1 -0
  151. package/dist/rules/owasp-a07/jwt-none-alg.js +81 -0
  152. package/dist/rules/owasp-a07/jwt-none-alg.js.map +1 -0
  153. package/dist/rules/owasp-a07/no-password-hashing.d.ts +3 -0
  154. package/dist/rules/owasp-a07/no-password-hashing.d.ts.map +1 -0
  155. package/dist/rules/owasp-a07/no-password-hashing.js +70 -0
  156. package/dist/rules/owasp-a07/no-password-hashing.js.map +1 -0
  157. package/dist/rules/owasp-a07/weak-session.d.ts +3 -0
  158. package/dist/rules/owasp-a07/weak-session.d.ts.map +1 -0
  159. package/dist/rules/owasp-a07/weak-session.js +64 -0
  160. package/dist/rules/owasp-a07/weak-session.js.map +1 -0
  161. package/dist/rules/owasp-a08/unsafe-deserialization.d.ts +3 -0
  162. package/dist/rules/owasp-a08/unsafe-deserialization.d.ts.map +1 -0
  163. package/dist/rules/owasp-a08/unsafe-deserialization.js +78 -0
  164. package/dist/rules/owasp-a08/unsafe-deserialization.js.map +1 -0
  165. package/dist/rules/owasp-a08/unsafe-eval.d.ts +3 -0
  166. package/dist/rules/owasp-a08/unsafe-eval.d.ts.map +1 -0
  167. package/dist/rules/owasp-a08/unsafe-eval.js +73 -0
  168. package/dist/rules/owasp-a08/unsafe-eval.js.map +1 -0
  169. package/dist/rules/owasp-a09/log-sensitive-data.d.ts +3 -0
  170. package/dist/rules/owasp-a09/log-sensitive-data.d.ts.map +1 -0
  171. package/dist/rules/owasp-a09/log-sensitive-data.js +73 -0
  172. package/dist/rules/owasp-a09/log-sensitive-data.js.map +1 -0
  173. package/dist/rules/owasp-a09/missing-error-handling.d.ts +3 -0
  174. package/dist/rules/owasp-a09/missing-error-handling.d.ts.map +1 -0
  175. package/dist/rules/owasp-a09/missing-error-handling.js +84 -0
  176. package/dist/rules/owasp-a09/missing-error-handling.js.map +1 -0
  177. package/dist/rules/owasp-a10/open-redirect.d.ts +3 -0
  178. package/dist/rules/owasp-a10/open-redirect.d.ts.map +1 -0
  179. package/dist/rules/owasp-a10/open-redirect.js +67 -0
  180. package/dist/rules/owasp-a10/open-redirect.js.map +1 -0
  181. package/dist/rules/owasp-a10/unvalidated-fetch.d.ts +3 -0
  182. package/dist/rules/owasp-a10/unvalidated-fetch.d.ts.map +1 -0
  183. package/dist/rules/owasp-a10/unvalidated-fetch.js +85 -0
  184. package/dist/rules/owasp-a10/unvalidated-fetch.js.map +1 -0
  185. package/dist/rules/registry.d.ts +20 -0
  186. package/dist/rules/registry.d.ts.map +1 -0
  187. package/dist/rules/registry.js +142 -0
  188. package/dist/rules/registry.js.map +1 -0
  189. package/dist/scanner/engine.d.ts +21 -0
  190. package/dist/scanner/engine.d.ts.map +1 -0
  191. package/dist/scanner/engine.js +260 -0
  192. package/dist/scanner/engine.js.map +1 -0
  193. package/dist/scanner/file-walker.d.ts +7 -0
  194. package/dist/scanner/file-walker.d.ts.map +1 -0
  195. package/dist/scanner/file-walker.js +81 -0
  196. package/dist/scanner/file-walker.js.map +1 -0
  197. package/dist/scanner/language-detect.d.ts +5 -0
  198. package/dist/scanner/language-detect.d.ts.map +1 -0
  199. package/dist/scanner/language-detect.js +91 -0
  200. package/dist/scanner/language-detect.js.map +1 -0
  201. package/dist/scanner/sca-scanner.d.ts +38 -0
  202. package/dist/scanner/sca-scanner.d.ts.map +1 -0
  203. package/dist/scanner/sca-scanner.js +223 -0
  204. package/dist/scanner/sca-scanner.js.map +1 -0
  205. package/dist/types/index.d.ts +114 -0
  206. package/dist/types/index.d.ts.map +1 -0
  207. package/dist/types/index.js +25 -0
  208. package/dist/types/index.js.map +1 -0
  209. package/dist/utils/pattern-matcher.d.ts +4 -0
  210. package/dist/utils/pattern-matcher.d.ts.map +1 -0
  211. package/dist/utils/pattern-matcher.js +72 -0
  212. package/dist/utils/pattern-matcher.js.map +1 -0
  213. package/dist/utils/scoring.d.ts +8 -0
  214. package/dist/utils/scoring.d.ts.map +1 -0
  215. package/dist/utils/scoring.js +76 -0
  216. package/dist/utils/scoring.js.map +1 -0
  217. package/dist/utils/suppression.d.ts +3 -0
  218. package/dist/utils/suppression.d.ts.map +1 -0
  219. package/dist/utils/suppression.js +33 -0
  220. package/dist/utils/suppression.js.map +1 -0
  221. package/package.json +94 -0
@@ -0,0 +1,78 @@
1
+ // OWASP A08:2021 — Software and Data Integrity Failures
2
+ // Rule: Unsafe deserialization of untrusted data
3
+ export const UnsafeDeserialization = {
4
+ id: 'OWASP-A08-002',
5
+ name: 'Unsafe Deserialization of Untrusted Data',
6
+ owasp: 'A08:2021',
7
+ cwe: 'CWE-502',
8
+ severity: 'CRITICAL',
9
+ languages: ['javascript', 'typescript', 'python', 'java', 'php', 'ruby'],
10
+ description: 'Deserializing objects from untrusted sources (request body, cookies, network) ' +
11
+ 'using formats that support class instantiation (pickle, PHP serialize, Java ObjectInputStream, ' +
12
+ 'node-serialize). Attackers craft payloads that execute code during deserialization.',
13
+ patterns: [
14
+ {
15
+ // Python pickle.loads with untrusted data
16
+ pattern: /pickle\s*\.\s*(?:loads|load)\s*\(\s*(?:request\.|req\.|data\.|body\.|socket\.|recv)/gi,
17
+ snippetLines: 3,
18
+ },
19
+ {
20
+ // Python pickle.loads from base64-decoded user data
21
+ pattern: /pickle\s*\.\s*loads\s*\(\s*(?:base64\.b64decode|b64decode)\s*\(/gi,
22
+ requiresContext: /(?:request\.|req\.|cookie|header|data|body|input)/i,
23
+ snippetLines: 5,
24
+ },
25
+ {
26
+ // PHP: unserialize with user input
27
+ pattern: /unserialize\s*\(\s*\$_(?:GET|POST|REQUEST|COOKIE|SESSION)\s*\[/gi,
28
+ snippetLines: 3,
29
+ },
30
+ {
31
+ // Java: ObjectInputStream.readObject with untrusted data
32
+ pattern: /new\s+ObjectInputStream\s*\(\s*(?:socket|request|connection|input)\.getInputStream/gi,
33
+ snippetLines: 3,
34
+ },
35
+ {
36
+ // Java: XMLDecoder with user input
37
+ pattern: /new\s+XMLDecoder\s*\(\s*(?!.*ResourceBundle)/gi,
38
+ requiresContext: /(?:request|socket|stream|input|data)/i,
39
+ snippetLines: 5,
40
+ },
41
+ {
42
+ // Node.js: node-serialize
43
+ pattern: /(?:require|import)\s*\(\s*['"`]node-serialize['"`]\s*\)/gi,
44
+ snippetLines: 1,
45
+ },
46
+ {
47
+ // Ruby: Marshal.load with user data
48
+ pattern: /Marshal\s*\.\s*load\s*\(\s*(?:params|request\.|cookie|Base64\.decode|data)/gi,
49
+ snippetLines: 3,
50
+ },
51
+ ],
52
+ fix: 'Avoid serialization formats that support object instantiation (pickle, PHP serialize, Java ObjectInputStream).\n\n' +
53
+ '// Use safe alternatives:\n' +
54
+ '// JSON (no code execution, only data):\n' +
55
+ 'const data = JSON.parse(req.body); // safe — JSON is data-only\n\n' +
56
+ '// Python — use JSON instead of pickle:\n' +
57
+ 'import json\n' +
58
+ 'data = json.loads(request.data) # safe — no code execution\n\n' +
59
+ '// If you must use pickle (internal only):\n' +
60
+ '# Use cryptographic MAC to verify data integrity before deserializing:\n' +
61
+ 'import hmac, hashlib, pickle\n' +
62
+ 'def safe_loads(data: bytes, secret: bytes) -> object:\n' +
63
+ ' mac, payload = data[:32], data[32:]\n' +
64
+ ' expected = hmac.new(secret, payload, hashlib.sha256).digest()\n' +
65
+ ' if not hmac.compare_digest(mac, expected):\n' +
66
+ ' raise ValueError("Data integrity check failed")\n' +
67
+ ' return pickle.loads(payload)\n\n' +
68
+ '// Java — use JSON (Jackson/Gson) with type allowlisting:\n' +
69
+ 'ObjectMapper mapper = new ObjectMapper();\n' +
70
+ 'mapper.activateDefaultTyping(PTF, ObjectMapper.DefaultTyping.NON_FINAL);',
71
+ references: [
72
+ 'https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures/',
73
+ 'https://cwe.mitre.org/data/definitions/502.html',
74
+ 'https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html',
75
+ ],
76
+ tags: ['deserialization', 'pickle', 'integrity', 'rce', 'object-injection'],
77
+ };
78
+ //# sourceMappingURL=unsafe-deserialization.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unsafe-deserialization.js","sourceRoot":"","sources":["../../../src/rules/owasp-a08/unsafe-deserialization.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,iDAAiD;AAIjD,MAAM,CAAC,MAAM,qBAAqB,GAAS;IACzC,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,0CAA0C;IAChD,KAAK,EAAE,UAAU;IACjB,GAAG,EAAE,SAAS;IACd,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC;IACxE,WAAW,EACT,gFAAgF;QAChF,iGAAiG;QACjG,qFAAqF;IACvF,QAAQ,EAAE;QACR;YACE,0CAA0C;YAC1C,OAAO,EACL,uFAAuF;YACzF,YAAY,EAAE,CAAC;SAChB;QACD;YACE,oDAAoD;YACpD,OAAO,EACL,mEAAmE;YACrE,eAAe,EAAE,oDAAoD;YACrE,YAAY,EAAE,CAAC;SAChB;QACD;YACE,mCAAmC;YACnC,OAAO,EACL,kEAAkE;YACpE,YAAY,EAAE,CAAC;SAChB;QACD;YACE,yDAAyD;YACzD,OAAO,EACL,sFAAsF;YACxF,YAAY,EAAE,CAAC;SAChB;QACD;YACE,mCAAmC;YACnC,OAAO,EACL,gDAAgD;YAClD,eAAe,EAAE,uCAAuC;YACxD,YAAY,EAAE,CAAC;SAChB;QACD;YACE,0BAA0B;YAC1B,OAAO,EAAE,2DAA2D;YACpE,YAAY,EAAE,CAAC;SAChB;QACD;YACE,oCAAoC;YACpC,OAAO,EACL,8EAA8E;YAChF,YAAY,EAAE,CAAC;SAChB;KACF;IACD,GAAG,EACD,oHAAoH;QACpH,6BAA6B;QAC7B,2CAA2C;QAC3C,oEAAoE;QACpE,2CAA2C;QAC3C,eAAe;QACf,iEAAiE;QACjE,8CAA8C;QAC9C,0EAA0E;QAC1E,gCAAgC;QAChC,yDAAyD;QACzD,2CAA2C;QAC3C,qEAAqE;QACrE,kDAAkD;QAClD,2DAA2D;QAC3D,sCAAsC;QACtC,6DAA6D;QAC7D,6CAA6C;QAC7C,0EAA0E;IAC5E,UAAU,EAAE;QACV,wEAAwE;QACxE,iDAAiD;QACjD,iFAAiF;KAClF;IACD,IAAI,EAAE,CAAC,iBAAiB,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,kBAAkB,CAAC;CAC5E,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Rule } from '../../types/index.js';
2
+ export declare const UnsafeEval: Rule;
3
+ //# sourceMappingURL=unsafe-eval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unsafe-eval.d.ts","sourceRoot":"","sources":["../../../src/rules/owasp-a08/unsafe-eval.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAEjD,eAAO,MAAM,UAAU,EAAE,IA2ExB,CAAC"}
@@ -0,0 +1,73 @@
1
+ // OWASP A08:2021 — Software and Data Integrity Failures
2
+ // Rule: eval() / Function() constructor with dynamic/user content
3
+ export const UnsafeEval = {
4
+ id: 'OWASP-A08-001',
5
+ name: 'Unsafe Use of eval() or Dynamic Code Execution',
6
+ owasp: 'A08:2021',
7
+ cwe: 'CWE-95',
8
+ severity: 'CRITICAL',
9
+ languages: ['javascript', 'typescript', 'python', 'ruby', 'php'],
10
+ description: 'eval(), new Function(), or exec() used to evaluate user-controlled or externally-sourced ' +
11
+ 'strings as code. This enables arbitrary code execution on the server or client. ' +
12
+ 'AI tools sometimes suggest eval() for JSON parsing or dynamic property access.',
13
+ patterns: [
14
+ {
15
+ // JS: eval() with any non-literal argument
16
+ pattern: /\beval\s*\(\s*(?!['"`][^'"`]*['"`]\s*\))/gi,
17
+ snippetLines: 3,
18
+ },
19
+ {
20
+ // JS: new Function() constructor with user input
21
+ pattern: /new\s+Function\s*\([^)]*(?:req\.|request\.|input\.|user\.|data\.|\+\s*\w)/gi,
22
+ snippetLines: 3,
23
+ },
24
+ {
25
+ // JS: setTimeout/setInterval with string (deprecated, evaluates as eval)
26
+ pattern: /(?:setTimeout|setInterval)\s*\(\s*(?:['"`][^'"`]*['"`]\s*\+|`[^`]*\$\{)/gi,
27
+ snippetLines: 3,
28
+ },
29
+ {
30
+ // Python: exec() / eval() with user input
31
+ pattern: /\b(?:exec|eval)\s*\(\s*(?:request\.|req\.|input\.|data\.|user\.)/gi,
32
+ snippetLines: 3,
33
+ },
34
+ {
35
+ // Python: exec() with string concatenation
36
+ pattern: /\bexec\s*\(\s*['"`][^'"`]*['"`]\s*\+/gi,
37
+ snippetLines: 3,
38
+ },
39
+ {
40
+ // PHP: eval() — almost always dangerous
41
+ pattern: /\beval\s*\(\s*\$/gi,
42
+ snippetLines: 3,
43
+ },
44
+ {
45
+ // Ruby: eval / instance_eval with user input
46
+ pattern: /\beval\s*\(\s*(?:params|request\.|req\.)/gi,
47
+ snippetLines: 3,
48
+ },
49
+ ],
50
+ fix: 'Avoid eval() and dynamic code execution entirely.\n\n' +
51
+ '// BAD — JSON parsing with eval:\n' +
52
+ 'const data = eval("(" + jsonString + ")");\n\n' +
53
+ '// GOOD:\n' +
54
+ 'const data = JSON.parse(jsonString); // throws on invalid JSON\n\n' +
55
+ '// BAD — dynamic property access:\n' +
56
+ 'eval(`obj.${userProperty} = value`);\n\n' +
57
+ '// GOOD:\n' +
58
+ 'const ALLOWED_PROPS = ["name", "email"]; // whitelist\n' +
59
+ 'if (ALLOWED_PROPS.includes(userProperty)) {\n' +
60
+ ' obj[userProperty] = value;\n' +
61
+ '}\n\n' +
62
+ '// Python — never exec user input:\n' +
63
+ '# Use ast.literal_eval() for safe evaluation of literals:\n' +
64
+ 'import ast\n' +
65
+ 'value = ast.literal_eval(user_string) # only allows literals, not expressions',
66
+ references: [
67
+ 'https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures/',
68
+ 'https://cwe.mitre.org/data/definitions/95.html',
69
+ 'https://cheatsheetseries.owasp.org/cheatsheets/Injection_Prevention_Cheat_Sheet.html',
70
+ ],
71
+ tags: ['eval', 'code-injection', 'rce', 'integrity'],
72
+ };
73
+ //# sourceMappingURL=unsafe-eval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unsafe-eval.js","sourceRoot":"","sources":["../../../src/rules/owasp-a08/unsafe-eval.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,kEAAkE;AAIlE,MAAM,CAAC,MAAM,UAAU,GAAS;IAC9B,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,gDAAgD;IACtD,KAAK,EAAE,UAAU;IACjB,GAAG,EAAE,QAAQ;IACb,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC;IAChE,WAAW,EACT,2FAA2F;QAC3F,kFAAkF;QAClF,gFAAgF;IAClF,QAAQ,EAAE;QACR;YACE,2CAA2C;YAC3C,OAAO,EAAE,4CAA4C;YACrD,YAAY,EAAE,CAAC;SAChB;QACD;YACE,iDAAiD;YACjD,OAAO,EACL,6EAA6E;YAC/E,YAAY,EAAE,CAAC;SAChB;QACD;YACE,yEAAyE;YACzE,OAAO,EACL,2EAA2E;YAC7E,YAAY,EAAE,CAAC;SAChB;QACD;YACE,0CAA0C;YAC1C,OAAO,EACL,oEAAoE;YACtE,YAAY,EAAE,CAAC;SAChB;QACD;YACE,2CAA2C;YAC3C,OAAO,EAAE,wCAAwC;YACjD,YAAY,EAAE,CAAC;SAChB;QACD;YACE,wCAAwC;YACxC,OAAO,EAAE,oBAAoB;YAC7B,YAAY,EAAE,CAAC;SAChB;QACD;YACE,6CAA6C;YAC7C,OAAO,EACL,4CAA4C;YAC9C,YAAY,EAAE,CAAC;SAChB;KACF;IACD,GAAG,EACD,uDAAuD;QACvD,oCAAoC;QACpC,gDAAgD;QAChD,YAAY;QACZ,oEAAoE;QACpE,qCAAqC;QACrC,0CAA0C;QAC1C,YAAY;QACZ,yDAAyD;QACzD,+CAA+C;QAC/C,gCAAgC;QAChC,OAAO;QACP,sCAAsC;QACtC,6DAA6D;QAC7D,cAAc;QACd,gFAAgF;IAClF,UAAU,EAAE;QACV,wEAAwE;QACxE,gDAAgD;QAChD,sFAAsF;KACvF;IACD,IAAI,EAAE,CAAC,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,WAAW,CAAC;CACrD,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Rule } from '../../types/index.js';
2
+ export declare const LogSensitiveData: Rule;
3
+ //# sourceMappingURL=log-sensitive-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-sensitive-data.d.ts","sourceRoot":"","sources":["../../../src/rules/owasp-a09/log-sensitive-data.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAEjD,eAAO,MAAM,gBAAgB,EAAE,IA6E9B,CAAC"}
@@ -0,0 +1,73 @@
1
+ // OWASP A09:2021 — Security Logging and Monitoring Failures
2
+ // Rule: Sensitive data (passwords, tokens, PII) written to logs
3
+ export const LogSensitiveData = {
4
+ id: 'OWASP-A09-001',
5
+ name: 'Sensitive Data Logged to Console or Log Files',
6
+ owasp: 'A09:2021',
7
+ cwe: 'CWE-532',
8
+ severity: 'HIGH',
9
+ languages: ['javascript', 'typescript', 'python', 'java', 'go', 'ruby', 'php'],
10
+ description: 'Passwords, tokens, credit card numbers, social security numbers, or full request bodies ' +
11
+ 'with sensitive fields logged to console or log files. Log files are often stored insecurely, ' +
12
+ 'forwarded to third-party logging services, or accessible to operations staff. ' +
13
+ 'AI tools routinely log entire request objects for debugging.',
14
+ patterns: [
15
+ {
16
+ // console.log with sensitive variable names.
17
+ // [^)'"`]* stops at any quote character so we don't match keywords that
18
+ // appear only inside string/template-literal labels like console.log("Key count:", n).
19
+ // Only matches when the sensitive word appears as an identifier in the argument.
20
+ pattern: /console\s*\.\s*(?:log|debug|info|warn|error)\s*\([^)'"`]*(?:password|passwd|pwd|secret|token|apiKey|privateKey|accessKey|secretKey|authToken|bearerToken|ssn|cvv|credit_card|creditCard|authorization)/gi,
21
+ snippetLines: 3,
22
+ },
23
+ {
24
+ // Logging entire req.body (may contain passwords)
25
+ pattern: /(?:console|logger|log)\s*\.\s*(?:log|debug|info)\s*\([^)'"`]*req\s*\.\s*body\s*\)/gi,
26
+ snippetLines: 3,
27
+ },
28
+ {
29
+ // Python logging sensitive fields — stop at quotes to avoid matching string labels
30
+ pattern: /(?:logging|logger)\s*\.\s*(?:debug|info|warning|error|critical)\s*\([^)'"`]*(?:password|passwd|token|secret|apiKey|privateKey|ssn|cvv)/gi,
31
+ snippetLines: 3,
32
+ },
33
+ {
34
+ // Python print with sensitive data — require identifier context, not string label
35
+ pattern: /\bprint\s*\([^)'"`]*(?:password|passwd|token|secret|apiKey|privateKey|ssn|cvv|credit_card)\s*(?:=|,|\))/gi,
36
+ snippetLines: 3,
37
+ },
38
+ {
39
+ // Java logging sensitive params — stop at quotes
40
+ pattern: /(?:log|logger)\s*\.\s*(?:debug|info|warn|error|trace)\s*\([^)'"`]*(?:password|passwd|token|secret|authorization)/gi,
41
+ snippetLines: 3,
42
+ },
43
+ {
44
+ // Go: log.Printf/Println with sensitive identifiers — stop at quotes
45
+ pattern: /(?:log|logger)\s*\.\s*(?:Printf|Println|Print|Debugf|Infof)\s*\([^)'"`]*(?:password|passwd|token|secret|apiKey|privateKey)/gi,
46
+ snippetLines: 3,
47
+ },
48
+ ],
49
+ fix: 'Scrub sensitive fields from log output. Log security events (login attempts) without logging the values.\n\n' +
50
+ '// BAD:\n' +
51
+ 'console.log("Login attempt", req.body); // logs password!\n\n' +
52
+ '// GOOD — log only safe fields:\n' +
53
+ 'logger.info({ email: req.body.email, ip: req.ip }, "Login attempt");\n\n' +
54
+ '// Use a log scrubbing library:\n' +
55
+ 'import pino from "pino";\n' +
56
+ 'const logger = pino({\n' +
57
+ ' redact: {\n' +
58
+ ' paths: ["*.password", "*.token", "*.secret", "*.authorization", "*.cvv"],\n' +
59
+ ' censor: "[REDACTED]",\n' +
60
+ ' },\n' +
61
+ '});\n\n' +
62
+ '// Python — use a log filter:\n' +
63
+ 'SENSITIVE_KEYS = {"password", "token", "secret", "key"}\n' +
64
+ 'def scrub(data: dict) -> dict:\n' +
65
+ ' return {k: "[REDACTED]" if k in SENSITIVE_KEYS else v for k, v in data.items()}',
66
+ references: [
67
+ 'https://owasp.org/Top10/A09_2021-Security_Logging_and_Monitoring_Failures/',
68
+ 'https://cwe.mitre.org/data/definitions/532.html',
69
+ 'https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html',
70
+ ],
71
+ tags: ['logging', 'pii', 'sensitive-data', 'information-disclosure'],
72
+ };
73
+ //# sourceMappingURL=log-sensitive-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-sensitive-data.js","sourceRoot":"","sources":["../../../src/rules/owasp-a09/log-sensitive-data.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,gEAAgE;AAIhE,MAAM,CAAC,MAAM,gBAAgB,GAAS;IACpC,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,+CAA+C;IACrD,KAAK,EAAE,UAAU;IACjB,GAAG,EAAE,SAAS;IACd,QAAQ,EAAE,MAAM;IAChB,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC;IAC9E,WAAW,EACT,0FAA0F;QAC1F,+FAA+F;QAC/F,gFAAgF;QAChF,8DAA8D;IAChE,QAAQ,EAAE;QACR;YACE,6CAA6C;YAC7C,wEAAwE;YACxE,uFAAuF;YACvF,iFAAiF;YACjF,OAAO,EACL,0MAA0M;YAC5M,YAAY,EAAE,CAAC;SAChB;QACD;YACE,kDAAkD;YAClD,OAAO,EACL,qFAAqF;YACvF,YAAY,EAAE,CAAC;SAChB;QACD;YACE,mFAAmF;YACnF,OAAO,EACL,0IAA0I;YAC5I,YAAY,EAAE,CAAC;SAChB;QACD;YACE,kFAAkF;YAClF,OAAO,EACL,2GAA2G;YAC7G,YAAY,EAAE,CAAC;SAChB;QACD;YACE,iDAAiD;YACjD,OAAO,EACL,oHAAoH;YACtH,YAAY,EAAE,CAAC;SAChB;QACD;YACE,qEAAqE;YACrE,OAAO,EACL,8HAA8H;YAChI,YAAY,EAAE,CAAC;SAChB;KACF;IACD,GAAG,EACD,8GAA8G;QAC9G,WAAW;QACX,+DAA+D;QAC/D,mCAAmC;QACnC,0EAA0E;QAC1E,mCAAmC;QACnC,4BAA4B;QAC5B,yBAAyB;QACzB,eAAe;QACf,iFAAiF;QACjF,6BAA6B;QAC7B,QAAQ;QACR,SAAS;QACT,iCAAiC;QACjC,2DAA2D;QAC3D,kCAAkC;QAClC,qFAAqF;IACvF,UAAU,EAAE;QACV,4EAA4E;QAC5E,iDAAiD;QACjD,yEAAyE;KAC1E;IACD,IAAI,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,gBAAgB,EAAE,wBAAwB,CAAC;CACrE,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Rule } from '../../types/index.js';
2
+ export declare const MissingErrorHandling: Rule;
3
+ //# sourceMappingURL=missing-error-handling.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"missing-error-handling.d.ts","sourceRoot":"","sources":["../../../src/rules/owasp-a09/missing-error-handling.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAEjD,eAAO,MAAM,oBAAoB,EAAE,IAkFlC,CAAC"}
@@ -0,0 +1,84 @@
1
+ // OWASP A09:2021 — Security Logging and Monitoring Failures
2
+ // Rule: Missing error handling or silent error swallowing
3
+ export const MissingErrorHandling = {
4
+ id: 'OWASP-A09-002',
5
+ name: 'Silent Error Swallowing or Missing Error Handler',
6
+ owasp: 'A09:2021',
7
+ cwe: 'CWE-390',
8
+ severity: 'MEDIUM',
9
+ languages: ['javascript', 'typescript', 'python', 'java', 'go'],
10
+ description: 'Errors caught and silently ignored (empty catch blocks) or unhandled promise rejections. ' +
11
+ 'Silent failures mask security events — failed authentication attempts, injection attempts, ' +
12
+ 'and authorization failures go undetected and unmonitored.',
13
+ patterns: [
14
+ {
15
+ // Empty catch block
16
+ pattern: /catch\s*\(\s*\w+\s*\)\s*\{\s*\}/g,
17
+ snippetLines: 3,
18
+ },
19
+ {
20
+ // catch block with only a comment — suppress when developer explains the rationale
21
+ // (e.g. "// Ignore parse errors", "// Silently ignore failed images")
22
+ // These are intentional decisions, not forgotten error handling.
23
+ pattern: /catch\s*\(\s*\w+\s*\)\s*\{\s*\/\/[^\n]*\n\s*\}/g,
24
+ suppressIf: /catch\s*\([^)]*\)\s*\{\s*\/\/[^\n]*(?:ignore|intentional|silent|expected|safe|ok|ping|pong|frame|image|avatar|optional|fallback|non-?fatal|best.?effort)\b/i,
25
+ snippetLines: 3,
26
+ },
27
+ {
28
+ // Catch that only reassigns (no logging, no rethrow)
29
+ pattern: /catch\s*\(\s*\w+\s*\)\s*\{\s*(?:return\s+(?:null|undefined|false|0|{}\s*|\[\]\s*))\s*\}/g,
30
+ snippetLines: 3,
31
+ },
32
+ {
33
+ // Python: bare except pass
34
+ pattern: /except\s*(?:\w+\s*)?:\s*\n\s*pass\b/g,
35
+ snippetLines: 3,
36
+ },
37
+ {
38
+ // Python: except with only comment
39
+ pattern: /except\s*(?:\w+\s*)?:\s*\n\s*#[^\n]*\n\s*pass\b/g,
40
+ snippetLines: 3,
41
+ },
42
+ {
43
+ // Unhandled promise: .catch(() => {}) or .catch(err => {})
44
+ pattern: /\.catch\s*\(\s*(?:\(\s*\w*\s*\)|_)\s*=>\s*\{\s*\}\s*\)/g,
45
+ snippetLines: 3,
46
+ },
47
+ {
48
+ // Go: ignoring error return value with blank identifier
49
+ pattern: /\w+\s*,\s*_\s*:?=\s*(?:db\.|sql\.|os\.|http\.|io\.|json\.)/g,
50
+ requiresContext: /(?:err|error|sql\.|db\.|query|connect|read|write)/i,
51
+ snippetLines: 3,
52
+ },
53
+ ],
54
+ fix: 'Log and handle all errors. Use a centralized error handler.\n\n' +
55
+ '// BAD:\n' +
56
+ 'try {\n' +
57
+ ' await db.query(sql);\n' +
58
+ '} catch (err) {} // silent failure!\n\n' +
59
+ '// GOOD:\n' +
60
+ 'try {\n' +
61
+ ' await db.query(sql);\n' +
62
+ '} catch (err) {\n' +
63
+ ' logger.error({ err, sql }, "Database query failed");\n' +
64
+ ' throw err; // re-throw or handle appropriately\n' +
65
+ '}\n\n' +
66
+ '// Unhandled promise rejections:\n' +
67
+ 'process.on("unhandledRejection", (reason, promise) => {\n' +
68
+ ' logger.fatal({ reason }, "Unhandled promise rejection");\n' +
69
+ ' process.exit(1);\n' +
70
+ '});\n\n' +
71
+ '// Python:\n' +
72
+ 'try:\n' +
73
+ ' result = db.execute(query)\n' +
74
+ 'except Exception:\n' +
75
+ ' logger.exception("Database error") # logs traceback\n' +
76
+ ' raise # re-raise — do not swallow',
77
+ references: [
78
+ 'https://owasp.org/Top10/A09_2021-Security_Logging_and_Monitoring_Failures/',
79
+ 'https://cwe.mitre.org/data/definitions/390.html',
80
+ 'https://cheatsheetseries.owasp.org/cheatsheets/Error_Handling_Cheat_Sheet.html',
81
+ ],
82
+ tags: ['error-handling', 'logging', 'monitoring', 'silent-failure'],
83
+ };
84
+ //# sourceMappingURL=missing-error-handling.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"missing-error-handling.js","sourceRoot":"","sources":["../../../src/rules/owasp-a09/missing-error-handling.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,0DAA0D;AAI1D,MAAM,CAAC,MAAM,oBAAoB,GAAS;IACxC,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,kDAAkD;IACxD,KAAK,EAAE,UAAU;IACjB,GAAG,EAAE,SAAS;IACd,QAAQ,EAAE,QAAQ;IAClB,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC;IAC/D,WAAW,EACT,2FAA2F;QAC3F,6FAA6F;QAC7F,2DAA2D;IAC7D,QAAQ,EAAE;QACR;YACE,oBAAoB;YACpB,OAAO,EAAE,kCAAkC;YAC3C,YAAY,EAAE,CAAC;SAChB;QACD;YACE,mFAAmF;YACnF,sEAAsE;YACtE,iEAAiE;YACjE,OAAO,EAAE,iDAAiD;YAC1D,UAAU,EAAE,6JAA6J;YACzK,YAAY,EAAE,CAAC;SAChB;QACD;YACE,qDAAqD;YACrD,OAAO,EAAE,0FAA0F;YACnG,YAAY,EAAE,CAAC;SAChB;QACD;YACE,2BAA2B;YAC3B,OAAO,EAAE,sCAAsC;YAC/C,YAAY,EAAE,CAAC;SAChB;QACD;YACE,mCAAmC;YACnC,OAAO,EAAE,kDAAkD;YAC3D,YAAY,EAAE,CAAC;SAChB;QACD;YACE,2DAA2D;YAC3D,OAAO,EAAE,yDAAyD;YAClE,YAAY,EAAE,CAAC;SAChB;QACD;YACE,wDAAwD;YACxD,OAAO,EAAE,6DAA6D;YACtE,eAAe,EAAE,oDAAoD;YACrE,YAAY,EAAE,CAAC;SAChB;KACF;IACD,GAAG,EACD,iEAAiE;QACjE,WAAW;QACX,SAAS;QACT,0BAA0B;QAC1B,yCAAyC;QACzC,YAAY;QACZ,SAAS;QACT,0BAA0B;QAC1B,mBAAmB;QACnB,0DAA0D;QAC1D,oDAAoD;QACpD,OAAO;QACP,oCAAoC;QACpC,2DAA2D;QAC3D,8DAA8D;QAC9D,sBAAsB;QACtB,SAAS;QACT,cAAc;QACd,QAAQ;QACR,kCAAkC;QAClC,qBAAqB;QACrB,4DAA4D;QAC5D,wCAAwC;IAC1C,UAAU,EAAE;QACV,4EAA4E;QAC5E,iDAAiD;QACjD,gFAAgF;KACjF;IACD,IAAI,EAAE,CAAC,gBAAgB,EAAE,SAAS,EAAE,YAAY,EAAE,gBAAgB,CAAC;CACpE,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Rule } from '../../types/index.js';
2
+ export declare const OpenRedirect: Rule;
3
+ //# sourceMappingURL=open-redirect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-redirect.d.ts","sourceRoot":"","sources":["../../../src/rules/owasp-a10/open-redirect.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAEjD,eAAO,MAAM,YAAY,EAAE,IAsE1B,CAAC"}
@@ -0,0 +1,67 @@
1
+ // OWASP A10:2021 — Server-Side Request Forgery (SSRF)
2
+ // Rule: Open Redirect via unsanitized redirect URL
3
+ export const OpenRedirect = {
4
+ id: 'OWASP-A10-002',
5
+ name: 'Open Redirect via Unsanitized URL Parameter',
6
+ owasp: 'A10:2021',
7
+ cwe: 'CWE-601',
8
+ severity: 'MEDIUM',
9
+ languages: ['javascript', 'typescript', 'python', 'php', 'java', 'ruby'],
10
+ description: 'Server redirects users to a URL taken from request parameters without validation. ' +
11
+ 'Attackers use this for phishing (myapp.com/redirect?to=evil.com) or to bypass ' +
12
+ 'same-origin checks. AI tools frequently generate res.redirect(req.query.returnUrl).',
13
+ patterns: [
14
+ {
15
+ // Express: res.redirect with user query param
16
+ pattern: /res\s*\.\s*redirect\s*\(\s*(?:req|request)\s*\.\s*(?:query|body|params)\s*\.\s*\w+/gi,
17
+ snippetLines: 3,
18
+ },
19
+ {
20
+ // Python/Flask: redirect with user input
21
+ pattern: /redirect\s*\(\s*(?:request\.|req\.)\s*(?:args|form|json|data)\s*(?:\[|\.get\s*\()/gi,
22
+ snippetLines: 3,
23
+ },
24
+ {
25
+ // PHP: header('Location: ' . $_GET['...'])
26
+ pattern: /header\s*\(\s*['"`]\s*Location\s*:\s*['"`]\s*\.\s*\$_(?:GET|POST|REQUEST)/gi,
27
+ snippetLines: 3,
28
+ },
29
+ {
30
+ // Java: response.sendRedirect with user request param
31
+ pattern: /response\s*\.\s*sendRedirect\s*\(\s*request\s*\.\s*getParameter\s*\(/gi,
32
+ snippetLines: 3,
33
+ },
34
+ {
35
+ // Ruby/Rails: redirect_to with params
36
+ pattern: /redirect_to\s+(?:params|request\.referer)\s*(?:\[|\.fetch)/gi,
37
+ snippetLines: 3,
38
+ },
39
+ ],
40
+ fix: 'Validate redirect URLs against a whitelist of allowed destinations.\n\n' +
41
+ '// Express — safe redirect:\n' +
42
+ 'const ALLOWED_REDIRECT_HOSTS = ["myapp.com", "www.myapp.com"];\n\n' +
43
+ 'function safeRedirect(res: Response, url: string, fallback = "/"): void {\n' +
44
+ ' try {\n' +
45
+ ' const parsed = new URL(url, "https://myapp.com");\n' +
46
+ ' if (ALLOWED_REDIRECT_HOSTS.includes(parsed.hostname)) {\n' +
47
+ ' res.redirect(parsed.toString());\n' +
48
+ ' return;\n' +
49
+ ' }\n' +
50
+ ' } catch { /* invalid URL */ }\n' +
51
+ ' res.redirect(fallback); // safe fallback\n' +
52
+ '}\n\n' +
53
+ '// Or: only allow relative redirects (safest):\n' +
54
+ 'const returnUrl = req.query.returnUrl as string;\n' +
55
+ 'if (returnUrl?.startsWith("/") && !returnUrl.startsWith("//")) {\n' +
56
+ ' res.redirect(returnUrl);\n' +
57
+ '} else {\n' +
58
+ ' res.redirect("/dashboard"); // fallback\n' +
59
+ '}',
60
+ references: [
61
+ 'https://owasp.org/Top10/A10_2021-Server-Side_Request_Forgery_%28SSRF%29/',
62
+ 'https://cwe.mitre.org/data/definitions/601.html',
63
+ 'https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html',
64
+ ],
65
+ tags: ['open-redirect', 'url-validation', 'phishing', 'ssrf'],
66
+ };
67
+ //# sourceMappingURL=open-redirect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-redirect.js","sourceRoot":"","sources":["../../../src/rules/owasp-a10/open-redirect.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,mDAAmD;AAInD,MAAM,CAAC,MAAM,YAAY,GAAS;IAChC,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,6CAA6C;IACnD,KAAK,EAAE,UAAU;IACjB,GAAG,EAAE,SAAS;IACd,QAAQ,EAAE,QAAQ;IAClB,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC;IACxE,WAAW,EACT,oFAAoF;QACpF,gFAAgF;QAChF,qFAAqF;IACvF,QAAQ,EAAE;QACR;YACE,8CAA8C;YAC9C,OAAO,EACL,sFAAsF;YACxF,YAAY,EAAE,CAAC;SAChB;QACD;YACE,yCAAyC;YACzC,OAAO,EACL,qFAAqF;YACvF,YAAY,EAAE,CAAC;SAChB;QACD;YACE,2CAA2C;YAC3C,OAAO,EACL,6EAA6E;YAC/E,YAAY,EAAE,CAAC;SAChB;QACD;YACE,sDAAsD;YACtD,OAAO,EACL,wEAAwE;YAC1E,YAAY,EAAE,CAAC;SAChB;QACD;YACE,sCAAsC;YACtC,OAAO,EACL,8DAA8D;YAChE,YAAY,EAAE,CAAC;SAChB;KACF;IACD,GAAG,EACD,yEAAyE;QACzE,+BAA+B;QAC/B,oEAAoE;QACpE,6EAA6E;QAC7E,WAAW;QACX,yDAAyD;QACzD,+DAA+D;QAC/D,0CAA0C;QAC1C,iBAAiB;QACjB,SAAS;QACT,mCAAmC;QACnC,8CAA8C;QAC9C,OAAO;QACP,kDAAkD;QAClD,oDAAoD;QACpD,oEAAoE;QACpE,8BAA8B;QAC9B,YAAY;QACZ,6CAA6C;QAC7C,GAAG;IACL,UAAU,EAAE;QACV,0EAA0E;QAC1E,iDAAiD;QACjD,oGAAoG;KACrG;IACD,IAAI,EAAE,CAAC,eAAe,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,CAAC;CAC9D,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Rule } from '../../types/index.js';
2
+ export declare const UnvalidatedFetch: Rule;
3
+ //# sourceMappingURL=unvalidated-fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unvalidated-fetch.d.ts","sourceRoot":"","sources":["../../../src/rules/owasp-a10/unvalidated-fetch.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAEjD,eAAO,MAAM,gBAAgB,EAAE,IA2F9B,CAAC"}
@@ -0,0 +1,85 @@
1
+ // OWASP A10:2021 — Server-Side Request Forgery (SSRF)
2
+ // Rule: Server fetches a URL from user-controlled input without validation
3
+ export const UnvalidatedFetch = {
4
+ id: 'OWASP-A10-001',
5
+ name: 'Server-Side Request Forgery (SSRF) via Unvalidated URL',
6
+ owasp: 'A10:2021',
7
+ cwe: 'CWE-918',
8
+ severity: 'CRITICAL',
9
+ languages: ['javascript', 'typescript', 'python', 'php', 'java', 'go', 'ruby'],
10
+ description: 'Server makes HTTP/HTTPS requests to URLs derived from user input without validating ' +
11
+ 'the URL. Attackers can redirect requests to internal services (AWS metadata endpoint, ' +
12
+ 'Kubernetes API, Redis, internal DBs). A common AI mistake: webhook handlers and ' +
13
+ '"fetch URL" features that directly pass req.body.url to fetch().',
14
+ patterns: [
15
+ {
16
+ // fetch() with user input
17
+ pattern: /\bfetch\s*\(\s*(?:req|request)\s*\.\s*(?:body|params|query)\s*\.\s*\w+/gi,
18
+ snippetLines: 3,
19
+ },
20
+ {
21
+ // axios.get/post with user URL
22
+ pattern: /axios\s*\.\s*(?:get|post|put|patch|delete|request)\s*\(\s*(?:req|request)\s*\.\s*(?:body|params|query)\s*\.\s*\w+/gi,
23
+ snippetLines: 3,
24
+ },
25
+ {
26
+ // Node.js http/https.get with user URL
27
+ pattern: /(?:https?|http)\s*\.\s*(?:get|request)\s*\(\s*(?:req|request)\s*\.\s*(?:body|params|query)\s*\.\s*\w+/gi,
28
+ snippetLines: 3,
29
+ },
30
+ {
31
+ // Python requests.get/post with user URL
32
+ pattern: /requests\s*\.\s*(?:get|post|put|patch|delete|head|request)\s*\(\s*(?:request\.|req\.)\s*(?:args|form|json|data)\s*(?:\[|\.\s*get)/gi,
33
+ snippetLines: 3,
34
+ },
35
+ {
36
+ // Python urllib/httpx with user URL
37
+ pattern: /(?:urllib\.request\.urlopen|httpx\.(?:get|post|request))\s*\(\s*(?:request\.|req\.)/gi,
38
+ snippetLines: 3,
39
+ },
40
+ {
41
+ // PHP: curl_setopt with user URL
42
+ pattern: /curl_setopt\s*\([^,]+,\s*CURLOPT_URL\s*,\s*\$_(?:GET|POST|REQUEST)/gi,
43
+ snippetLines: 3,
44
+ },
45
+ {
46
+ // Go: http.Get / http.Post with user URL
47
+ pattern: /http\s*\.\s*(?:Get|Post|Do)\s*\(\s*(?:r\.(?:URL\.Query|FormValue)|req\.)/gi,
48
+ snippetLines: 3,
49
+ },
50
+ {
51
+ // Template literal URL from user input in fetch
52
+ pattern: /fetch\s*\(\s*`[^`]*\$\{[^}]*(?:req\.|request\.)(?:body|params|query)/gi,
53
+ snippetLines: 3,
54
+ },
55
+ ],
56
+ fix: 'Validate URLs against an allowlist of trusted schemes, hosts, and ports.\n\n' +
57
+ '// Node.js — URL validation helper:\n' +
58
+ 'const ALLOWED_HOSTS = ["api.trustedservice.com", "cdn.myapp.com"];\n\n' +
59
+ 'function validateUrl(rawUrl: string): URL {\n' +
60
+ ' let url: URL;\n' +
61
+ ' try {\n' +
62
+ ' url = new URL(rawUrl);\n' +
63
+ ' } catch {\n' +
64
+ ' throw new Error("Invalid URL format");\n' +
65
+ ' }\n' +
66
+ ' // Only allow HTTPS\n' +
67
+ ' if (url.protocol !== "https:") throw new Error("Only HTTPS URLs allowed");\n' +
68
+ ' // Only allow trusted hosts\n' +
69
+ ' if (!ALLOWED_HOSTS.includes(url.hostname)) throw new Error("Host not in allowlist");\n' +
70
+ ' // Block private IP ranges and localhost\n' +
71
+ ' if (/^(127\\.|10\\.|172\\.(1[6-9]|2\\d|3[01])\\.|192\\.168\\.|::1|localhost)/i.test(url.hostname)) {\n' +
72
+ ' throw new Error("Private/loopback addresses not allowed");\n' +
73
+ ' }\n' +
74
+ ' return url;\n' +
75
+ '}\n\n' +
76
+ 'const validatedUrl = validateUrl(req.body.webhookUrl);\n' +
77
+ 'const response = await fetch(validatedUrl.toString());',
78
+ references: [
79
+ 'https://owasp.org/Top10/A10_2021-Server-Side_Request_Forgery_%28SSRF%29/',
80
+ 'https://cwe.mitre.org/data/definitions/918.html',
81
+ 'https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html',
82
+ ],
83
+ tags: ['ssrf', 'request-forgery', 'url-validation', 'injection'],
84
+ };
85
+ //# sourceMappingURL=unvalidated-fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unvalidated-fetch.js","sourceRoot":"","sources":["../../../src/rules/owasp-a10/unvalidated-fetch.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,2EAA2E;AAI3E,MAAM,CAAC,MAAM,gBAAgB,GAAS;IACpC,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,wDAAwD;IAC9D,KAAK,EAAE,UAAU;IACjB,GAAG,EAAE,SAAS;IACd,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC;IAC9E,WAAW,EACT,sFAAsF;QACtF,wFAAwF;QACxF,kFAAkF;QAClF,kEAAkE;IACpE,QAAQ,EAAE;QACR;YACE,0BAA0B;YAC1B,OAAO,EACL,0EAA0E;YAC5E,YAAY,EAAE,CAAC;SAChB;QACD;YACE,+BAA+B;YAC/B,OAAO,EACL,qHAAqH;YACvH,YAAY,EAAE,CAAC;SAChB;QACD;YACE,uCAAuC;YACvC,OAAO,EACL,yGAAyG;YAC3G,YAAY,EAAE,CAAC;SAChB;QACD;YACE,yCAAyC;YACzC,OAAO,EACL,qIAAqI;YACvI,YAAY,EAAE,CAAC;SAChB;QACD;YACE,oCAAoC;YACpC,OAAO,EACL,uFAAuF;YACzF,YAAY,EAAE,CAAC;SAChB;QACD;YACE,iCAAiC;YACjC,OAAO,EACL,sEAAsE;YACxE,YAAY,EAAE,CAAC;SAChB;QACD;YACE,yCAAyC;YACzC,OAAO,EACL,4EAA4E;YAC9E,YAAY,EAAE,CAAC;SAChB;QACD;YACE,gDAAgD;YAChD,OAAO,EACL,wEAAwE;YAC1E,YAAY,EAAE,CAAC;SAChB;KACF;IACD,GAAG,EACD,8EAA8E;QAC9E,uCAAuC;QACvC,wEAAwE;QACxE,+CAA+C;QAC/C,mBAAmB;QACnB,WAAW;QACX,8BAA8B;QAC9B,eAAe;QACf,8CAA8C;QAC9C,OAAO;QACP,yBAAyB;QACzB,gFAAgF;QAChF,iCAAiC;QACjC,0FAA0F;QAC1F,8CAA8C;QAC9C,0GAA0G;QAC1G,kEAAkE;QAClE,OAAO;QACP,iBAAiB;QACjB,OAAO;QACP,0DAA0D;QAC1D,wDAAwD;IAC1D,UAAU,EAAE;QACV,0EAA0E;QAC1E,iDAAiD;QACjD,wGAAwG;KACzG;IACD,IAAI,EAAE,CAAC,MAAM,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,WAAW,CAAC;CACjE,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { Rule, OWASPCategory, SupportedLanguage } from '../types/index.js';
2
+ export declare class RuleRegistry {
3
+ private rules;
4
+ private _proRulesLoaded;
5
+ constructor(rules?: Rule[]);
6
+ /** Register additional rules (e.g., from @owaspscan/rules-pro) */
7
+ registerRules(rules: Rule[]): void;
8
+ get proRulesLoaded(): boolean;
9
+ get coreRuleCount(): number;
10
+ getAll(): Rule[];
11
+ getById(id: string): Rule | undefined;
12
+ getByCategory(category: OWASPCategory): Rule[];
13
+ getByLanguage(language: SupportedLanguage): Rule[];
14
+ filterByCategories(categoryPrefixes: string[]): Rule[];
15
+ size(): number;
16
+ }
17
+ /** Create a fresh registry, optionally with extra rules */
18
+ export declare function createRegistry(extraRules?: Rule[]): RuleRegistry;
19
+ export declare const registry: RuleRegistry;
20
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/rules/registry.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAyGhF,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,eAAe,CAAS;gBAEpB,KAAK,GAAE,IAAI,EAAe;IAOtC,kEAAkE;IAClE,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI;IAOlC,IAAI,cAAc,IAAI,OAAO,CAE5B;IAED,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,MAAM,IAAI,IAAI,EAAE;IAIhB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAIrC,aAAa,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,EAAE;IAI9C,aAAa,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,EAAE;IAMlD,kBAAkB,CAAC,gBAAgB,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE;IAStD,IAAI,IAAI,MAAM;CAGf;AAED,2DAA2D;AAC3D,wBAAgB,cAAc,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,GAAG,YAAY,CAMhE;AAGD,eAAO,MAAM,QAAQ,cAAqB,CAAC"}