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,308 @@
1
+ import { z } from "zod";
2
+ import { join } from "node:path";
3
+ import { text } from "../types/index.js";
4
+ import { parseLockfile, parsePackageJson } from "./lockfile-parser.js";
5
+ import { checkTyposquatting, typosquatFindings } from "./typosquat-checker.js";
6
+ import { detectInstallScripts, installScriptFindings } from "./install-script-detector.js";
7
+ import { safeReadJson, fileExists } from "../utils/fs-helpers.js";
8
+ function formatFindings(findings) {
9
+ if (findings.length === 0)
10
+ return "No findings.";
11
+ const bySeverity = { critical: 0, high: 0, medium: 0, low: 0, info: 0 };
12
+ for (const f of findings)
13
+ bySeverity[f.severity]++;
14
+ let output = `${findings.length} finding(s): ${bySeverity.critical} critical, ${bySeverity.high} high, ${bySeverity.medium} medium, ${bySeverity.low} low, ${bySeverity.info} info\n\n`;
15
+ for (const f of findings) {
16
+ output += `[${f.severity.toUpperCase()}] ${f.id}: ${f.title}\n`;
17
+ if (f.file)
18
+ output += ` File: ${f.file}\n`;
19
+ output += ` OWASP: ${f.owasp_mcp} — ${f.owasp_mcp_title}\n`;
20
+ output += ` Evidence: ${f.evidence}\n`;
21
+ output += ` Remediation: ${f.remediation}\n\n`;
22
+ }
23
+ return output.trim();
24
+ }
25
+ const depAuditLockfile = {
26
+ name: "dep_audit_lockfile",
27
+ description: "Parse lockfile (package-lock.json v2/v3, bun.lock) and list all dependencies with versions. Provides dependency tree overview for manual review.",
28
+ schema: {
29
+ path: z.string().describe("Project directory containing lockfile"),
30
+ },
31
+ async execute(args) {
32
+ const lockfile = await parseLockfile(args.path);
33
+ if (!lockfile)
34
+ return text(`No lockfile found in ${args.path}. Check that package-lock.json or bun.lock exists.`);
35
+ let output = `Lockfile: ${lockfile.lockfilePath} (${lockfile.lockfileType})\n`;
36
+ output += `Dependencies: ${lockfile.dependencies.length}\n\n`;
37
+ if (lockfile.dependencies.length > 0) {
38
+ const direct = lockfile.dependencies.filter(d => !d.name.includes(" > "));
39
+ const transitive = lockfile.dependencies.filter(d => d.name.includes(" > "));
40
+ output += `Direct: ${direct.length}, Transitive: ${transitive.length}\n\n`;
41
+ for (const dep of direct.slice(0, 100)) {
42
+ output += ` ${dep.name}@${dep.version}${dep.dev ? " (dev)" : ""}\n`;
43
+ }
44
+ if (direct.length > 100) {
45
+ output += ` ... and ${direct.length - 100} more\n`;
46
+ }
47
+ }
48
+ return text(output.trim());
49
+ },
50
+ };
51
+ const depCheckTyposquatting = {
52
+ name: "dep_check_typosquatting",
53
+ description: "Check all dependency names against top popular npm packages using: Levenshtein distance, keyboard-adjacent substitution, vowel swapping, separator confusion, scope squatting.",
54
+ schema: {
55
+ path: z.string().describe("Project directory containing package.json"),
56
+ ecosystem: z.string().optional().describe("Package ecosystem (default: npm)"),
57
+ },
58
+ async execute(args) {
59
+ const deps = await parsePackageJson(args.path);
60
+ if (!deps)
61
+ return text(`No package.json found in ${args.path}`);
62
+ const depNames = Object.keys(deps);
63
+ const matches = checkTyposquatting(depNames);
64
+ if (matches.length === 0) {
65
+ return text(`Checked ${depNames.length} dependencies — no typosquatting detected.`);
66
+ }
67
+ const findings = typosquatFindings(matches, join(args.path, "package.json"));
68
+ return text(formatFindings(findings));
69
+ },
70
+ };
71
+ const depCheckUnpinned = {
72
+ name: "dep_check_unpinned",
73
+ description: "Detect dependencies with unpinned version ranges: caret (^), tilde (~), star (*), greater-than (>=). Unpinned versions allow silent malicious updates.",
74
+ schema: {
75
+ path: z.string().describe("Project directory containing package.json"),
76
+ },
77
+ async execute(args) {
78
+ const deps = await parsePackageJson(args.path);
79
+ if (!deps)
80
+ return text(`No package.json found in ${args.path}`);
81
+ const findings = [];
82
+ let counter = 0;
83
+ const pkgJsonPath = join(args.path, "package.json");
84
+ // Check if lockfile exists
85
+ const hasLockfile = await fileExists(join(args.path, "package-lock.json")) ||
86
+ await fileExists(join(args.path, "bun.lock")) ||
87
+ await fileExists(join(args.path, "bun.lockb"));
88
+ if (!hasLockfile) {
89
+ counter++;
90
+ findings.push({
91
+ id: `DEP-PIN-${String(counter).padStart(3, "0")}`,
92
+ title: "No Lockfile Found",
93
+ severity: "high",
94
+ owasp_mcp: "MCP04",
95
+ owasp_mcp_title: "Supply Chain & Dependency Vulnerabilities",
96
+ category: "deps",
97
+ file: pkgJsonPath,
98
+ evidence: "No package-lock.json or bun.lock found — dependency resolution is non-deterministic",
99
+ remediation: "Run npm install or bun install to generate a lockfile. Commit the lockfile to version control.",
100
+ cwe: "CWE-1357",
101
+ });
102
+ }
103
+ for (const [name, version] of Object.entries(deps)) {
104
+ let issue = null;
105
+ if (version === "*" || version === "latest") {
106
+ issue = `"${version}" — matches ANY version`;
107
+ }
108
+ else if (version.startsWith("^")) {
109
+ issue = `"${version}" — caret range allows minor/patch updates`;
110
+ }
111
+ else if (version.startsWith("~")) {
112
+ issue = `"${version}" — tilde range allows patch updates`;
113
+ }
114
+ else if (version.startsWith(">=") || version.startsWith(">")) {
115
+ issue = `"${version}" — open-ended range`;
116
+ }
117
+ if (issue) {
118
+ counter++;
119
+ findings.push({
120
+ id: `DEP-PIN-${String(counter).padStart(3, "0")}`,
121
+ title: `Unpinned Version: ${name}`,
122
+ severity: version === "*" || version === "latest" ? "high" : "low",
123
+ owasp_mcp: "MCP04",
124
+ owasp_mcp_title: "Supply Chain & Dependency Vulnerabilities",
125
+ category: "deps",
126
+ file: pkgJsonPath,
127
+ evidence: `${name}: ${issue}`,
128
+ remediation: hasLockfile
129
+ ? "Version range is mitigated by lockfile presence. For maximum security, pin to exact versions."
130
+ : "Pin to exact version (e.g. \"1.2.3\" without ^ or ~). Generate and commit a lockfile.",
131
+ cwe: "CWE-1357",
132
+ });
133
+ }
134
+ }
135
+ return text(formatFindings(findings));
136
+ },
137
+ };
138
+ const depCheckInstallScripts = {
139
+ name: "dep_check_install_scripts",
140
+ description: "Detect dependencies with lifecycle scripts (preinstall, install, postinstall, prepare) that execute during npm/bun install with full system access.",
141
+ schema: {
142
+ path: z.string().describe("Project directory with node_modules"),
143
+ },
144
+ async execute(args) {
145
+ const results = await detectInstallScripts(args.path);
146
+ if (results.length === 0) {
147
+ return text("No dependencies with install scripts found.");
148
+ }
149
+ const lockfile = await parseLockfile(args.path);
150
+ const lockfilePath = lockfile?.lockfilePath ?? join(args.path, "package.json");
151
+ const findings = installScriptFindings(results, lockfilePath);
152
+ return text(formatFindings(findings));
153
+ },
154
+ };
155
+ const depCheckMcpSdkVersion = {
156
+ name: "dep_check_mcp_sdk_version",
157
+ description: "Check the installed @modelcontextprotocol/sdk version against known vulnerable versions and latest features (OAuth 2.1 support, etc).",
158
+ schema: {
159
+ path: z.string().describe("Project directory"),
160
+ },
161
+ async execute(args) {
162
+ const findings = [];
163
+ let counter = 0;
164
+ // Check package.json for declared version
165
+ const deps = await parsePackageJson(args.path);
166
+ const sdkVersion = deps?.["@modelcontextprotocol/sdk"];
167
+ if (!sdkVersion) {
168
+ return text("@modelcontextprotocol/sdk not found in dependencies.");
169
+ }
170
+ // Check installed version from node_modules
171
+ const installedPkgPath = join(args.path, "node_modules", "@modelcontextprotocol", "sdk", "package.json");
172
+ const installedPkg = await safeReadJson(installedPkgPath);
173
+ const installedVersion = installedPkg?.version;
174
+ const pkgJsonPath = join(args.path, "package.json");
175
+ let output = `@modelcontextprotocol/sdk\n`;
176
+ output += ` Declared: ${sdkVersion}\n`;
177
+ output += ` Installed: ${installedVersion ?? "not installed"}\n\n`;
178
+ // Known vulnerable versions (CVE-2025-6514 affects mcp-remote, not core SDK, but flag old versions)
179
+ if (installedVersion) {
180
+ const [major, minor, patch] = installedVersion.split(".").map(Number);
181
+ if (major === 0 || (major === 1 && minor < 10)) {
182
+ counter++;
183
+ findings.push({
184
+ id: `DEP-SDK-${String(counter).padStart(3, "0")}`,
185
+ title: "Outdated MCP SDK Version",
186
+ severity: "medium",
187
+ owasp_mcp: "MCP04",
188
+ owasp_mcp_title: "Supply Chain & Dependency Vulnerabilities",
189
+ category: "deps",
190
+ file: pkgJsonPath,
191
+ evidence: `@modelcontextprotocol/sdk@${installedVersion} — pre-1.10 versions may lack security fixes`,
192
+ remediation: "Update to the latest @modelcontextprotocol/sdk version for security patches and OAuth 2.1 support.",
193
+ cwe: "CWE-1104",
194
+ });
195
+ }
196
+ }
197
+ output += formatFindings(findings);
198
+ return text(output);
199
+ },
200
+ };
201
+ const depCheckDeprecated = {
202
+ name: "dep_check_deprecated",
203
+ description: "Detect deprecated dependencies by checking package.json 'deprecated' field in node_modules. Deprecated packages no longer receive security patches.",
204
+ schema: {
205
+ path: z.string().describe("Project directory with node_modules"),
206
+ },
207
+ async execute(args) {
208
+ const findings = [];
209
+ let counter = 0;
210
+ const lockfile = await parseLockfile(args.path);
211
+ if (!lockfile || lockfile.dependencies.length === 0) {
212
+ return text("No lockfile or dependencies found.");
213
+ }
214
+ const pkgJsonPath = join(args.path, "package.json");
215
+ for (const dep of lockfile.dependencies) {
216
+ // Only check direct deps (not transitive)
217
+ if (dep.name.includes(" > "))
218
+ continue;
219
+ const depPkgPath = join(args.path, "node_modules", dep.name, "package.json");
220
+ const depPkg = await safeReadJson(depPkgPath);
221
+ if (!depPkg)
222
+ continue;
223
+ if (depPkg.deprecated) {
224
+ counter++;
225
+ findings.push({
226
+ id: `DEP-DEPR-${String(counter).padStart(3, "0")}`,
227
+ title: `Deprecated Package: ${dep.name}`,
228
+ severity: "medium",
229
+ owasp_mcp: "MCP04",
230
+ owasp_mcp_title: "Supply Chain & Dependency Vulnerabilities",
231
+ category: "deps",
232
+ file: pkgJsonPath,
233
+ evidence: `${dep.name}@${dep.version} — ${String(depPkg.deprecated).substring(0, 200)}`,
234
+ remediation: `Replace ${dep.name} with its recommended successor or remove it.`,
235
+ cwe: "CWE-1104",
236
+ });
237
+ }
238
+ }
239
+ return text(formatFindings(findings));
240
+ },
241
+ };
242
+ const depCheckLicense = {
243
+ name: "dep_check_license",
244
+ description: "Audit dependency licenses: copyleft (GPL, AGPL), unknown/missing licenses, non-OSI-approved licenses. Important for MCP servers in enterprise environments.",
245
+ schema: {
246
+ path: z.string().describe("Project directory with node_modules"),
247
+ },
248
+ async execute(args) {
249
+ const findings = [];
250
+ let counter = 0;
251
+ const lockfile = await parseLockfile(args.path);
252
+ if (!lockfile || lockfile.dependencies.length === 0) {
253
+ return text("No lockfile or dependencies found.");
254
+ }
255
+ const pkgJsonPath = join(args.path, "package.json");
256
+ const COPYLEFT = ["GPL", "AGPL", "LGPL", "SSPL", "EUPL", "MPL"];
257
+ for (const dep of lockfile.dependencies) {
258
+ if (dep.name.includes(" > "))
259
+ continue;
260
+ const depPkgPath = join(args.path, "node_modules", dep.name, "package.json");
261
+ const depPkg = await safeReadJson(depPkgPath);
262
+ if (!depPkg)
263
+ continue;
264
+ const license = depPkg.license;
265
+ if (!license) {
266
+ counter++;
267
+ findings.push({
268
+ id: `DEP-LIC-${String(counter).padStart(3, "0")}`,
269
+ title: `Missing License: ${dep.name}`,
270
+ severity: "low",
271
+ owasp_mcp: "MCP04",
272
+ owasp_mcp_title: "Supply Chain & Dependency Vulnerabilities",
273
+ category: "deps",
274
+ file: pkgJsonPath,
275
+ evidence: `${dep.name}@${dep.version} — no license field in package.json`,
276
+ remediation: `Verify the license of ${dep.name} manually. Missing license may indicate usage restrictions.`,
277
+ cwe: "CWE-1357",
278
+ });
279
+ }
280
+ else if (COPYLEFT.some(c => license.toUpperCase().includes(c))) {
281
+ counter++;
282
+ findings.push({
283
+ id: `DEP-LIC-${String(counter).padStart(3, "0")}`,
284
+ title: `Copyleft License: ${dep.name} (${license})`,
285
+ severity: "info",
286
+ owasp_mcp: "MCP04",
287
+ owasp_mcp_title: "Supply Chain & Dependency Vulnerabilities",
288
+ category: "deps",
289
+ file: pkgJsonPath,
290
+ evidence: `${dep.name}@${dep.version} — license: ${license} (copyleft)`,
291
+ remediation: `Review copyleft obligations for ${license}. Copyleft licenses may require source disclosure.`,
292
+ cwe: "CWE-1357",
293
+ });
294
+ }
295
+ }
296
+ return text(formatFindings(findings));
297
+ },
298
+ };
299
+ export const depsTools = [
300
+ depAuditLockfile,
301
+ depCheckTyposquatting,
302
+ depCheckUnpinned,
303
+ depCheckInstallScripts,
304
+ depCheckMcpSdkVersion,
305
+ depCheckDeprecated,
306
+ depCheckLicense,
307
+ ];
308
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/deps/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { Finding } from "../types/findings.js";
2
+ export interface InstallScriptResult {
3
+ package: string;
4
+ version: string;
5
+ scripts: Record<string, string>;
6
+ }
7
+ export declare function detectInstallScripts(projectPath: string): Promise<InstallScriptResult[]>;
8
+ export declare function installScriptFindings(results: InstallScriptResult[], lockfilePath: string): Finding[];
9
+ //# sourceMappingURL=install-script-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-script-detector.d.ts","sourceRoot":"","sources":["../../src/deps/install-script-detector.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAIpD,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAqC9F;AA0BD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,mBAAmB,EAAE,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,EAAE,CAkCrG"}
@@ -0,0 +1,98 @@
1
+ import { join } from "node:path";
2
+ import { safeReadJson } from "../utils/fs-helpers.js";
3
+ import { readdir } from "node:fs/promises";
4
+ const DANGEROUS_SCRIPTS = ["preinstall", "install", "postinstall", "prepare"];
5
+ export async function detectInstallScripts(projectPath) {
6
+ const results = [];
7
+ const nodeModulesPath = join(projectPath, "node_modules");
8
+ let entries;
9
+ try {
10
+ entries = await readdir(nodeModulesPath, { withFileTypes: true });
11
+ }
12
+ catch {
13
+ return results;
14
+ }
15
+ for (const entry of entries) {
16
+ if (!entry.isDirectory())
17
+ continue;
18
+ if (entry.name.startsWith("@")) {
19
+ // Scoped package — look one level deeper
20
+ const scopePath = join(nodeModulesPath, entry.name);
21
+ let scopeEntries;
22
+ try {
23
+ scopeEntries = await readdir(scopePath, { withFileTypes: true });
24
+ }
25
+ catch {
26
+ continue;
27
+ }
28
+ for (const scopeEntry of scopeEntries) {
29
+ if (!scopeEntry.isDirectory())
30
+ continue;
31
+ const fullName = `${entry.name}/${scopeEntry.name}`;
32
+ const result = await checkPackageScripts(nodeModulesPath, fullName);
33
+ if (result)
34
+ results.push(result);
35
+ }
36
+ }
37
+ else if (!entry.name.startsWith(".")) {
38
+ const result = await checkPackageScripts(nodeModulesPath, entry.name);
39
+ if (result)
40
+ results.push(result);
41
+ }
42
+ }
43
+ return results;
44
+ }
45
+ async function checkPackageScripts(nodeModulesPath, packageName) {
46
+ const pkgJsonPath = join(nodeModulesPath, packageName, "package.json");
47
+ const pkg = await safeReadJson(pkgJsonPath);
48
+ if (!pkg)
49
+ return null;
50
+ const scripts = pkg.scripts;
51
+ if (!scripts)
52
+ return null;
53
+ const dangerousScripts = {};
54
+ for (const scriptName of DANGEROUS_SCRIPTS) {
55
+ if (scripts[scriptName]) {
56
+ dangerousScripts[scriptName] = scripts[scriptName];
57
+ }
58
+ }
59
+ if (Object.keys(dangerousScripts).length === 0)
60
+ return null;
61
+ return {
62
+ package: packageName,
63
+ version: pkg.version ?? "unknown",
64
+ scripts: dangerousScripts,
65
+ };
66
+ }
67
+ export function installScriptFindings(results, lockfilePath) {
68
+ const findings = [];
69
+ let counter = 0;
70
+ for (const result of results) {
71
+ for (const [scriptName, scriptContent] of Object.entries(result.scripts)) {
72
+ counter++;
73
+ // Determine severity based on script content
74
+ let severity = "medium";
75
+ const lowerContent = scriptContent.toLowerCase();
76
+ if (/curl|wget|http|eval|exec|\.sh|bash|powershell|cmd/.test(lowerContent)) {
77
+ severity = "high";
78
+ }
79
+ if (/rm\s+-rf|del\s+\/|format\s+/.test(lowerContent)) {
80
+ severity = "critical";
81
+ }
82
+ findings.push({
83
+ id: `DEP-SCRIPT-${String(counter).padStart(3, "0")}`,
84
+ title: `Install Script in ${result.package}: ${scriptName}`,
85
+ severity,
86
+ owasp_mcp: "MCP04",
87
+ owasp_mcp_title: "Supply Chain & Dependency Vulnerabilities",
88
+ category: "deps",
89
+ file: lockfilePath,
90
+ evidence: `${result.package}@${result.version} — ${scriptName}: "${scriptContent.substring(0, 200)}"`,
91
+ remediation: `Review the ${scriptName} script in ${result.package}. Consider using --ignore-scripts during install if the script is unnecessary.`,
92
+ cwe: "CWE-829",
93
+ });
94
+ }
95
+ }
96
+ return findings;
97
+ }
98
+ //# sourceMappingURL=install-script-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-script-detector.js","sourceRoot":"","sources":["../../src/deps/install-script-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export interface ParsedDependency {
2
+ name: string;
3
+ version: string;
4
+ resolved?: string;
5
+ integrity?: string;
6
+ dev?: boolean;
7
+ }
8
+ export interface LockfileResult {
9
+ lockfileType: "package-lock-v2" | "package-lock-v3" | "bun-lock" | "unknown";
10
+ lockfilePath: string;
11
+ dependencies: ParsedDependency[];
12
+ }
13
+ export declare function parseLockfile(projectPath: string): Promise<LockfileResult | null>;
14
+ export declare function parsePackageJson(projectPath: string): Promise<Record<string, string> | null>;
15
+ //# sourceMappingURL=lockfile-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lockfile-parser.d.ts","sourceRoot":"","sources":["../../src/deps/lockfile-parser.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,iBAAiB,GAAG,iBAAiB,GAAG,UAAU,GAAG,SAAS,CAAC;IAC7E,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,gBAAgB,EAAE,CAAC;CAClC;AAED,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CA8BvF;AAqFD,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC,CAalG"}
@@ -0,0 +1,123 @@
1
+ import { join } from "node:path";
2
+ import { safeReadJson, safeReadFile, fileExists } from "../utils/fs-helpers.js";
3
+ export async function parseLockfile(projectPath) {
4
+ // Try package-lock.json first
5
+ const npmLockPath = join(projectPath, "package-lock.json");
6
+ if (await fileExists(npmLockPath)) {
7
+ const data = await safeReadJson(npmLockPath);
8
+ if (data) {
9
+ return parseNpmLock(data, npmLockPath);
10
+ }
11
+ }
12
+ // Try bun.lock (JSONC format or text)
13
+ const bunLockPath = join(projectPath, "bun.lock");
14
+ if (await fileExists(bunLockPath)) {
15
+ const content = await safeReadFile(bunLockPath);
16
+ if (content) {
17
+ return parseBunLock(content, bunLockPath);
18
+ }
19
+ }
20
+ // Try bun.lockb (binary — can't parse, just note it exists)
21
+ const bunLockbPath = join(projectPath, "bun.lockb");
22
+ if (await fileExists(bunLockbPath)) {
23
+ return {
24
+ lockfileType: "bun-lock",
25
+ lockfilePath: bunLockbPath,
26
+ dependencies: [],
27
+ };
28
+ }
29
+ return null;
30
+ }
31
+ function parseNpmLock(data, path) {
32
+ const version = data.lockfileVersion ?? 1;
33
+ const deps = [];
34
+ if (version >= 2 && data.packages) {
35
+ // v2/v3 format uses "packages" map
36
+ const packages = data.packages;
37
+ for (const [key, pkg] of Object.entries(packages)) {
38
+ if (!key || key === "")
39
+ continue; // Skip root
40
+ // Key format: "node_modules/pkg-name" or "node_modules/@scope/pkg-name"
41
+ const name = key.replace(/^node_modules\//, "").replace(/\/node_modules\//g, " > ");
42
+ const pkgVersion = pkg.version ?? "unknown";
43
+ deps.push({
44
+ name,
45
+ version: pkgVersion,
46
+ resolved: pkg.resolved,
47
+ integrity: pkg.integrity,
48
+ dev: pkg.dev,
49
+ });
50
+ }
51
+ }
52
+ else if (data.dependencies) {
53
+ // v1 format
54
+ const dependencies = data.dependencies;
55
+ for (const [name, pkg] of Object.entries(dependencies)) {
56
+ deps.push({
57
+ name,
58
+ version: pkg.version ?? "unknown",
59
+ resolved: pkg.resolved,
60
+ integrity: pkg.integrity,
61
+ dev: pkg.dev,
62
+ });
63
+ }
64
+ }
65
+ return {
66
+ lockfileType: version >= 3 ? "package-lock-v3" : "package-lock-v2",
67
+ lockfilePath: path,
68
+ dependencies: deps,
69
+ };
70
+ }
71
+ function parseBunLock(content, path) {
72
+ const deps = [];
73
+ // Bun.lock is a JSONC-like format. Try to parse it.
74
+ try {
75
+ // Strip comments and parse
76
+ const cleaned = content.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
77
+ const data = JSON.parse(cleaned);
78
+ if (data.packages) {
79
+ const packages = data.packages;
80
+ for (const [key, value] of Object.entries(packages)) {
81
+ if (Array.isArray(value)) {
82
+ // Bun lock format: [version, url, hash, ...]
83
+ deps.push({
84
+ name: key,
85
+ version: value[0] ?? "unknown",
86
+ resolved: value[1],
87
+ integrity: value[2],
88
+ });
89
+ }
90
+ }
91
+ }
92
+ }
93
+ catch {
94
+ // If JSON parsing fails, try line-by-line extraction
95
+ const lines = content.split("\n");
96
+ for (const line of lines) {
97
+ const match = line.match(/"([^"]+)":\s*\["([^"]+)"/);
98
+ if (match) {
99
+ deps.push({ name: match[1], version: match[2] });
100
+ }
101
+ }
102
+ }
103
+ return {
104
+ lockfileType: "bun-lock",
105
+ lockfilePath: path,
106
+ dependencies: deps,
107
+ };
108
+ }
109
+ export async function parsePackageJson(projectPath) {
110
+ const pkgPath = join(projectPath, "package.json");
111
+ const pkg = await safeReadJson(pkgPath);
112
+ if (!pkg)
113
+ return null;
114
+ const allDeps = {};
115
+ const deps = pkg.dependencies;
116
+ const devDeps = pkg.devDependencies;
117
+ if (deps)
118
+ Object.assign(allDeps, deps);
119
+ if (devDeps)
120
+ Object.assign(allDeps, devDeps);
121
+ return allDeps;
122
+ }
123
+ //# sourceMappingURL=lockfile-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lockfile-parser.js","sourceRoot":"","sources":["../../src/deps/lockfile-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { Finding } from "../types/findings.js";
2
+ export interface TyposquatMatch {
3
+ dependency: string;
4
+ target: string;
5
+ method: string;
6
+ distance?: number;
7
+ }
8
+ export declare function checkTyposquatting(depNames: string[]): TyposquatMatch[];
9
+ export declare function typosquatFindings(matches: TyposquatMatch[], filePath: string): Finding[];
10
+ //# sourceMappingURL=typosquat-checker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typosquat-checker.d.ts","sourceRoot":"","sources":["../../src/deps/typosquat-checker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEpD,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,CA0EvE;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,CAaxF"}