@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,81 @@
1
+ // ============================================================
2
+ // Config Loader — finds and merges owaspscan.config.json
3
+ // Search order: --config <path> → ./owaspscan.config.json → ./.owaspscanrc → defaults
4
+ // CLI flags passed as overrides always win
5
+ // ============================================================
6
+ import fs from 'fs';
7
+ import path from 'path';
8
+ import { DEFAULT_CONFIG } from './schema.js';
9
+ const CONFIG_FILENAMES = ['owaspscan.config.json', '.owaspscanrc'];
10
+ function tryReadJson(filePath) {
11
+ try {
12
+ const raw = fs.readFileSync(filePath, 'utf8');
13
+ return JSON.parse(raw);
14
+ }
15
+ catch {
16
+ return null;
17
+ }
18
+ }
19
+ /**
20
+ * Find the config file, starting from the given directory and walking up to the filesystem root.
21
+ */
22
+ function findConfigFile(startDir) {
23
+ let dir = startDir;
24
+ const root = path.parse(dir).root;
25
+ while (true) {
26
+ for (const name of CONFIG_FILENAMES) {
27
+ const candidate = path.join(dir, name);
28
+ if (fs.existsSync(candidate))
29
+ return candidate;
30
+ }
31
+ if (dir === root)
32
+ break;
33
+ const parent = path.dirname(dir);
34
+ if (parent === dir)
35
+ break;
36
+ dir = parent;
37
+ }
38
+ return null;
39
+ }
40
+ /**
41
+ * Load the effective config by merging: defaults < config file < CLI overrides.
42
+ *
43
+ * @param cliOverrides Partial config from CLI flags (undefined fields are ignored)
44
+ * @param explicitConfigPath Path from --config flag (overrides auto-discovery)
45
+ * @param searchDir Directory to start config file search from (default: cwd)
46
+ */
47
+ export function loadConfig(cliOverrides = {}, explicitConfigPath, searchDir = process.cwd()) {
48
+ let fileConfig = {};
49
+ if (explicitConfigPath) {
50
+ const parsed = tryReadJson(path.resolve(explicitConfigPath));
51
+ if (!parsed) {
52
+ process.stderr.write(`Warning: Could not read config file at ${explicitConfigPath}\n`);
53
+ }
54
+ else {
55
+ fileConfig = parsed;
56
+ }
57
+ }
58
+ else {
59
+ const found = findConfigFile(searchDir);
60
+ if (found) {
61
+ const parsed = tryReadJson(found);
62
+ if (parsed) {
63
+ fileConfig = parsed;
64
+ }
65
+ }
66
+ }
67
+ // Merge: defaults < file config < CLI overrides (only defined keys from CLI win)
68
+ const merged = { ...DEFAULT_CONFIG };
69
+ for (const key of Object.keys(fileConfig)) {
70
+ if (fileConfig[key] !== undefined) {
71
+ merged[key] = fileConfig[key];
72
+ }
73
+ }
74
+ for (const key of Object.keys(cliOverrides)) {
75
+ if (cliOverrides[key] !== undefined) {
76
+ merged[key] = cliOverrides[key];
77
+ }
78
+ }
79
+ return merged;
80
+ }
81
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,yDAAyD;AACzD,sFAAsF;AACtF,2CAA2C;AAC3C,+DAA+D;AAE/D,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,gBAAgB,GAAG,CAAC,uBAAuB,EAAE,cAAc,CAAC,CAAC;AAEnE,SAAS,WAAW,CAAC,QAAgB;IACnC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAoB,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,QAAgB;IACtC,IAAI,GAAG,GAAG,QAAQ,CAAC;IACnB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;IAElC,OAAO,IAAI,EAAE,CAAC;QACZ,KAAK,MAAM,IAAI,IAAI,gBAAgB,EAAE,CAAC;YACpC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACvC,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;gBAAE,OAAO,SAAS,CAAC;QACjD,CAAC;QACD,IAAI,GAAG,KAAK,IAAI;YAAE,MAAM;QACxB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,GAAG;YAAE,MAAM;QAC1B,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CACxB,eAAyC,EAAE,EAC3C,kBAA2B,EAC3B,YAAoB,OAAO,CAAC,GAAG,EAAE;IAEjC,IAAI,UAAU,GAAoB,EAAE,CAAC;IAErC,IAAI,kBAAkB,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC;QAC7D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,0CAA0C,kBAAkB,IAAI,CAAC,CAAC;QACzF,CAAC;aAAM,CAAC;YACN,UAAU,GAAG,MAAM,CAAC;QACtB,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,KAAK,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;QACxC,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;YAClC,IAAI,MAAM,EAAE,CAAC;gBACX,UAAU,GAAG,MAAM,CAAC;YACtB,CAAC;QACH,CAAC;IACH,CAAC;IAED,iFAAiF;IACjF,MAAM,MAAM,GAA8B,EAAE,GAAG,cAAc,EAAE,CAAC;IAEhE,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAA8B,EAAE,CAAC;QACvE,IAAI,UAAU,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YACjC,MAAkC,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAA8B,EAAE,CAAC;QACzE,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YACnC,MAAkC,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { Confidence, FailOnLevel, OutputFormat } from '../types/index.js';
2
+ export interface OWASPScanConfig {
3
+ /** OWASP category prefixes to scan (e.g. ["A01", "A03", "LLM01"]). Default: all */
4
+ rules?: string[];
5
+ /** Glob patterns to exclude from scanning */
6
+ exclude?: string[];
7
+ /** Exit code 1 if any finding at this severity or above */
8
+ failOn?: FailOnLevel;
9
+ /** Only report findings at this confidence level or higher */
10
+ minConfidence?: Confidence;
11
+ /** Output format */
12
+ format?: OutputFormat;
13
+ /** Show fix suggestions and references */
14
+ verbose?: boolean;
15
+ /** Run SCA dependency scanning against OSV database */
16
+ sca?: boolean;
17
+ /** Use Claude AI to verify low-confidence findings (requires ANTHROPIC_API_KEY) */
18
+ aiVerify?: boolean;
19
+ /** Max number of LLM API calls per scan run */
20
+ aiVerifyLimit?: number;
21
+ }
22
+ export declare const DEFAULT_CONFIG: Required<OWASPScanConfig>;
23
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE/E,MAAM,WAAW,eAAe;IAC9B,mFAAmF;IACnF,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,8DAA8D;IAC9D,aAAa,CAAC,EAAE,UAAU,CAAC;IAC3B,oBAAoB;IACpB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,uDAAuD;IACvD,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,mFAAmF;IACnF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+CAA+C;IAC/C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,eAAe,CAUpD,CAAC"}
@@ -0,0 +1,17 @@
1
+ // ============================================================
2
+ // OWASPScan Configuration Schema
3
+ // Supports owaspscan.config.json or .owaspscanrc in project root
4
+ // CLI flags always override config file values
5
+ // ============================================================
6
+ export const DEFAULT_CONFIG = {
7
+ rules: [],
8
+ exclude: [],
9
+ failOn: 'never',
10
+ minConfidence: 'LOW',
11
+ format: 'console',
12
+ verbose: false,
13
+ sca: false,
14
+ aiVerify: false,
15
+ aiVerifyLimit: 50,
16
+ };
17
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,iCAAiC;AACjC,iEAAiE;AACjE,+CAA+C;AAC/C,+DAA+D;AAyB/D,MAAM,CAAC,MAAM,cAAc,GAA8B;IACvD,KAAK,EAAE,EAAE;IACT,OAAO,EAAE,EAAE;IACX,MAAM,EAAE,OAAO;IACf,aAAa,EAAE,KAAK;IACpB,MAAM,EAAE,SAAS;IACjB,OAAO,EAAE,KAAK;IACd,GAAG,EAAE,KAAK;IACV,QAAQ,EAAE,KAAK;IACf,aAAa,EAAE,EAAE;CAClB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":""}
@@ -0,0 +1,250 @@
1
+ // ============================================================
2
+ // OWASPScan MCP Server
3
+ // Exposes security scanning as MCP tools for AI agents
4
+ // Compatible with Claude Desktop, Cursor, Cline, and any MCP client
5
+ // ============================================================
6
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
7
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
8
+ import { z } from 'zod';
9
+ import path from 'path';
10
+ import { scanDirectory, scanCode } from '../scanner/engine.js';
11
+ import { scanFile as scanSingleFile } from '../scanner/engine.js';
12
+ import { registry } from '../rules/registry.js';
13
+ import { reportLlm } from '../reporter/llm.js';
14
+ import { reportJson } from '../reporter/json.js';
15
+ const SUPPORTED_LANGUAGES = [
16
+ 'javascript', 'typescript', 'python', 'java', 'go', 'php', 'ruby', 'csharp', 'rust',
17
+ ];
18
+ const server = new McpServer({
19
+ name: 'owaspscan',
20
+ version: '1.0.0',
21
+ });
22
+ // ─── Tool: scan_file ───────────────────────────────────────────────────────
23
+ server.tool('scan_file', 'Scan a single source code file for OWASP Top 10 + LLM Top 10 security vulnerabilities. ' +
24
+ 'Returns findings with severity, OWASP category, CWE, line numbers, code snippets, and fix guidance.', {
25
+ path: z.string().describe('Absolute or relative path to the file to scan'),
26
+ rules: z
27
+ .array(z.string())
28
+ .optional()
29
+ .describe('Filter to specific OWASP categories e.g. ["A01", "A03", "LLM01"]. Omit for all rules.'),
30
+ format: z
31
+ .enum(['llm', 'json'])
32
+ .default('llm')
33
+ .describe('Output format: "llm" (compact, token-efficient) or "json" (full structured data)'),
34
+ }, async ({ path: filePath, rules, format }) => {
35
+ const resolvedPath = path.resolve(filePath);
36
+ const allRules = rules && rules.length > 0
37
+ ? registry.filterByCategories(rules)
38
+ : registry.getAll();
39
+ const fileResult = await scanSingleFile(resolvedPath, allRules);
40
+ // Wrap into ScanResult format
41
+ const { buildScanResult } = await import('../utils/scoring.js');
42
+ const result = buildScanResult(resolvedPath, [fileResult], fileResult.scanDurationMs, 'never');
43
+ const output = format === 'json' ? reportJson(result) : reportLlm(result);
44
+ return {
45
+ content: [{ type: 'text', text: output }],
46
+ };
47
+ });
48
+ // ─── Tool: scan_directory ─────────────────────────────────────────────────
49
+ server.tool('scan_directory', 'Recursively scan a project directory for OWASP Top 10 + LLM Top 10 security vulnerabilities across all supported languages. ' +
50
+ 'Supports JS/TS, Python, Java, Go, PHP, Ruby, C#, Rust.', {
51
+ path: z.string().describe('Path to the directory to scan'),
52
+ recursive: z
53
+ .boolean()
54
+ .default(true)
55
+ .describe('Whether to scan subdirectories recursively'),
56
+ rules: z
57
+ .array(z.string())
58
+ .optional()
59
+ .describe('Filter to specific OWASP categories. Omit for all 35+ rules.'),
60
+ exclude: z
61
+ .array(z.string())
62
+ .optional()
63
+ .describe('Glob patterns to exclude (e.g. ["**/*.test.ts", "migrations/**"])'),
64
+ format: z
65
+ .enum(['llm', 'json'])
66
+ .default('llm')
67
+ .describe('Output format'),
68
+ fail_on: z
69
+ .enum(['critical', 'high', 'medium', 'low', 'never'])
70
+ .default('never')
71
+ .describe('Severity threshold — result.passed will be false if findings at or above this level exist'),
72
+ }, async ({ path: dirPath, recursive, rules, exclude, format, fail_on }) => {
73
+ const resolvedPath = path.resolve(dirPath);
74
+ const result = await scanDirectory(resolvedPath, {
75
+ rules,
76
+ exclude,
77
+ recursive,
78
+ failOn: fail_on,
79
+ verbose: false,
80
+ });
81
+ const output = format === 'json' ? reportJson(result) : reportLlm(result);
82
+ return {
83
+ content: [{ type: 'text', text: output }],
84
+ };
85
+ });
86
+ // ─── Tool: scan_code ──────────────────────────────────────────────────────
87
+ server.tool('scan_code', 'Scan a code snippet (string) for security vulnerabilities without needing a file. ' +
88
+ 'Perfect for scanning code that was just generated or modified by an AI assistant before committing.', {
89
+ code: z.string().describe('The source code to scan'),
90
+ language: z
91
+ .enum(SUPPORTED_LANGUAGES)
92
+ .describe('Programming language of the code snippet'),
93
+ filename: z
94
+ .string()
95
+ .optional()
96
+ .default('<inline>')
97
+ .describe('Optional filename for context in findings output'),
98
+ rules: z
99
+ .array(z.string())
100
+ .optional()
101
+ .describe('Filter to specific OWASP categories. Omit for all rules.'),
102
+ format: z.enum(['llm', 'json']).default('llm'),
103
+ }, async ({ code, language, filename, rules, format }) => {
104
+ const result = await scanCode(code, language, filename ?? '<inline>', rules);
105
+ const output = format === 'json' ? reportJson(result) : reportLlm(result);
106
+ return {
107
+ content: [{ type: 'text', text: output }],
108
+ };
109
+ });
110
+ // ─── Tool: get_rules ─────────────────────────────────────────────────────
111
+ server.tool('get_rules', 'List all available security rules with their IDs, names, OWASP categories, severity, and CWE numbers.', {
112
+ owasp_category: z
113
+ .string()
114
+ .optional()
115
+ .describe('Filter by OWASP category prefix e.g. "A01", "LLM01", "EXTRA"'),
116
+ language: z
117
+ .enum(SUPPORTED_LANGUAGES)
118
+ .optional()
119
+ .describe('Filter rules applicable to a specific language'),
120
+ severity: z
121
+ .enum(['CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'INFO'])
122
+ .optional()
123
+ .describe('Filter by minimum severity'),
124
+ }, async ({ owasp_category, language, severity }) => {
125
+ let rules = registry.getAll();
126
+ if (owasp_category) {
127
+ rules = rules.filter((r) => r.owasp.startsWith(owasp_category.toUpperCase()));
128
+ }
129
+ if (language) {
130
+ rules = rules.filter((r) => r.languages.includes('all') || r.languages.includes(language));
131
+ }
132
+ if (severity) {
133
+ const sevOrder = { CRITICAL: 5, HIGH: 4, MEDIUM: 3, LOW: 2, INFO: 1 };
134
+ const minSev = sevOrder[severity];
135
+ rules = rules.filter((r) => sevOrder[r.severity] >= minSev);
136
+ }
137
+ const output = rules
138
+ .map((r) => `[${r.id}] ${r.name}\n` +
139
+ ` OWASP: ${r.owasp} | CWE: ${r.cwe} | Severity: ${r.severity}\n` +
140
+ ` Languages: ${r.languages.join(', ')}\n` +
141
+ ` Tags: ${r.tags.join(', ')}\n`)
142
+ .join('\n');
143
+ return {
144
+ content: [
145
+ {
146
+ type: 'text',
147
+ text: `OWASPScan Rules (${rules.length} total):\n\n${output}`,
148
+ },
149
+ ],
150
+ };
151
+ });
152
+ // ─── Tool: explain_finding ───────────────────────────────────────────────
153
+ server.tool('explain_finding', 'Get detailed explanation, example vulnerable code, and secure code fix for a specific rule ID.', {
154
+ rule_id: z
155
+ .string()
156
+ .describe('Rule ID to explain, e.g. "OWASP-A03-001" or "LLM-01-001"'),
157
+ }, async ({ rule_id }) => {
158
+ const rule = registry.getById(rule_id);
159
+ if (!rule) {
160
+ return {
161
+ content: [
162
+ {
163
+ type: 'text',
164
+ text: `Rule "${rule_id}" not found. Use get_rules to see available rule IDs.`,
165
+ },
166
+ ],
167
+ isError: true,
168
+ };
169
+ }
170
+ const output = [
171
+ `## ${rule.name}`,
172
+ `**ID:** ${rule.id}`,
173
+ `**OWASP Category:** ${rule.owasp}`,
174
+ `**CWE:** ${rule.cwe}`,
175
+ `**Severity:** ${rule.severity}`,
176
+ `**Applicable Languages:** ${rule.languages.join(', ')}`,
177
+ '',
178
+ '### Description',
179
+ rule.description,
180
+ '',
181
+ '### Remediation',
182
+ '```',
183
+ rule.fix,
184
+ '```',
185
+ '',
186
+ '### References',
187
+ ...rule.references.map((r) => `- ${r}`),
188
+ '',
189
+ '### Tags',
190
+ rule.tags.map((t) => `\`${t}\``).join(', '),
191
+ ].join('\n');
192
+ return {
193
+ content: [{ type: 'text', text: output }],
194
+ };
195
+ });
196
+ // ─── Tool: get_owasp_category ─────────────────────────────────────────────
197
+ server.tool('get_owasp_category', 'Get a description of an OWASP Top 10 or LLM Top 10 category with all related rules.', {
198
+ category: z
199
+ .string()
200
+ .describe('OWASP category e.g. "A03:2021", "LLM01:2025", or just "A03" or "LLM01"'),
201
+ }, async ({ category }) => {
202
+ const prefix = category.toUpperCase().replace(/:.*/, '');
203
+ const rules = registry.filterByCategories([prefix]);
204
+ const CATEGORY_DESCRIPTIONS = {
205
+ 'A01:2021': 'Broken Access Control — Users can act outside their intended permissions.',
206
+ 'A02:2021': 'Cryptographic Failures — Weak encryption, hardcoded secrets, insecure randomness.',
207
+ 'A03:2021': 'Injection — SQL, command, NoSQL, LDAP, template, XSS injection.',
208
+ 'A04:2021': 'Insecure Design — Missing rate limiting, mass assignment, flawed security design.',
209
+ 'A05:2021': 'Security Misconfiguration — Debug mode, wildcard CORS, default credentials.',
210
+ 'A06:2021': 'Vulnerable and Outdated Components — Known CVEs, deprecated APIs.',
211
+ 'A07:2021': 'Identification and Authentication Failures — JWT, password storage, session bugs.',
212
+ 'A08:2021': 'Software and Data Integrity Failures — eval(), unsafe deserialization.',
213
+ 'A09:2021': 'Security Logging and Monitoring Failures — Sensitive data in logs, silent errors.',
214
+ 'A10:2021': 'Server-Side Request Forgery (SSRF) — Unvalidated URLs in server requests.',
215
+ 'LLM01:2025': 'Prompt Injection — User input injected into LLM prompts.',
216
+ 'LLM02:2025': 'Sensitive Information Disclosure — PII/secrets sent to LLMs or leaked.',
217
+ 'LLM05:2025': 'Improper Output Handling — LLM output used unsafely in code.',
218
+ 'LLM06:2025': 'Excessive Agency — LLM agents with too many permissions and no human oversight.',
219
+ 'LLM07:2025': 'System Prompt Leakage — System prompt contents exposed to users.',
220
+ 'LLM10:2025': 'Unbounded Consumption — No token limits or rate limits on LLM API calls.',
221
+ };
222
+ const matchedKey = Object.keys(CATEGORY_DESCRIPTIONS).find((k) => k.toUpperCase().startsWith(prefix));
223
+ const description = matchedKey
224
+ ? CATEGORY_DESCRIPTIONS[matchedKey]
225
+ : `No description available for category: ${category}`;
226
+ const rulesText = rules
227
+ .map((r) => ` [${r.severity}] ${r.id} — ${r.name}`)
228
+ .join('\n');
229
+ const output = [
230
+ `## OWASP ${category}`,
231
+ description ?? '',
232
+ '',
233
+ `### Rules in OWASPScan for this category (${rules.length}):`,
234
+ rulesText || ' No rules found for this category.',
235
+ ].join('\n');
236
+ return {
237
+ content: [{ type: 'text', text: output }],
238
+ };
239
+ });
240
+ // ─── Start server ─────────────────────────────────────────────────────────
241
+ async function main() {
242
+ const transport = new StdioServerTransport();
243
+ await server.connect(transport);
244
+ process.stderr.write('OWASPScan MCP Server running on stdio\n');
245
+ }
246
+ main().catch((err) => {
247
+ process.stderr.write(`Fatal error: ${String(err)}\n`);
248
+ process.exit(1);
249
+ });
250
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ export interface TSNode {
2
+ type: string;
3
+ text: string;
4
+ startPosition: {
5
+ row: number;
6
+ column: number;
7
+ };
8
+ endPosition: {
9
+ row: number;
10
+ column: number;
11
+ };
12
+ childCount: number;
13
+ namedChildCount: number;
14
+ children: TSNode[];
15
+ namedChildren: TSNode[];
16
+ parent: TSNode | null;
17
+ firstChild: TSNode | null;
18
+ firstNamedChild: TSNode | null;
19
+ nextSibling: TSNode | null;
20
+ nextNamedSibling: TSNode | null;
21
+ child(index: number): TSNode | null;
22
+ namedChild(index: number): TSNode | null;
23
+ childForFieldName(fieldName: string): TSNode | null;
24
+ }
25
+ export interface TSTree {
26
+ rootNode: TSNode;
27
+ }
28
+ export type ParseLanguage = 'javascript' | 'typescript' | 'python';
29
+ /**
30
+ * Parse source code into an AST.
31
+ * Returns null if tree-sitter is unavailable or parsing fails.
32
+ */
33
+ export declare function parseCode(code: string, language: ParseLanguage): TSTree | null;
34
+ /** Recursively walk every node in the tree, calling visitor for each. */
35
+ export declare function walkTree(node: TSNode, visitor: (n: TSNode) => void): void;
36
+ /** Collect all nodes of a specific type. */
37
+ export declare function findAllNodes(root: TSNode, type: string): TSNode[];
38
+ //# sourceMappingURL=ast-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-parser.d.ts","sourceRoot":"","sources":["../../src/parsers/ast-parser.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,WAAW,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACpC,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACzC,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CACrD;AAED,MAAM,WAAW,MAAM;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,YAAY,GAAG,QAAQ,CAAC;AAoDnE;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAQ9E;AAED,yEAAyE;AACzE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAKzE;AAED,4CAA4C;AAC5C,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAMjE"}
@@ -0,0 +1,88 @@
1
+ // ============================================================
2
+ // AST Parser — tree-sitter wrapper with lazy-loading and caching
3
+ //
4
+ // tree-sitter is a native CJS module; use createRequire in ESM context.
5
+ // Parser instances are cached per language for performance.
6
+ // All errors return null — callers fall back to regex/taint on failure.
7
+ // ============================================================
8
+ import { createRequire } from 'module';
9
+ const _require = createRequire(import.meta.url);
10
+ // ---- Internal state ----
11
+ let _ParserClass = null;
12
+ let _jsLang = null;
13
+ let _pyLang = null;
14
+ function loadParser() {
15
+ if (!_ParserClass) {
16
+ _ParserClass = _require('tree-sitter');
17
+ }
18
+ return _ParserClass;
19
+ }
20
+ function loadLanguage(language) {
21
+ if (language === 'javascript' || language === 'typescript') {
22
+ if (!_jsLang) {
23
+ _jsLang = _require('tree-sitter-javascript');
24
+ }
25
+ return _jsLang;
26
+ }
27
+ if (language === 'python') {
28
+ if (!_pyLang) {
29
+ _pyLang = _require('tree-sitter-python');
30
+ }
31
+ return _pyLang;
32
+ }
33
+ return null;
34
+ }
35
+ // Cached parser instances (one per language)
36
+ const _parsers = new Map();
37
+ function getParser(language) {
38
+ if (_parsers.has(language)) {
39
+ return _parsers.get(language);
40
+ }
41
+ try {
42
+ const ParserClass = loadParser();
43
+ if (!ParserClass)
44
+ return null;
45
+ const lang = loadLanguage(language);
46
+ if (!lang)
47
+ return null;
48
+ const parser = new ParserClass();
49
+ parser.setLanguage(lang);
50
+ _parsers.set(language, parser);
51
+ return parser;
52
+ }
53
+ catch {
54
+ return null;
55
+ }
56
+ }
57
+ /**
58
+ * Parse source code into an AST.
59
+ * Returns null if tree-sitter is unavailable or parsing fails.
60
+ */
61
+ export function parseCode(code, language) {
62
+ try {
63
+ const parser = getParser(language);
64
+ if (!parser)
65
+ return null;
66
+ return parser.parse(code);
67
+ }
68
+ catch {
69
+ return null;
70
+ }
71
+ }
72
+ /** Recursively walk every node in the tree, calling visitor for each. */
73
+ export function walkTree(node, visitor) {
74
+ visitor(node);
75
+ for (const child of node.children) {
76
+ walkTree(child, visitor);
77
+ }
78
+ }
79
+ /** Collect all nodes of a specific type. */
80
+ export function findAllNodes(root, type) {
81
+ const results = [];
82
+ walkTree(root, (n) => {
83
+ if (n.type === type)
84
+ results.push(n);
85
+ });
86
+ return results;
87
+ }
88
+ //# sourceMappingURL=ast-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-parser.js","sourceRoot":"","sources":["../../src/parsers/ast-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ import type { TSNode } from './ast-parser.js';
2
+ import type { OWASPCategory, Severity } from '../types/index.js';
3
+ export type TaintMap = Map<string, string>;
4
+ /**
5
+ * Scan a single file's AST and collect the names of exported functions/variables
6
+ * whose bodies contain direct user-input sources.
7
+ *
8
+ * Used for cross-file taint tracking: if file A exports `getUserId(req)` which
9
+ * reads `req.query.id`, and file B calls `getUserId(req)`, the return value in
10
+ * file B should be treated as tainted.
11
+ */
12
+ export declare function collectExportedTaintSources(rootNode: TSNode, language: 'javascript' | 'typescript'): TaintMap;
13
+ /**
14
+ * Walk all variable declarations and assignments in the AST.
15
+ * When the right-hand side is/contains a user input source, mark the
16
+ * left-hand variable name(s) as tainted.
17
+ *
18
+ * crossFileSources: optional map of function names from other files that return
19
+ * tainted data (built by collectExportedTaintSources in the pre-pass).
20
+ *
21
+ * Returns the initial (un-propagated) taint map.
22
+ */
23
+ export declare function buildInitialTaintMap(rootNode: TSNode, language: 'javascript' | 'typescript' | 'python', crossFileSources?: TaintMap): TaintMap;
24
+ /**
25
+ * Fixed-point propagation: if the RHS of an assignment contains a tainted
26
+ * identifier, the LHS variable becomes tainted too.
27
+ *
28
+ * Mutates `tainted` in place. Runs until no new taints are added (max 10 passes).
29
+ */
30
+ export declare function propagateTaint(rootNode: TSNode, tainted: TaintMap, language: 'javascript' | 'typescript' | 'python'): void;
31
+ /**
32
+ * Build the full taint map: initial sources + propagated chains.
33
+ * crossFileSources: optional function names from other files that return tainted data.
34
+ */
35
+ export declare function buildTaintMap(rootNode: TSNode, language: 'javascript' | 'typescript' | 'python', crossFileSources?: TaintMap): TaintMap;
36
+ export interface ASTFinding {
37
+ ruleId: string;
38
+ owasp: OWASPCategory;
39
+ severity: Severity;
40
+ description: string;
41
+ line: number;
42
+ column: number;
43
+ snippet: string;
44
+ argText: string;
45
+ sinkName: string;
46
+ taintPath?: string[];
47
+ suppressedByMiddleware?: boolean;
48
+ }
49
+ /**
50
+ * Scan a parsed AST for vulnerabilities.
51
+ * Combines two detection modes:
52
+ * 1. Direct: user input appears directly in a sink argument
53
+ * 2. Taint: user input was assigned to a variable that reaches the sink
54
+ *
55
+ * The taint map is built via AST node traversal (not regex), so it is
56
+ * precise — handles destructuring, reassignment, template literals.
57
+ * Middleware-aware: handlers guarded by validate/auth middleware get LOW confidence.
58
+ *
59
+ * crossFileSources: optional map of function names from other scanned files that
60
+ * return tainted data (populated by the two-pass scanDirectory pre-pass).
61
+ */
62
+ export declare function findVulnerableCalls(rootNode: TSNode, language: 'javascript' | 'typescript' | 'python', sourceLines: string[], crossFileSources?: TaintMap): ASTFinding[];
63
+ //# sourceMappingURL=ast-queries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-queries.d.ts","sourceRoot":"","sources":["../../src/parsers/ast-queries.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAejE,MAAM,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAI3C;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,YAAY,GAAG,YAAY,GACpC,QAAQ,CA+CV;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,YAAY,GAAG,YAAY,GAAG,QAAQ,EAChD,gBAAgB,CAAC,EAAE,QAAQ,GAC1B,QAAQ,CAsGV;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,QAAQ,EACjB,QAAQ,EAAE,YAAY,GAAG,YAAY,GAAG,QAAQ,GAC/C,IAAI,CA+DN;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,YAAY,GAAG,YAAY,GAAG,QAAQ,EAChD,gBAAgB,CAAC,EAAE,QAAQ,GAC1B,QAAQ,CAMV;AA0GD,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,QAAQ,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAkND;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,YAAY,GAAG,YAAY,GAAG,QAAQ,EAChD,WAAW,EAAE,MAAM,EAAE,EACrB,gBAAgB,CAAC,EAAE,QAAQ,GAC1B,UAAU,EAAE,CAqCd"}