mcp-security-scanner 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 (205) hide show
  1. package/LICENSE +21 -0
  2. package/README.ar.md +662 -0
  3. package/README.bn.md +662 -0
  4. package/README.bs.md +662 -0
  5. package/README.da.md +662 -0
  6. package/README.de.md +662 -0
  7. package/README.el.md +662 -0
  8. package/README.es.md +662 -0
  9. package/README.fr.md +663 -0
  10. package/README.hi.md +662 -0
  11. package/README.it.md +662 -0
  12. package/README.ja.md +663 -0
  13. package/README.ko.md +662 -0
  14. package/README.md +662 -0
  15. package/README.no.md +662 -0
  16. package/README.pl.md +662 -0
  17. package/README.pt-BR.md +662 -0
  18. package/README.ru.md +662 -0
  19. package/README.th.md +662 -0
  20. package/README.tr.md +662 -0
  21. package/README.uk.md +663 -0
  22. package/README.vi.md +662 -0
  23. package/README.zh-TW.md +661 -0
  24. package/README.zh.md +661 -0
  25. package/dist/config/env-scanner.d.ts +3 -0
  26. package/dist/config/env-scanner.d.ts.map +1 -0
  27. package/dist/config/env-scanner.js +85 -0
  28. package/dist/config/env-scanner.js.map +1 -0
  29. package/dist/config/index.d.ts +3 -0
  30. package/dist/config/index.d.ts.map +1 -0
  31. package/dist/config/index.js +169 -0
  32. package/dist/config/index.js.map +1 -0
  33. package/dist/config/mcp-config-parser.d.ts +16 -0
  34. package/dist/config/mcp-config-parser.d.ts.map +1 -0
  35. package/dist/config/mcp-config-parser.js +86 -0
  36. package/dist/config/mcp-config-parser.js.map +1 -0
  37. package/dist/config/server-verification.d.ts +5 -0
  38. package/dist/config/server-verification.d.ts.map +1 -0
  39. package/dist/config/server-verification.js +221 -0
  40. package/dist/config/server-verification.js.map +1 -0
  41. package/dist/data/dangerous-sinks.d.ts +13 -0
  42. package/dist/data/dangerous-sinks.d.ts.map +1 -0
  43. package/dist/data/dangerous-sinks.js +45 -0
  44. package/dist/data/dangerous-sinks.js.map +1 -0
  45. package/dist/data/owasp-mcp-top10.d.ts +12 -0
  46. package/dist/data/owasp-mcp-top10.d.ts.map +1 -0
  47. package/dist/data/owasp-mcp-top10.js +95 -0
  48. package/dist/data/owasp-mcp-top10.js.map +1 -0
  49. package/dist/data/poisoning-patterns.d.ts +15 -0
  50. package/dist/data/poisoning-patterns.d.ts.map +1 -0
  51. package/dist/data/poisoning-patterns.js +146 -0
  52. package/dist/data/poisoning-patterns.js.map +1 -0
  53. package/dist/data/popular-packages.d.ts +2 -0
  54. package/dist/data/popular-packages.d.ts.map +1 -0
  55. package/dist/data/popular-packages.js +71 -0
  56. package/dist/data/popular-packages.js.map +1 -0
  57. package/dist/data/secret-patterns.d.ts +8 -0
  58. package/dist/data/secret-patterns.d.ts.map +1 -0
  59. package/dist/data/secret-patterns.js +129 -0
  60. package/dist/data/secret-patterns.js.map +1 -0
  61. package/dist/deps/index.d.ts +3 -0
  62. package/dist/deps/index.d.ts.map +1 -0
  63. package/dist/deps/index.js +308 -0
  64. package/dist/deps/index.js.map +1 -0
  65. package/dist/deps/install-script-detector.d.ts +9 -0
  66. package/dist/deps/install-script-detector.d.ts.map +1 -0
  67. package/dist/deps/install-script-detector.js +98 -0
  68. package/dist/deps/install-script-detector.js.map +1 -0
  69. package/dist/deps/lockfile-parser.d.ts +15 -0
  70. package/dist/deps/lockfile-parser.d.ts.map +1 -0
  71. package/dist/deps/lockfile-parser.js +123 -0
  72. package/dist/deps/lockfile-parser.js.map +1 -0
  73. package/dist/deps/typosquat-checker.d.ts +10 -0
  74. package/dist/deps/typosquat-checker.d.ts.map +1 -0
  75. package/dist/deps/typosquat-checker.js +84 -0
  76. package/dist/deps/typosquat-checker.js.map +1 -0
  77. package/dist/index.d.ts +3 -0
  78. package/dist/index.d.ts.map +1 -0
  79. package/dist/index.js +315 -0
  80. package/dist/index.js.map +1 -0
  81. package/dist/meta/sources.d.ts +3 -0
  82. package/dist/meta/sources.d.ts.map +1 -0
  83. package/dist/meta/sources.js +43 -0
  84. package/dist/meta/sources.js.map +1 -0
  85. package/dist/protocol/mcp-server.d.ts +4 -0
  86. package/dist/protocol/mcp-server.d.ts.map +1 -0
  87. package/dist/protocol/mcp-server.js +32 -0
  88. package/dist/protocol/mcp-server.js.map +1 -0
  89. package/dist/protocol/tools.d.ts +3 -0
  90. package/dist/protocol/tools.d.ts.map +1 -0
  91. package/dist/protocol/tools.js +21 -0
  92. package/dist/protocol/tools.js.map +1 -0
  93. package/dist/report/index.d.ts +3 -0
  94. package/dist/report/index.d.ts.map +1 -0
  95. package/dist/report/index.js +259 -0
  96. package/dist/report/index.js.map +1 -0
  97. package/dist/report/json-report.d.ts +4 -0
  98. package/dist/report/json-report.d.ts.map +1 -0
  99. package/dist/report/json-report.js +61 -0
  100. package/dist/report/json-report.js.map +1 -0
  101. package/dist/report/markdown.d.ts +3 -0
  102. package/dist/report/markdown.d.ts.map +1 -0
  103. package/dist/report/markdown.js +89 -0
  104. package/dist/report/markdown.js.map +1 -0
  105. package/dist/report/sarif.d.ts +3 -0
  106. package/dist/report/sarif.d.ts.map +1 -0
  107. package/dist/report/sarif.js +56 -0
  108. package/dist/report/sarif.js.map +1 -0
  109. package/dist/runtime/client.d.ts +31 -0
  110. package/dist/runtime/client.d.ts.map +1 -0
  111. package/dist/runtime/client.js +53 -0
  112. package/dist/runtime/client.js.map +1 -0
  113. package/dist/runtime/index.d.ts +3 -0
  114. package/dist/runtime/index.d.ts.map +1 -0
  115. package/dist/runtime/index.js +239 -0
  116. package/dist/runtime/index.js.map +1 -0
  117. package/dist/runtime/pinning.d.ts +21 -0
  118. package/dist/runtime/pinning.d.ts.map +1 -0
  119. package/dist/runtime/pinning.js +74 -0
  120. package/dist/runtime/pinning.js.map +1 -0
  121. package/dist/runtime/schema-analyzer.d.ts +14 -0
  122. package/dist/runtime/schema-analyzer.d.ts.map +1 -0
  123. package/dist/runtime/schema-analyzer.js +204 -0
  124. package/dist/runtime/schema-analyzer.js.map +1 -0
  125. package/dist/runtime/tool-analyzer.d.ts +6 -0
  126. package/dist/runtime/tool-analyzer.d.ts.map +1 -0
  127. package/dist/runtime/tool-analyzer.js +92 -0
  128. package/dist/runtime/tool-analyzer.js.map +1 -0
  129. package/dist/static/analyzers/code-execution.d.ts +4 -0
  130. package/dist/static/analyzers/code-execution.d.ts.map +1 -0
  131. package/dist/static/analyzers/code-execution.js +72 -0
  132. package/dist/static/analyzers/code-execution.js.map +1 -0
  133. package/dist/static/analyzers/command-injection.d.ts +4 -0
  134. package/dist/static/analyzers/command-injection.d.ts.map +1 -0
  135. package/dist/static/analyzers/command-injection.js +62 -0
  136. package/dist/static/analyzers/command-injection.js.map +1 -0
  137. package/dist/static/analyzers/info-disclosure.d.ts +4 -0
  138. package/dist/static/analyzers/info-disclosure.d.ts.map +1 -0
  139. package/dist/static/analyzers/info-disclosure.js +65 -0
  140. package/dist/static/analyzers/info-disclosure.js.map +1 -0
  141. package/dist/static/analyzers/insecure-crypto.d.ts +4 -0
  142. package/dist/static/analyzers/insecure-crypto.d.ts.map +1 -0
  143. package/dist/static/analyzers/insecure-crypto.js +65 -0
  144. package/dist/static/analyzers/insecure-crypto.js.map +1 -0
  145. package/dist/static/analyzers/logging-audit.d.ts +4 -0
  146. package/dist/static/analyzers/logging-audit.d.ts.map +1 -0
  147. package/dist/static/analyzers/logging-audit.js +81 -0
  148. package/dist/static/analyzers/logging-audit.js.map +1 -0
  149. package/dist/static/analyzers/path-traversal.d.ts +4 -0
  150. package/dist/static/analyzers/path-traversal.d.ts.map +1 -0
  151. package/dist/static/analyzers/path-traversal.js +42 -0
  152. package/dist/static/analyzers/path-traversal.js.map +1 -0
  153. package/dist/static/analyzers/prototype-pollution.d.ts +4 -0
  154. package/dist/static/analyzers/prototype-pollution.d.ts.map +1 -0
  155. package/dist/static/analyzers/prototype-pollution.js +80 -0
  156. package/dist/static/analyzers/prototype-pollution.js.map +1 -0
  157. package/dist/static/analyzers/regex-dos.d.ts +4 -0
  158. package/dist/static/analyzers/regex-dos.d.ts.map +1 -0
  159. package/dist/static/analyzers/regex-dos.js +78 -0
  160. package/dist/static/analyzers/regex-dos.js.map +1 -0
  161. package/dist/static/analyzers/secret-hardcoded.d.ts +4 -0
  162. package/dist/static/analyzers/secret-hardcoded.d.ts.map +1 -0
  163. package/dist/static/analyzers/secret-hardcoded.js +70 -0
  164. package/dist/static/analyzers/secret-hardcoded.js.map +1 -0
  165. package/dist/static/analyzers/ssrf.d.ts +4 -0
  166. package/dist/static/analyzers/ssrf.d.ts.map +1 -0
  167. package/dist/static/analyzers/ssrf.js +39 -0
  168. package/dist/static/analyzers/ssrf.js.map +1 -0
  169. package/dist/static/analyzers/unsafe-regex.d.ts +4 -0
  170. package/dist/static/analyzers/unsafe-regex.d.ts.map +1 -0
  171. package/dist/static/analyzers/unsafe-regex.js +36 -0
  172. package/dist/static/analyzers/unsafe-regex.js.map +1 -0
  173. package/dist/static/ast-engine.d.ts +22 -0
  174. package/dist/static/ast-engine.d.ts.map +1 -0
  175. package/dist/static/ast-engine.js +155 -0
  176. package/dist/static/ast-engine.js.map +1 -0
  177. package/dist/static/index.d.ts +3 -0
  178. package/dist/static/index.d.ts.map +1 -0
  179. package/dist/static/index.js +114 -0
  180. package/dist/static/index.js.map +1 -0
  181. package/dist/static/taint-tracker.d.ts +15 -0
  182. package/dist/static/taint-tracker.d.ts.map +1 -0
  183. package/dist/static/taint-tracker.js +70 -0
  184. package/dist/static/taint-tracker.js.map +1 -0
  185. package/dist/types/findings.d.ts +60 -0
  186. package/dist/types/findings.d.ts.map +1 -0
  187. package/dist/types/findings.js +9 -0
  188. package/dist/types/findings.js.map +1 -0
  189. package/dist/types/index.d.ts +23 -0
  190. package/dist/types/index.d.ts.map +1 -0
  191. package/dist/types/index.js +8 -0
  192. package/dist/types/index.js.map +1 -0
  193. package/dist/utils/crypto.d.ts +4 -0
  194. package/dist/utils/crypto.d.ts.map +1 -0
  195. package/dist/utils/crypto.js +12 -0
  196. package/dist/utils/crypto.js.map +1 -0
  197. package/dist/utils/fs-helpers.d.ts +7 -0
  198. package/dist/utils/fs-helpers.d.ts.map +1 -0
  199. package/dist/utils/fs-helpers.js +92 -0
  200. package/dist/utils/fs-helpers.js.map +1 -0
  201. package/dist/utils/levenshtein.d.ts +7 -0
  202. package/dist/utils/levenshtein.d.ts.map +1 -0
  203. package/dist/utils/levenshtein.js +89 -0
  204. package/dist/utils/levenshtein.js.map +1 -0
  205. package/package.json +57 -0
@@ -0,0 +1,80 @@
1
+ import { findCallExpressions, getCallName, getQualifiedCallName, getLocation, containsUserInput, SyntaxKind } from "../ast-engine.js";
2
+ import { getCallEvidence } from "../taint-tracker.js";
3
+ export function analyzePrototypePollution(sourceFiles) {
4
+ const findings = [];
5
+ let counter = 0;
6
+ for (const sf of sourceFiles) {
7
+ const calls = findCallExpressions(sf);
8
+ for (const call of calls) {
9
+ const qname = getQualifiedCallName(call);
10
+ // Object.assign with user input
11
+ if (qname === "Object.assign") {
12
+ const args = call.getArguments();
13
+ if (args.length >= 2 && containsUserInput(args[args.length - 1])) {
14
+ const loc = getLocation(call);
15
+ counter++;
16
+ findings.push({
17
+ id: `SAST-PROTO-${String(counter).padStart(3, "0")}`,
18
+ title: "Prototype Pollution via Object.assign()",
19
+ severity: "high",
20
+ owasp_mcp: "MCP05",
21
+ owasp_mcp_title: "Command Injection & Code Execution",
22
+ category: "static",
23
+ file: loc.file,
24
+ line: loc.line,
25
+ column: loc.column,
26
+ evidence: getCallEvidence(call),
27
+ remediation: "Filter __proto__, constructor, and prototype properties from user input before passing to Object.assign(). Use a safe merge utility.",
28
+ cwe: "CWE-1321",
29
+ });
30
+ }
31
+ }
32
+ // JSON.parse followed by spread/assign
33
+ if (getCallName(call) === "parse" && qname === "JSON.parse") {
34
+ if (containsUserInput(call)) {
35
+ const loc = getLocation(call);
36
+ counter++;
37
+ findings.push({
38
+ id: `SAST-PROTO-${String(counter).padStart(3, "0")}`,
39
+ title: "JSON.parse() with Untrusted Input",
40
+ severity: "medium",
41
+ owasp_mcp: "MCP05",
42
+ owasp_mcp_title: "Command Injection & Code Execution",
43
+ category: "static",
44
+ file: loc.file,
45
+ line: loc.line,
46
+ column: loc.column,
47
+ evidence: getCallEvidence(call),
48
+ remediation: "Validate JSON.parse output before using in Object.assign/spread. Filter __proto__ and constructor keys.",
49
+ cwe: "CWE-1321",
50
+ });
51
+ }
52
+ }
53
+ }
54
+ // Check for bracket notation with user input: obj[userInput]
55
+ const elementAccess = sf.getDescendantsOfKind(SyntaxKind.ElementAccessExpression);
56
+ for (const ea of elementAccess) {
57
+ const arg = ea.getArgumentExpression();
58
+ if (arg && containsUserInput(arg)) {
59
+ const loc = getLocation(ea);
60
+ counter++;
61
+ findings.push({
62
+ id: `SAST-PROTO-${String(counter).padStart(3, "0")}`,
63
+ title: "Dynamic Property Access with User Input",
64
+ severity: "medium",
65
+ owasp_mcp: "MCP05",
66
+ owasp_mcp_title: "Command Injection & Code Execution",
67
+ category: "static",
68
+ file: loc.file,
69
+ line: loc.line,
70
+ column: loc.column,
71
+ evidence: ea.getText().substring(0, 200),
72
+ remediation: "Validate property names against an allowlist before using bracket notation with user input. Block __proto__, constructor, prototype.",
73
+ cwe: "CWE-1321",
74
+ });
75
+ }
76
+ }
77
+ }
78
+ return findings;
79
+ }
80
+ //# sourceMappingURL=prototype-pollution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prototype-pollution.js","sourceRoot":"","sources":["../../../src/static/analyzers/prototype-pollution.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { SourceFile } from "ts-morph";
2
+ import type { Finding } from "../../types/findings.js";
3
+ export declare function analyzeRegexDos(sourceFiles: SourceFile[]): Finding[];
4
+ //# sourceMappingURL=regex-dos.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regex-dos.d.ts","sourceRoot":"","sources":["../../../src/static/analyzers/regex-dos.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAWvD,wBAAgB,eAAe,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,OAAO,EAAE,CAuEpE"}
@@ -0,0 +1,78 @@
1
+ import { getLocation, SyntaxKind } from "../ast-engine.js";
2
+ // Patterns that indicate ReDoS vulnerability
3
+ const REDOS_PATTERNS = [
4
+ /\(.*[+*].*\)[+*]/, // Nested quantifiers: (a+)+
5
+ /\(.*\|.*\)[+*]/, // Alternation in quantified group: (a|b)+
6
+ /\([^)]*[+*][^)]*[+*][^)]*\)/, // Multiple quantifiers in group
7
+ /(.)\+\1\+/, // Overlapping quantifiers like a+a+
8
+ ];
9
+ export function analyzeRegexDos(sourceFiles) {
10
+ const findings = [];
11
+ let counter = 0;
12
+ for (const sf of sourceFiles) {
13
+ // Check RegExp literals
14
+ const regexLiterals = sf.getDescendantsOfKind(SyntaxKind.RegularExpressionLiteral);
15
+ for (const regex of regexLiterals) {
16
+ const text = regex.getText();
17
+ // Remove the /flags part to get pattern
18
+ const pattern = text.slice(1, text.lastIndexOf("/"));
19
+ for (const redos of REDOS_PATTERNS) {
20
+ if (redos.test(pattern)) {
21
+ const loc = getLocation(regex);
22
+ counter++;
23
+ findings.push({
24
+ id: `SAST-REDOS-${String(counter).padStart(3, "0")}`,
25
+ title: "Potential ReDoS Pattern",
26
+ severity: "medium",
27
+ owasp_mcp: "MCP05",
28
+ owasp_mcp_title: "Command Injection & Code Execution",
29
+ category: "static",
30
+ file: loc.file,
31
+ line: loc.line,
32
+ column: loc.column,
33
+ evidence: `Regex literal with potential catastrophic backtracking: ${text.substring(0, 100)}`,
34
+ remediation: "Refactor regex to avoid nested quantifiers and overlapping alternations. Consider using a regex engine with backtracking limits.",
35
+ cwe: "CWE-1333",
36
+ });
37
+ break;
38
+ }
39
+ }
40
+ }
41
+ // Check new RegExp() with string arguments for same patterns
42
+ const newExprs = sf.getDescendantsOfKind(SyntaxKind.NewExpression);
43
+ for (const expr of newExprs) {
44
+ if (expr.getExpression().getText() !== "RegExp")
45
+ continue;
46
+ const args = expr.getArguments();
47
+ if (args.length === 0)
48
+ continue;
49
+ const firstArg = args[0];
50
+ if (firstArg.getKind() === SyntaxKind.StringLiteral) {
51
+ const pattern = firstArg.getText().replace(/^['"]|['"]$/g, "");
52
+ for (const redos of REDOS_PATTERNS) {
53
+ if (redos.test(pattern)) {
54
+ const loc = getLocation(expr);
55
+ counter++;
56
+ findings.push({
57
+ id: `SAST-REDOS-${String(counter).padStart(3, "0")}`,
58
+ title: "Potential ReDoS in new RegExp()",
59
+ severity: "medium",
60
+ owasp_mcp: "MCP05",
61
+ owasp_mcp_title: "Command Injection & Code Execution",
62
+ category: "static",
63
+ file: loc.file,
64
+ line: loc.line,
65
+ column: loc.column,
66
+ evidence: `new RegExp() with potential backtracking: ${expr.getText().substring(0, 100)}`,
67
+ remediation: "Refactor regex pattern to avoid nested quantifiers. Consider using a safe regex library.",
68
+ cwe: "CWE-1333",
69
+ });
70
+ break;
71
+ }
72
+ }
73
+ }
74
+ }
75
+ }
76
+ return findings;
77
+ }
78
+ //# sourceMappingURL=regex-dos.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regex-dos.js","sourceRoot":"","sources":["../../../src/static/analyzers/regex-dos.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { SourceFile } from "ts-morph";
2
+ import type { Finding } from "../../types/findings.js";
3
+ export declare function analyzeHardcodedSecrets(sourceFiles: SourceFile[]): Finding[];
4
+ //# sourceMappingURL=secret-hardcoded.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-hardcoded.d.ts","sourceRoot":"","sources":["../../../src/static/analyzers/secret-hardcoded.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAIvD,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,OAAO,EAAE,CAuE5E"}
@@ -0,0 +1,70 @@
1
+ import { findStringLiterals, findTemplateExpressions, getLocation } from "../ast-engine.js";
2
+ import { SECRET_PATTERNS } from "../../data/secret-patterns.js";
3
+ export function analyzeHardcodedSecrets(sourceFiles) {
4
+ const findings = [];
5
+ let counter = 0;
6
+ for (const sf of sourceFiles) {
7
+ // Skip test files
8
+ const filePath = sf.getFilePath();
9
+ if (filePath.includes(".test.") || filePath.includes(".spec.") || filePath.includes("__test__"))
10
+ continue;
11
+ // Check string literals
12
+ const strings = findStringLiterals(sf);
13
+ for (const str of strings) {
14
+ const value = str.getLiteralText();
15
+ if (value.length < 8)
16
+ continue; // Skip short strings
17
+ for (const pattern of SECRET_PATTERNS) {
18
+ if (pattern.pattern.test(value)) {
19
+ const loc = getLocation(str);
20
+ counter++;
21
+ // Mask the secret in evidence
22
+ const masked = value.substring(0, 8) + "..." + value.substring(value.length - 4);
23
+ findings.push({
24
+ id: `SAST-SECRET-${String(counter).padStart(3, "0")}`,
25
+ title: `Hardcoded ${pattern.name}`,
26
+ severity: pattern.severity,
27
+ owasp_mcp: "MCP01",
28
+ owasp_mcp_title: "Excessive Privilege & Token Mismanagement",
29
+ category: "static",
30
+ file: loc.file,
31
+ line: loc.line,
32
+ column: loc.column,
33
+ evidence: `${pattern.name} found in string literal: "${masked}"`,
34
+ remediation: "Move secrets to environment variables. Use process.env to read them at runtime. Never commit secrets to source code.",
35
+ cwe: "CWE-798",
36
+ });
37
+ break; // One finding per string
38
+ }
39
+ }
40
+ }
41
+ // Check template literals
42
+ const templates = findTemplateExpressions(sf);
43
+ for (const tmpl of templates) {
44
+ const text = tmpl.getText();
45
+ for (const pattern of SECRET_PATTERNS) {
46
+ if (pattern.pattern.test(text)) {
47
+ const loc = getLocation(tmpl);
48
+ counter++;
49
+ findings.push({
50
+ id: `SAST-SECRET-${String(counter).padStart(3, "0")}`,
51
+ title: `Hardcoded ${pattern.name} in Template Literal`,
52
+ severity: pattern.severity,
53
+ owasp_mcp: "MCP01",
54
+ owasp_mcp_title: "Excessive Privilege & Token Mismanagement",
55
+ category: "static",
56
+ file: loc.file,
57
+ line: loc.line,
58
+ column: loc.column,
59
+ evidence: `${pattern.name} found in template literal`,
60
+ remediation: "Move secrets to environment variables. Use process.env to read them at runtime.",
61
+ cwe: "CWE-798",
62
+ });
63
+ break;
64
+ }
65
+ }
66
+ }
67
+ }
68
+ return findings;
69
+ }
70
+ //# sourceMappingURL=secret-hardcoded.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-hardcoded.js","sourceRoot":"","sources":["../../../src/static/analyzers/secret-hardcoded.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { SourceFile } from "ts-morph";
2
+ import type { Finding } from "../../types/findings.js";
3
+ export declare function analyzeSsrf(sourceFiles: SourceFile[]): Finding[];
4
+ //# sourceMappingURL=ssrf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssrf.d.ts","sourceRoot":"","sources":["../../../src/static/analyzers/ssrf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAMvD,wBAAgB,WAAW,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,OAAO,EAAE,CAqChE"}
@@ -0,0 +1,39 @@
1
+ import { findCallExpressions, getCallName, getLocation, containsUserInput } from "../ast-engine.js";
2
+ import { getCallEvidence } from "../taint-tracker.js";
3
+ const SSRF_NAMES = new Set(["fetch", "get", "post", "put", "delete", "patch", "request"]);
4
+ export function analyzeSsrf(sourceFiles) {
5
+ const findings = [];
6
+ let counter = 0;
7
+ for (const sf of sourceFiles) {
8
+ const calls = findCallExpressions(sf);
9
+ for (const call of calls) {
10
+ const name = getCallName(call);
11
+ if (!SSRF_NAMES.has(name))
12
+ continue;
13
+ const args = call.getArguments();
14
+ if (args.length === 0)
15
+ continue;
16
+ const firstArg = args[0];
17
+ if (!containsUserInput(firstArg))
18
+ continue;
19
+ const loc = getLocation(call);
20
+ counter++;
21
+ findings.push({
22
+ id: `SAST-SSRF-${String(counter).padStart(3, "0")}`,
23
+ title: `Potential SSRF via ${name}()`,
24
+ severity: "high",
25
+ owasp_mcp: "MCP05",
26
+ owasp_mcp_title: "Command Injection & Code Execution",
27
+ category: "static",
28
+ file: loc.file,
29
+ line: loc.line,
30
+ column: loc.column,
31
+ evidence: getCallEvidence(call),
32
+ remediation: "Validate and allowlist URLs before making requests. Never pass user-controlled input directly as request URLs.",
33
+ cwe: "CWE-918",
34
+ });
35
+ }
36
+ }
37
+ return findings;
38
+ }
39
+ //# sourceMappingURL=ssrf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssrf.js","sourceRoot":"","sources":["../../../src/static/analyzers/ssrf.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACpG,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;AAE1F,MAAM,UAAU,WAAW,CAAC,WAAyB;IACnD,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,mBAAmB,CAAC,EAAE,CAAC,CAAC;QACtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;YAC/B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAS;YAEpC,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;YACjC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS;YAEhC,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACzB,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC;gBAAE,SAAS;YAE3C,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;YAC9B,OAAO,EAAE,CAAC;YAEV,QAAQ,CAAC,IAAI,CAAC;gBACZ,EAAE,EAAE,aAAa,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;gBACnD,KAAK,EAAE,sBAAsB,IAAI,IAAI;gBACrC,QAAQ,EAAE,MAAM;gBAChB,SAAS,EAAE,OAAO;gBAClB,eAAe,EAAE,oCAAoC;gBACrD,QAAQ,EAAE,QAAQ;gBAClB,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,QAAQ,EAAE,eAAe,CAAC,IAAI,CAAC;gBAC/B,WAAW,EAAE,gHAAgH;gBAC7H,GAAG,EAAE,SAAS;aACf,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { SourceFile } from "ts-morph";
2
+ import type { Finding } from "../../types/findings.js";
3
+ export declare function analyzeUnsafeRegex(sourceFiles: SourceFile[]): Finding[];
4
+ //# sourceMappingURL=unsafe-regex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unsafe-regex.d.ts","sourceRoot":"","sources":["../../../src/static/analyzers/unsafe-regex.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAGvD,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,OAAO,EAAE,CAoCvE"}
@@ -0,0 +1,36 @@
1
+ import { findNewRegExpCalls, getLocation, containsUserInput } from "../ast-engine.js";
2
+ export function analyzeUnsafeRegex(sourceFiles) {
3
+ const findings = [];
4
+ let counter = 0;
5
+ for (const sf of sourceFiles) {
6
+ const regexpCalls = findNewRegExpCalls(sf);
7
+ for (const call of regexpCalls) {
8
+ const args = call.getChildrenOfKind(18); // SyntaxList children
9
+ // Get first argument
10
+ const firstArg = call.getChildren().find(c => {
11
+ const kind = c.getKindName();
12
+ return kind === "SyntaxList";
13
+ });
14
+ if (containsUserInput(call)) {
15
+ const loc = getLocation(call);
16
+ counter++;
17
+ findings.push({
18
+ id: `SAST-REGEX-${String(counter).padStart(3, "0")}`,
19
+ title: "User Input in new RegExp()",
20
+ severity: "high",
21
+ owasp_mcp: "MCP05",
22
+ owasp_mcp_title: "Command Injection & Code Execution",
23
+ category: "static",
24
+ file: loc.file,
25
+ line: loc.line,
26
+ column: loc.column,
27
+ evidence: call.getText().substring(0, 200),
28
+ remediation: "Escape user input before passing to new RegExp(). Use a function like escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'); }",
29
+ cwe: "CWE-185",
30
+ });
31
+ }
32
+ }
33
+ }
34
+ return findings;
35
+ }
36
+ //# sourceMappingURL=unsafe-regex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unsafe-regex.js","sourceRoot":"","sources":["../../../src/static/analyzers/unsafe-regex.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAEtF,MAAM,UAAU,kBAAkB,CAAC,WAAyB;IAC1D,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;QAC7B,MAAM,WAAW,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAAC;QAC3C,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;YAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,sBAAsB;YAC/D,qBAAqB;YACrB,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;gBAC3C,MAAM,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;gBAC7B,OAAO,IAAI,KAAK,YAAY,CAAC;YAC/B,CAAC,CAAC,CAAC;YAEH,IAAI,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC5B,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;gBAC9B,OAAO,EAAE,CAAC;gBACV,QAAQ,CAAC,IAAI,CAAC;oBACZ,EAAE,EAAE,cAAc,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;oBACpD,KAAK,EAAE,4BAA4B;oBACnC,QAAQ,EAAE,MAAM;oBAChB,SAAS,EAAE,OAAO;oBAClB,eAAe,EAAE,oCAAoC;oBACrD,QAAQ,EAAE,QAAQ;oBAClB,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,MAAM,EAAE,GAAG,CAAC,MAAM;oBAClB,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC;oBAC1C,WAAW,EAAE,qJAAqJ;oBAClK,GAAG,EAAE,SAAS;iBACf,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { Project, SourceFile, SyntaxKind, Node, CallExpression, StringLiteral } from "ts-morph";
2
+ export interface AstProject {
3
+ project: Project;
4
+ sourceFiles: SourceFile[];
5
+ rootDir: string;
6
+ }
7
+ export declare function initProject(path: string, tsconfigPath?: string): AstProject;
8
+ export declare function findCallExpressions(sourceFile: SourceFile): CallExpression[];
9
+ export declare function getCallName(call: CallExpression): string;
10
+ export declare function getQualifiedCallName(call: CallExpression): string;
11
+ export declare function containsUserInput(node: Node): boolean;
12
+ export declare function getLocation(node: Node): {
13
+ file: string;
14
+ line: number;
15
+ column: number;
16
+ };
17
+ export declare function findStringLiterals(sourceFile: SourceFile): StringLiteral[];
18
+ export declare function findTemplateExpressions(sourceFile: SourceFile): Node[];
19
+ export declare function hasShellTrue(call: CallExpression): boolean;
20
+ export declare function findNewRegExpCalls(sourceFile: SourceFile): Node[];
21
+ export { SyntaxKind, Node, type SourceFile, type CallExpression };
22
+ //# sourceMappingURL=ast-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-engine.d.ts","sourceRoot":"","sources":["../../src/static/ast-engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,cAAc,EAAE,aAAa,EAA4D,MAAM,UAAU,CAAC;AAG1J,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,UAAU,CAoD3E;AAGD,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,UAAU,GAAG,cAAc,EAAE,CAE5E;AAGD,wBAAgB,WAAW,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CAcxD;AAGD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CAejE;AAGD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CA8BrD;AAGD,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAStF;AAGD,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,UAAU,GAAG,aAAa,EAAE,CAE1E;AAGD,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,EAAE,CAKtE;AAGD,wBAAgB,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAO1D;AAGD,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,EAAE,CAYjE;AAED,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,UAAU,EAAE,KAAK,cAAc,EAAE,CAAC"}
@@ -0,0 +1,155 @@
1
+ import { Project, SyntaxKind, Node } from "ts-morph";
2
+ import { resolve } from "node:path";
3
+ export function initProject(path, tsconfigPath) {
4
+ const rootDir = resolve(path);
5
+ const project = new Project({
6
+ compilerOptions: {
7
+ allowJs: true,
8
+ checkJs: false,
9
+ noEmit: true,
10
+ skipLibCheck: true,
11
+ target: 99, // ESNext
12
+ module: 99, // ESNext
13
+ },
14
+ skipAddingFilesFromTsConfig: true,
15
+ skipFileDependencyResolution: true,
16
+ });
17
+ // Discover and add source files
18
+ const globs = [
19
+ `${rootDir}/**/*.ts`,
20
+ `${rootDir}/**/*.js`,
21
+ `${rootDir}/**/*.mts`,
22
+ `${rootDir}/**/*.mjs`,
23
+ ];
24
+ const excludeGlobs = [
25
+ `${rootDir}/node_modules/**`,
26
+ `${rootDir}/dist/**`,
27
+ `${rootDir}/.git/**`,
28
+ `${rootDir}/**/*.d.ts`,
29
+ ];
30
+ project.addSourceFilesAtPaths(globs);
31
+ // Remove excluded files
32
+ for (const sf of project.getSourceFiles()) {
33
+ const fp = sf.getFilePath();
34
+ if (excludeGlobs.some(g => {
35
+ const base = g.replace("/**", "");
36
+ return fp.includes(base.replace(`${rootDir}/`, ""));
37
+ })) {
38
+ // Simplistic: check if path contains node_modules, dist, .git, or ends with .d.ts
39
+ }
40
+ }
41
+ const sourceFiles = project.getSourceFiles().filter(sf => {
42
+ const fp = sf.getFilePath();
43
+ return !fp.includes("/node_modules/") &&
44
+ !fp.includes("/dist/") &&
45
+ !fp.includes("/.git/") &&
46
+ !fp.endsWith(".d.ts");
47
+ });
48
+ return { project, sourceFiles, rootDir };
49
+ }
50
+ // Helper: find all call expressions in a source file
51
+ export function findCallExpressions(sourceFile) {
52
+ return sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression);
53
+ }
54
+ // Helper: get the function/method name from a call expression
55
+ export function getCallName(call) {
56
+ const expr = call.getExpression();
57
+ // Simple call: exec(...)
58
+ if (Node.isIdentifier(expr)) {
59
+ return expr.getText();
60
+ }
61
+ // Property access: child_process.exec(...), fs.readFile(...)
62
+ if (Node.isPropertyAccessExpression(expr)) {
63
+ return expr.getName();
64
+ }
65
+ return expr.getText();
66
+ }
67
+ // Helper: get the full qualified call name like "child_process.exec" or "fs.readFile"
68
+ export function getQualifiedCallName(call) {
69
+ const expr = call.getExpression();
70
+ if (Node.isPropertyAccessExpression(expr)) {
71
+ const obj = expr.getExpression();
72
+ if (Node.isIdentifier(obj)) {
73
+ return `${obj.getText()}.${expr.getName()}`;
74
+ }
75
+ }
76
+ if (Node.isIdentifier(expr)) {
77
+ return expr.getText();
78
+ }
79
+ return expr.getText();
80
+ }
81
+ // Helper: check if an expression contains user input (function params, args.*, etc)
82
+ export function containsUserInput(node) {
83
+ const text = node.getText();
84
+ // Check for common user input patterns
85
+ const userInputPatterns = [
86
+ /\bargs\b/, // MCP tool args
87
+ /\breq\.query\b/, // Express query
88
+ /\breq\.params\b/, // Express params
89
+ /\breq\.body\b/, // Express body
90
+ /\breq\.headers\b/, // Express headers
91
+ /\bparams\b/, // Generic params
92
+ /\binput\b/, // Generic input
93
+ /\buserInput\b/, // Generic userInput
94
+ ];
95
+ if (userInputPatterns.some(p => p.test(text)))
96
+ return true;
97
+ // Check for template literals with interpolations
98
+ if (node.getKind() === SyntaxKind.TemplateExpression)
99
+ return true;
100
+ // Check for identifiers that trace to function parameters
101
+ const identifiers = node.getDescendantsOfKind(SyntaxKind.Identifier);
102
+ for (const id of identifiers) {
103
+ const name = id.getText();
104
+ if (["args", "params", "input", "query", "body", "userInput", "data", "payload"].includes(name)) {
105
+ return true;
106
+ }
107
+ }
108
+ return false;
109
+ }
110
+ // Helper: get location info
111
+ export function getLocation(node) {
112
+ const sf = node.getSourceFile();
113
+ const start = node.getStart();
114
+ const { line, column } = sf.getLineAndColumnAtPos(start);
115
+ return {
116
+ file: sf.getFilePath(),
117
+ line,
118
+ column,
119
+ };
120
+ }
121
+ // Helper: get all string literals in a file
122
+ export function findStringLiterals(sourceFile) {
123
+ return sourceFile.getDescendantsOfKind(SyntaxKind.StringLiteral);
124
+ }
125
+ // Helper: get all template expressions (template literals with interpolation)
126
+ export function findTemplateExpressions(sourceFile) {
127
+ return [
128
+ ...sourceFile.getDescendantsOfKind(SyntaxKind.TemplateExpression),
129
+ ...sourceFile.getDescendantsOfKind(SyntaxKind.NoSubstitutionTemplateLiteral),
130
+ ];
131
+ }
132
+ // Helper: check if a call has shell:true in options
133
+ export function hasShellTrue(call) {
134
+ const args = call.getArguments();
135
+ for (const arg of args) {
136
+ const text = arg.getText();
137
+ if (/shell\s*:\s*true/.test(text))
138
+ return true;
139
+ }
140
+ return false;
141
+ }
142
+ // Helper: find new RegExp() calls
143
+ export function findNewRegExpCalls(sourceFile) {
144
+ const results = [];
145
+ // new RegExp(...)
146
+ const newExprs = sourceFile.getDescendantsOfKind(SyntaxKind.NewExpression);
147
+ for (const expr of newExprs) {
148
+ if (expr.getExpression().getText() === "RegExp") {
149
+ results.push(expr);
150
+ }
151
+ }
152
+ return results;
153
+ }
154
+ export { SyntaxKind, Node };
155
+ //# sourceMappingURL=ast-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-engine.js","sourceRoot":"","sources":["../../src/static/ast-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ToolDef } from "../types/index.js";
2
+ export declare const staticTools: ToolDef[];
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/static/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAqHjD,eAAO,MAAM,WAAW,EAAE,OAAO,EAyDhC,CAAC"}