@cybedefend/vibedefend 1.5.0 → 1.7.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 (264) hide show
  1. package/README.md +71 -2
  2. package/dist/api/gateway-request.js +49 -0
  3. package/dist/api/gateway-request.js.map +1 -0
  4. package/dist/api/projects.js +67 -0
  5. package/dist/api/projects.js.map +1 -1
  6. package/dist/api/repository-link.js +157 -0
  7. package/dist/api/repository-link.js.map +1 -0
  8. package/dist/auth/auth-store.js +107 -25
  9. package/dist/auth/auth-store.js.map +1 -1
  10. package/dist/auth/auth.js +21 -0
  11. package/dist/auth/auth.js.map +1 -1
  12. package/dist/clients/cursor.js +5 -1
  13. package/dist/clients/cursor.js.map +1 -1
  14. package/dist/clients/vscode.js +38 -29
  15. package/dist/clients/vscode.js.map +1 -1
  16. package/dist/commands/mcp/allow.js +219 -0
  17. package/dist/commands/mcp/allow.js.map +1 -0
  18. package/dist/commands/mcp/connect.js +337 -0
  19. package/dist/commands/mcp/connect.js.map +1 -0
  20. package/dist/commands/mcp/index.js +170 -0
  21. package/dist/commands/mcp/index.js.map +1 -0
  22. package/dist/commands/mcp/proxy.js +320 -0
  23. package/dist/commands/mcp/proxy.js.map +1 -0
  24. package/dist/commands/mcp/scan.js +349 -0
  25. package/dist/commands/mcp/scan.js.map +1 -0
  26. package/dist/commands/mcp/sync.js +215 -0
  27. package/dist/commands/mcp/sync.js.map +1 -0
  28. package/dist/config.js +6 -0
  29. package/dist/config.js.map +1 -1
  30. package/dist/diagnostics.js +78 -12
  31. package/dist/diagnostics.js.map +1 -1
  32. package/dist/doctor.js +19 -0
  33. package/dist/doctor.js.map +1 -1
  34. package/dist/guards-evaluator/analysis-types.js +27 -0
  35. package/dist/guards-evaluator/analysis-types.js.map +1 -0
  36. package/dist/guards-evaluator/command-analysis.js +572 -0
  37. package/dist/guards-evaluator/command-analysis.js.map +1 -0
  38. package/dist/guards-evaluator/command-view.js +586 -0
  39. package/dist/guards-evaluator/command-view.js.map +1 -0
  40. package/dist/guards-evaluator/env.js +11 -0
  41. package/dist/guards-evaluator/env.js.map +1 -0
  42. package/dist/guards-evaluator/evaluate.js +91 -41
  43. package/dist/guards-evaluator/evaluate.js.map +1 -1
  44. package/dist/guards-evaluator/index.js +2 -1
  45. package/dist/guards-evaluator/index.js.map +1 -1
  46. package/dist/guards-evaluator/inline-code.js +259 -0
  47. package/dist/guards-evaluator/inline-code.js.map +1 -0
  48. package/dist/guards-evaluator/normalize.js +716 -0
  49. package/dist/guards-evaluator/normalize.js.map +1 -0
  50. package/dist/guards-evaluator/preprocess.js +13 -5
  51. package/dist/guards-evaluator/preprocess.js.map +1 -1
  52. package/dist/guards-evaluator/redact.js +19 -0
  53. package/dist/guards-evaluator/redact.js.map +1 -1
  54. package/dist/guards-evaluator/regex.js +25 -3
  55. package/dist/guards-evaluator/regex.js.map +1 -1
  56. package/dist/guards-evaluator/safe-commands.js +155 -0
  57. package/dist/guards-evaluator/safe-commands.js.map +1 -0
  58. package/dist/guards-evaluator/triage.js +315 -0
  59. package/dist/guards-evaluator/triage.js.map +1 -0
  60. package/dist/hook-runner.js +24679 -5079
  61. package/dist/hooks/install.js +38 -0
  62. package/dist/hooks/install.js.map +1 -1
  63. package/dist/hooks/runtime/config.js +38 -0
  64. package/dist/hooks/runtime/config.js.map +1 -1
  65. package/dist/hooks/runtime/emit.js +94 -61
  66. package/dist/hooks/runtime/emit.js.map +1 -1
  67. package/dist/hooks/runtime/fetch-rules.js +22 -7
  68. package/dist/hooks/runtime/fetch-rules.js.map +1 -1
  69. package/dist/hooks/runtime/gateway-http-error.js +34 -0
  70. package/dist/hooks/runtime/gateway-http-error.js.map +1 -0
  71. package/dist/hooks/runtime/guard-rules-cache.js +139 -17
  72. package/dist/hooks/runtime/guard-rules-cache.js.map +1 -1
  73. package/dist/hooks/runtime/guard-violations-buffer.js +321 -48
  74. package/dist/hooks/runtime/guard-violations-buffer.js.map +1 -1
  75. package/dist/hooks/runtime/judge-cache.js +6 -0
  76. package/dist/hooks/runtime/judge-cache.js.map +1 -1
  77. package/dist/hooks/runtime/judge-triage.js +193 -0
  78. package/dist/hooks/runtime/judge-triage.js.map +1 -0
  79. package/dist/hooks/runtime/judge.js +7 -1
  80. package/dist/hooks/runtime/judge.js.map +1 -1
  81. package/dist/hooks/runtime/pre-compact.js +12 -6
  82. package/dist/hooks/runtime/pre-compact.js.map +1 -1
  83. package/dist/hooks/runtime/resolve.js +90 -8
  84. package/dist/hooks/runtime/resolve.js.map +1 -1
  85. package/dist/hooks/runtime/retry-policy.js +57 -0
  86. package/dist/hooks/runtime/retry-policy.js.map +1 -0
  87. package/dist/hooks/runtime/review-sessions.js +74 -0
  88. package/dist/hooks/runtime/review-sessions.js.map +1 -0
  89. package/dist/hooks/runtime/script-resolve.js +695 -0
  90. package/dist/hooks/runtime/script-resolve.js.map +1 -0
  91. package/dist/hooks/runtime/session-activation.js +5 -1
  92. package/dist/hooks/runtime/session-activation.js.map +1 -1
  93. package/dist/hooks/runtime/session-review.js +163 -45
  94. package/dist/hooks/runtime/session-review.js.map +1 -1
  95. package/dist/hooks/runtime/session-start.js +2 -1
  96. package/dist/hooks/runtime/session-start.js.map +1 -1
  97. package/dist/hooks/runtime/session-writes.js +232 -0
  98. package/dist/hooks/runtime/session-writes.js.map +1 -0
  99. package/dist/hooks/runtime/sniff.js +26 -7
  100. package/dist/hooks/runtime/sniff.js.map +1 -1
  101. package/dist/hooks/runtime/target-resolve.js +336 -0
  102. package/dist/hooks/runtime/target-resolve.js.map +1 -0
  103. package/dist/hooks/runtime/unmapped-tools.js +93 -0
  104. package/dist/hooks/runtime/unmapped-tools.js.map +1 -0
  105. package/dist/hooks/runtime/usage-block.js +4 -0
  106. package/dist/hooks/runtime/usage-block.js.map +1 -1
  107. package/dist/hooks/runtime/user-prompt-submit.js +2 -1
  108. package/dist/hooks/runtime/user-prompt-submit.js.map +1 -1
  109. package/dist/hooks/runtime/wire-text.js +41 -0
  110. package/dist/hooks/runtime/wire-text.js.map +1 -0
  111. package/dist/hooks/runtime/work-dir.js +84 -0
  112. package/dist/hooks/runtime/work-dir.js.map +1 -0
  113. package/dist/index.js +45 -12
  114. package/dist/index.js.map +1 -1
  115. package/dist/install.js +174 -11
  116. package/dist/install.js.map +1 -1
  117. package/dist/link.js +74 -48
  118. package/dist/link.js.map +1 -1
  119. package/dist/login.js +77 -11
  120. package/dist/login.js.map +1 -1
  121. package/dist/mcp/auth/agent-sign-ins.js +174 -0
  122. package/dist/mcp/auth/agent-sign-ins.js.map +1 -0
  123. package/dist/mcp/auth/callback.js +200 -0
  124. package/dist/mcp/auth/callback.js.map +1 -0
  125. package/dist/mcp/auth/connect.js +392 -0
  126. package/dist/mcp/auth/connect.js.map +1 -0
  127. package/dist/mcp/auth/discovery.js +399 -0
  128. package/dist/mcp/auth/discovery.js.map +1 -0
  129. package/dist/mcp/auth/oauth.js +326 -0
  130. package/dist/mcp/auth/oauth.js.map +1 -0
  131. package/dist/mcp/auth/probe.js +128 -0
  132. package/dist/mcp/auth/probe.js.map +1 -0
  133. package/dist/mcp/auth/secrets.js +446 -0
  134. package/dist/mcp/auth/secrets.js.map +1 -0
  135. package/dist/mcp/auth/store.js +260 -0
  136. package/dist/mcp/auth/store.js.map +1 -0
  137. package/dist/mcp/auth/tokenSource.js +55 -0
  138. package/dist/mcp/auth/tokenSource.js.map +1 -0
  139. package/dist/mcp/config/atomicWrite.js +98 -0
  140. package/dist/mcp/config/atomicWrite.js.map +1 -0
  141. package/dist/mcp/config/clients.js +171 -0
  142. package/dist/mcp/config/clients.js.map +1 -0
  143. package/dist/mcp/config/cybedefend-servers.js +48 -0
  144. package/dist/mcp/config/cybedefend-servers.js.map +1 -0
  145. package/dist/mcp/config/discover.js +114 -0
  146. package/dist/mcp/config/discover.js.map +1 -0
  147. package/dist/mcp/config/hook.js +123 -0
  148. package/dist/mcp/config/hook.js.map +1 -0
  149. package/dist/mcp/config/index.js +11 -0
  150. package/dist/mcp/config/index.js.map +1 -0
  151. package/dist/mcp/config/install.js +132 -0
  152. package/dist/mcp/config/install.js.map +1 -0
  153. package/dist/mcp/config/installed.js +37 -0
  154. package/dist/mcp/config/installed.js.map +1 -0
  155. package/dist/mcp/config/jsonEdit.js +119 -0
  156. package/dist/mcp/config/jsonEdit.js.map +1 -0
  157. package/dist/mcp/config/lock.js +102 -0
  158. package/dist/mcp/config/lock.js.map +1 -0
  159. package/dist/mcp/config/proxyBinary.js +211 -0
  160. package/dist/mcp/config/proxyBinary.js.map +1 -0
  161. package/dist/mcp/config/rewrite.js +388 -0
  162. package/dist/mcp/config/rewrite.js.map +1 -0
  163. package/dist/mcp/config/types.js +34 -0
  164. package/dist/mcp/config/types.js.map +1 -0
  165. package/dist/mcp/proxy/audit.js +83 -0
  166. package/dist/mcp/proxy/audit.js.map +1 -0
  167. package/dist/mcp/proxy/authInterceptor.js +119 -0
  168. package/dist/mcp/proxy/authInterceptor.js.map +1 -0
  169. package/dist/mcp/proxy/expand.js +93 -0
  170. package/dist/mcp/proxy/expand.js.map +1 -0
  171. package/dist/mcp/proxy/inject.js +412 -0
  172. package/dist/mcp/proxy/inject.js.map +1 -0
  173. package/dist/mcp/proxy/intercept.js +63 -0
  174. package/dist/mcp/proxy/intercept.js.map +1 -0
  175. package/dist/mcp/proxy/jsonrpc.js +153 -0
  176. package/dist/mcp/proxy/jsonrpc.js.map +1 -0
  177. package/dist/mcp/proxy/log.js +109 -0
  178. package/dist/mcp/proxy/log.js.map +1 -0
  179. package/dist/mcp/proxy/paths.js +57 -0
  180. package/dist/mcp/proxy/paths.js.map +1 -0
  181. package/dist/mcp/proxy/proxy.js +520 -0
  182. package/dist/mcp/proxy/proxy.js.map +1 -0
  183. package/dist/mcp/proxy/serverCheckTimer.js +75 -0
  184. package/dist/mcp/proxy/serverCheckTimer.js.map +1 -0
  185. package/dist/mcp/proxy/sessionLifecycle.js +29 -0
  186. package/dist/mcp/proxy/sessionLifecycle.js.map +1 -0
  187. package/dist/mcp/proxy/spec.js +203 -0
  188. package/dist/mcp/proxy/spec.js.map +1 -0
  189. package/dist/mcp/proxy/sse.js +77 -0
  190. package/dist/mcp/proxy/sse.js.map +1 -0
  191. package/dist/mcp/proxy/upstream.js +2 -0
  192. package/dist/mcp/proxy/upstream.js.map +1 -0
  193. package/dist/mcp/proxy/upstreamHttp.js +499 -0
  194. package/dist/mcp/proxy/upstreamHttp.js.map +1 -0
  195. package/dist/mcp/proxy/upstreamStdio.js +188 -0
  196. package/dist/mcp/proxy/upstreamStdio.js.map +1 -0
  197. package/dist/mcp/proxy/upstreams.js +143 -0
  198. package/dist/mcp/proxy/upstreams.js.map +1 -0
  199. package/dist/mcp/proxy/verifyInterceptor.js +718 -0
  200. package/dist/mcp/proxy/verifyInterceptor.js.map +1 -0
  201. package/dist/mcp/proxy/windowsCommand.js +99 -0
  202. package/dist/mcp/proxy/windowsCommand.js.map +1 -0
  203. package/dist/mcp/report/buffer.js +351 -0
  204. package/dist/mcp/report/buffer.js.map +1 -0
  205. package/dist/mcp/report/coalesce.js +165 -0
  206. package/dist/mcp/report/coalesce.js.map +1 -0
  207. package/dist/mcp/report/constants.js +51 -0
  208. package/dist/mcp/report/constants.js.map +1 -0
  209. package/dist/mcp/report/project.js +83 -0
  210. package/dist/mcp/report/project.js.map +1 -0
  211. package/dist/mcp/report/reporter.js +443 -0
  212. package/dist/mcp/report/reporter.js.map +1 -0
  213. package/dist/mcp/report/types.js +3 -0
  214. package/dist/mcp/report/types.js.map +1 -0
  215. package/dist/mcp/report/validate.js +179 -0
  216. package/dist/mcp/report/validate.js.map +1 -0
  217. package/dist/mcp/scan/args.js +228 -0
  218. package/dist/mcp/scan/args.js.map +1 -0
  219. package/dist/mcp/scan/results.js +253 -0
  220. package/dist/mcp/scan/results.js.map +1 -0
  221. package/dist/mcp/scan/types.js +40 -0
  222. package/dist/mcp/scan/types.js.map +1 -0
  223. package/dist/mcp/verify/api.js +514 -0
  224. package/dist/mcp/verify/api.js.map +1 -0
  225. package/dist/mcp/verify/backend.js +143 -0
  226. package/dist/mcp/verify/backend.js.map +1 -0
  227. package/dist/mcp/verify/cache.js +200 -0
  228. package/dist/mcp/verify/cache.js.map +1 -0
  229. package/dist/mcp/verify/contract-errors.js +198 -0
  230. package/dist/mcp/verify/contract-errors.js.map +1 -0
  231. package/dist/mcp/verify/digest.js +91 -0
  232. package/dist/mcp/verify/digest.js.map +1 -0
  233. package/dist/mcp/verify/factory.js +56 -0
  234. package/dist/mcp/verify/factory.js.map +1 -0
  235. package/dist/mcp/verify/identity.js +286 -0
  236. package/dist/mcp/verify/identity.js.map +1 -0
  237. package/dist/mcp/verify/policy-store.js +63 -0
  238. package/dist/mcp/verify/policy-store.js.map +1 -0
  239. package/dist/mcp/verify/policy.js +160 -0
  240. package/dist/mcp/verify/policy.js.map +1 -0
  241. package/dist/mcp/verify/pool.js +27 -0
  242. package/dist/mcp/verify/pool.js.map +1 -0
  243. package/dist/mcp/verify/token-refresh.js +44 -0
  244. package/dist/mcp/verify/token-refresh.js.map +1 -0
  245. package/dist/mcp/verify/token.js +67 -0
  246. package/dist/mcp/verify/token.js.map +1 -0
  247. package/dist/mcp/verify/verifier.js +1166 -0
  248. package/dist/mcp/verify/verifier.js.map +1 -0
  249. package/dist/org-gate.js +1 -1
  250. package/dist/org-gate.js.map +1 -1
  251. package/dist/org.js +146 -0
  252. package/dist/org.js.map +1 -0
  253. package/dist/project-create.js +129 -0
  254. package/dist/project-create.js.map +1 -0
  255. package/dist/prompts.js +21 -0
  256. package/dist/prompts.js.map +1 -1
  257. package/dist/re2.wasm +0 -0
  258. package/dist/status.js +61 -0
  259. package/dist/status.js.map +1 -1
  260. package/dist/uninstall.js +49 -4
  261. package/dist/uninstall.js.map +1 -1
  262. package/dist/utils.js +62 -6
  263. package/dist/utils.js.map +1 -1
  264. package/package.json +10 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/mcp/report/validate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,228 @@
1
+ /**
2
+ * What is going out in a `tools/call`, checked locally and sent nowhere.
3
+ *
4
+ * Two questions, both answerable without a backend:
5
+ *
6
+ * - is there a credential in these arguments? An agent that has been told
7
+ * to "include your AWS key for authentication" will do it, and the
8
+ * argument is where it lands.
9
+ * - is there a URL pointing somewhere this server has no business with?
10
+ * That is the shape of exfiltration through an innocent-looking
11
+ * parameter.
12
+ *
13
+ * ─── Why these patterns and not a general entropy check ─────────────────────
14
+ *
15
+ * High entropy is everywhere in a tool call: a UUID, a commit sha, a base64
16
+ * image, a JSON Web Key. A detector built on entropy fires on all of them,
17
+ * and a detector that fires on all of them is turned off within a week. So
18
+ * every rule here matches a credential FORMAT that its issuer publishes — the
19
+ * prefixes AWS, GitHub, Slack, Stripe and OpenAI put on their keys precisely
20
+ * so that scanners can find them — plus the two structural shapes that are
21
+ * unambiguous, a PEM private key block and a signed JWT.
22
+ *
23
+ * ─── Why the regular expressions look the way they do ───────────────────────
24
+ *
25
+ * No nested quantifier, no alternation inside a repetition, no backreference:
26
+ * every pattern below is linear in the length of its input. The input is
27
+ * attacker-controlled — it comes from a server's tool schema by way of an
28
+ * agent — and a catastrophic backtrack here would hang the MCP session. That
29
+ * is why the shapes are `prefix` + a fixed-width character class, and why the
30
+ * scanned length is capped.
31
+ */
32
+ import { MAX_SCAN_BYTES, walkStrings } from './types.js';
33
+ /**
34
+ * Credential formats their issuers publish, plus the two unambiguous
35
+ * structural shapes.
36
+ */
37
+ const SECRET_RULES = [
38
+ {
39
+ rule: 'aws-access-key',
40
+ severity: 'high',
41
+ pattern: /\b(?:AKIA|ASIA|ABIA|ACCA)[0-9A-Z]{16}\b/,
42
+ detail: 'an AWS access key id',
43
+ },
44
+ {
45
+ rule: 'github-token',
46
+ severity: 'high',
47
+ pattern: /\bgh[pousr]_[A-Za-z0-9]{36,}\b/,
48
+ detail: 'a GitHub token',
49
+ },
50
+ {
51
+ rule: 'github-fine-grained-token',
52
+ severity: 'high',
53
+ pattern: /\bgithub_pat_[A-Za-z0-9_]{60,}\b/,
54
+ detail: 'a GitHub fine-grained token',
55
+ },
56
+ {
57
+ rule: 'slack-token',
58
+ severity: 'high',
59
+ pattern: /\bxox[abposr]-[A-Za-z0-9-]{10,}\b/,
60
+ detail: 'a Slack token',
61
+ },
62
+ {
63
+ rule: 'stripe-key',
64
+ severity: 'high',
65
+ pattern: /\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{20,}\b/,
66
+ detail: 'a Stripe secret key',
67
+ },
68
+ {
69
+ rule: 'openai-key',
70
+ severity: 'high',
71
+ pattern: /\bsk-(?:proj-)?[A-Za-z0-9_-]{32,}\b/,
72
+ detail: 'an OpenAI API key',
73
+ },
74
+ {
75
+ rule: 'google-api-key',
76
+ severity: 'high',
77
+ pattern: /\bAIza[0-9A-Za-z_-]{35}\b/,
78
+ detail: 'a Google API key',
79
+ },
80
+ {
81
+ rule: 'private-key',
82
+ severity: 'high',
83
+ // The header alone: the body is base64 and matching it would be the
84
+ // nested-quantifier mistake this file exists to avoid.
85
+ pattern: /-----BEGIN (?:RSA |EC |DSA |OPENSSH |PGP )?PRIVATE KEY(?: BLOCK)?-----/,
86
+ detail: 'a private key block',
87
+ },
88
+ {
89
+ rule: 'jwt',
90
+ severity: 'medium',
91
+ // Three dot-separated base64url segments, the first starting with the
92
+ // encoding of `{"alg"`.
93
+ pattern: /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/,
94
+ detail: 'a signed JSON Web Token',
95
+ },
96
+ ];
97
+ /** `Authorization: Bearer …` and friends, spelled out in an argument. */
98
+ const BEARER_RULE = {
99
+ rule: 'bearer-header',
100
+ severity: 'medium',
101
+ pattern: /\b(?:authorization|x-api-key)\b\s*[:=]\s*(?:bearer\s+)?[A-Za-z0-9._~+/=-]{16,}/i,
102
+ detail: 'an authorization header value',
103
+ };
104
+ /**
105
+ * Scans the `arguments` of a `tools/call`.
106
+ *
107
+ * Returns findings; decides nothing. What to do about them is `policy.ts`'s
108
+ * job, and by default it is to say so rather than to refuse.
109
+ */
110
+ export function scanArguments(args, context) {
111
+ const findings = [];
112
+ const expected = expectedHosts(context);
113
+ const uriProperties = declaredUriProperties(context.inputSchema);
114
+ for (const { path, value } of walkStrings(args)) {
115
+ const text = value.length > MAX_SCAN_BYTES ? value.slice(0, MAX_SCAN_BYTES) : value;
116
+ for (const rule of [...SECRET_RULES, BEARER_RULE]) {
117
+ if (!rule.pattern.test(text))
118
+ continue;
119
+ findings.push({
120
+ kind: 'secret-in-arguments',
121
+ rule: rule.rule,
122
+ severity: rule.severity,
123
+ where: `arguments.${path}`,
124
+ // The value is never quoted: a secret repeated into a log or into the
125
+ // agent's context is the leak this finding exists to prevent.
126
+ detail: `looks like ${rule.detail}`,
127
+ });
128
+ }
129
+ for (const host of hostsIn(text)) {
130
+ if (expected.has(host))
131
+ continue;
132
+ // A parameter the tool DECLARES as a URI is what the tool is for. A
133
+ // `fetch` tool that takes a URL is not exfiltrating anything by being
134
+ // given one, and flagging it would be the finding nobody reads.
135
+ if (isDeclaredUri(path, uriProperties))
136
+ continue;
137
+ findings.push({
138
+ kind: 'unexpected-url',
139
+ rule: 'outbound-url',
140
+ severity: 'medium',
141
+ where: `arguments.${path}`,
142
+ detail: `contains a URL to ${host}, which is not this server and is not a parameter it declares as a URI`,
143
+ });
144
+ }
145
+ }
146
+ return dedupe(findings);
147
+ }
148
+ /** Hosts this server has business with. */
149
+ export function expectedHosts(context) {
150
+ const hosts = new Set();
151
+ if (context.spec.transport === 'http') {
152
+ const host = hostOf(context.spec.url);
153
+ if (host)
154
+ hosts.add(host);
155
+ }
156
+ // A host the tool documents is one the author meant it to reach.
157
+ for (const host of hostsIn(context.description ?? ''))
158
+ hosts.add(host);
159
+ for (const host of hostsIn(JSON.stringify(context.inputSchema ?? null)))
160
+ hosts.add(host);
161
+ return hosts;
162
+ }
163
+ const URL_PATTERN = /\bhttps?:\/\/[^\s"'<>()\\]{1,2000}/gi;
164
+ /** Every http(s) host mentioned in a string. */
165
+ export function hostsIn(text) {
166
+ const hosts = [];
167
+ for (const match of text.slice(0, MAX_SCAN_BYTES).matchAll(URL_PATTERN)) {
168
+ const host = hostOf(match[0]);
169
+ if (host)
170
+ hosts.push(host);
171
+ }
172
+ return hosts;
173
+ }
174
+ function hostOf(url) {
175
+ // A URL at the end of a sentence carries the full stop with it: "talks to
176
+ // https://api.example.com." would otherwise read as the host
177
+ // `api.example.com.`, which never matches the same host written without it,
178
+ // and the documented host would be flagged as unexpected.
179
+ const trimmed = url.replace(/[.,;:!?)\]]+$/, '');
180
+ try {
181
+ return new URL(trimmed).host.toLowerCase().replace(/\.$/, '') || null;
182
+ }
183
+ catch {
184
+ return null;
185
+ }
186
+ }
187
+ /**
188
+ * The property names a schema declares as URIs, by `format: 'uri'` or by
189
+ * being named like one.
190
+ */
191
+ export function declaredUriProperties(schema) {
192
+ const names = new Set();
193
+ const properties = typeof schema === 'object' && schema !== null
194
+ ? schema.properties
195
+ : undefined;
196
+ if (!properties)
197
+ return names;
198
+ for (const [name, property] of Object.entries(properties)) {
199
+ if (/^(url|uri|href|link|endpoint|webhook|callback)/i.test(name)) {
200
+ names.add(name);
201
+ continue;
202
+ }
203
+ if (typeof property !== 'object' || property === null)
204
+ continue;
205
+ const typed = property;
206
+ if (typed.format === 'uri' || typed.format === 'url')
207
+ names.add(name);
208
+ }
209
+ return names;
210
+ }
211
+ function isDeclaredUri(path, uriProperties) {
212
+ const head = path.split(/[.[]/)[0];
213
+ return uriProperties.has(head);
214
+ }
215
+ /** One finding per rule and place; a key repeated in a body is one leak. */
216
+ function dedupe(findings) {
217
+ const seen = new Set();
218
+ const out = [];
219
+ for (const finding of findings) {
220
+ const key = `${finding.kind}|${finding.rule}|${finding.where}`;
221
+ if (seen.has(key))
222
+ continue;
223
+ seen.add(key);
224
+ out.push(finding);
225
+ }
226
+ return out;
227
+ }
228
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../../../src/mcp/scan/args.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,253 @@
1
+ /**
2
+ * Text coming back from a tool, read as what it is: input to a language
3
+ * model.
4
+ *
5
+ * A result is not data the agent looks at, it is text the agent CONTINUES
6
+ * FROM. A sentence in a returned document telling the assistant to ignore its
7
+ * instructions is, from the model's point of view, indistinguishable from a
8
+ * sentence its own user wrote — that is the whole of prompt injection, and no
9
+ * amount of parsing changes it.
10
+ *
11
+ * ─── What this can and cannot do ────────────────────────────────────────────
12
+ *
13
+ * Heuristics, deliberately, and no LLM call: sending every tool result to a
14
+ * model would double the cost of every session and send the contents of the
15
+ * user's files somewhere. What heuristics buy is the loud cases — the ones
16
+ * that read like an instruction because they ARE one — and what they cannot
17
+ * do is catch a well-written one. The honest framing is that this raises the
18
+ * cost of the obvious attack, and the `[VibeDefend]` block tells the agent
19
+ * that the text below it is data.
20
+ *
21
+ * ─── The false-positive budget is zero ──────────────────────────────────────
22
+ *
23
+ * A tool result is the single most common thing in a session. A detector with
24
+ * a 1% false-positive rate fires several times an hour and is off by
25
+ * Wednesday. So every rule here needs BOTH an imperative addressed to an
26
+ * assistant AND a target — "ignore" alone is a word, "ignore all previous
27
+ * instructions" is an attack — and the suite measures the rate on the real
28
+ * output of every tool of the reference servers.
29
+ *
30
+ * Every pattern is linear: no nested quantifier, no alternation inside a
31
+ * repetition. The input is attacker-controlled by construction.
32
+ */
33
+ import { MAX_SCAN_BYTES } from './types.js';
34
+ const RESULT_RULES = [
35
+ {
36
+ rule: 'ignore-instructions',
37
+ severity: 'high',
38
+ // Three parts are required — the verb, what it is aimed at, and the noun
39
+ // — and the gaps between them admit PROSE only. The gap used to be
40
+ // `[^.\n]`, which matched
41
+ // `ignore(previous: string[], instructions: string[])`: a function
42
+ // signature read as an attack. Brackets, braces and colons are how code
43
+ // looks and are not how a sentence does.
44
+ pattern: /\b(?:ignore|disregard|forget|override)\b[a-z\s'’-]{0,40}\b(?:previous|prior|earlier|above|all|any|your)\b[a-z\s'’-]{0,40}\b(?:instruction|instructions|prompt|prompts|rule|rules|guideline|guidelines|directive|directives)\b/i,
45
+ detail: 'text telling the assistant to ignore its instructions',
46
+ },
47
+ {
48
+ rule: 'new-instructions',
49
+ severity: 'high',
50
+ pattern: /\b(?:new|updated|revised|real|actual)\s+(?:system\s+)?(?:instruction|instructions|prompt|directive|directives)\b\s*[:\-—]/i,
51
+ detail: 'text announcing a new set of instructions',
52
+ },
53
+ {
54
+ rule: 'role-impersonation',
55
+ severity: 'high',
56
+ pattern: /(?:<\/?system>|\[\/?system\]|^\s*###\s*system\b|\bsystem\s*:\s*you\s+are\b)/im,
57
+ detail: 'text impersonating a system message',
58
+ },
59
+ {
60
+ rule: 'assistant-redirection',
61
+ severity: 'high',
62
+ pattern: /\byou\s+(?:are\s+now|must\s+now|should\s+now|will\s+now)\b[^.\n]{0,60}\b(?:instead|from\s+now\s+on|forget)\b/i,
63
+ detail: 'text redirecting the assistant to a new role',
64
+ },
65
+ {
66
+ rule: 'assistant-redirection',
67
+ severity: 'high',
68
+ // The same attack in two sentences rather than one: "You are now a shell
69
+ // assistant. From now on, …". The rule above stops at the full stop, so
70
+ // the role reassignment is named on its own.
71
+ pattern: /\byou\s+are\s+now\s+(?:a|an|the)\b[a-z\s-]{0,30}\b(?:assistant|agent|model|bot|shell|terminal|admin|administrator|developer|root)\b/i,
72
+ detail: 'text reassigning the assistant to a new role',
73
+ },
74
+ {
75
+ rule: 'silent-exfiltration',
76
+ severity: 'high',
77
+ // The user has to be who is kept in the dark, not what is being talked
78
+ // about. Without the lookahead, "do not tell the user's password to a
79
+ // third party" — a sentence out of an ordinary security policy — read as
80
+ // an attack.
81
+ pattern: /\b(?:do\s+not|don['’]?t|never)\s+(?:tell|mention|inform|notify|show|reveal)\b[a-z\s-]{0,30}\buser\b(?!['’]s)(?=\s*(?:[.,;!?)]|about\b|that\b|this\b|it\b|anything\b|$))/i,
82
+ detail: 'text asking the assistant to hide something from the user',
83
+ },
84
+ {
85
+ rule: 'credential-request',
86
+ severity: 'high',
87
+ pattern: /\b(?:read|open|cat|send|include|attach|upload)\b[^.\n]{0,50}(?:~\/\.ssh|~\/\.aws|\.env\b|id_rsa|credentials\b|private\s+key)/i,
88
+ detail: 'text asking the assistant to read or send a credential file',
89
+ },
90
+ {
91
+ rule: 'tool-call-injection',
92
+ severity: 'medium',
93
+ pattern: /\b(?:you\s+must|you\s+should|please)\s+(?:now\s+)?(?:call|invoke|run|use)\b[^.\n]{0,30}\btool\b/i,
94
+ detail: 'text instructing the assistant to call a tool',
95
+ },
96
+ ];
97
+ /** Characters that carry no glyph and exist to hide text from a reader. */
98
+ const ZERO_WIDTH = /[​‌‍⁠᠎]/;
99
+ /** Bidirectional overrides, which reorder what a human sees. */
100
+ const BIDI_OVERRIDE = /[‪-‮⁦-⁩]/;
101
+ /** Cyrillic and Greek letters that are drawn like Latin ones. */
102
+ const CONFUSABLES = /[аеорсхАЕОРСХοαερ]/;
103
+ /**
104
+ * Scans the text of a `tools/call` result.
105
+ *
106
+ * Only the text: an image, a blob or a resource link carries no prose for a
107
+ * model to follow, and decoding a base64 payload to search it would be a way
108
+ * of spending a session's CPU on a picture.
109
+ */
110
+ export function scanResultText(text, options = {}) {
111
+ const limit = options.maxBytes ?? MAX_SCAN_BYTES;
112
+ const body = text.length > limit ? text.slice(0, limit) : text;
113
+ const findings = [];
114
+ for (const rule of RESULT_RULES) {
115
+ const match = rule.pattern.exec(body);
116
+ if (!match)
117
+ continue;
118
+ findings.push({
119
+ kind: 'prompt-injection',
120
+ rule: rule.rule,
121
+ severity: rule.severity,
122
+ where: `result[${match.index}]`,
123
+ detail: rule.detail,
124
+ });
125
+ }
126
+ // Hidden text: only a finding when there is an instruction hiding in it.
127
+ // Zero-width characters are also how a legitimate document marks a line
128
+ // break opportunity, and flagging every one of them would be noise.
129
+ const hidden = hiddenText(body);
130
+ if (hidden.length > 0) {
131
+ const instruction = RESULT_RULES.some((rule) => rule.pattern.test(hidden));
132
+ if (instruction) {
133
+ findings.push({
134
+ kind: 'prompt-injection',
135
+ rule: 'hidden-instructions',
136
+ severity: 'high',
137
+ where: 'result',
138
+ detail: 'instructions hidden in text the user cannot see',
139
+ });
140
+ }
141
+ }
142
+ if (ZERO_WIDTH.test(body) && findings.length > 0) {
143
+ findings.push({
144
+ kind: 'prompt-injection',
145
+ rule: 'zero-width-characters',
146
+ severity: 'medium',
147
+ where: 'result',
148
+ detail: 'invisible characters alongside the flagged text',
149
+ });
150
+ }
151
+ if (BIDI_OVERRIDE.test(body)) {
152
+ findings.push({
153
+ kind: 'prompt-injection',
154
+ rule: 'bidi-override',
155
+ severity: 'medium',
156
+ where: 'result',
157
+ detail: 'characters that reorder what a human reader sees',
158
+ });
159
+ }
160
+ if (hasConfusableWord(body)) {
161
+ findings.push({
162
+ kind: 'prompt-injection',
163
+ rule: 'homoglyphs',
164
+ severity: 'medium',
165
+ where: 'result',
166
+ detail: 'a word mixing Latin letters with look-alikes from another script',
167
+ });
168
+ }
169
+ return findings;
170
+ }
171
+ /**
172
+ * Text a reader will not see: HTML comments, and elements styled invisible.
173
+ *
174
+ * Concatenated rather than scanned in place, so an instruction split across
175
+ * three comments is found as one sentence.
176
+ */
177
+ export function hiddenText(body) {
178
+ const parts = [];
179
+ for (const match of body.matchAll(/<!--([^]{0,4000}?)-->/g))
180
+ parts.push(match[1]);
181
+ for (const match of body.matchAll(/<[a-z]+[^>]{0,200}style="[^"]{0,200}(?:display\s*:\s*none|visibility\s*:\s*hidden|font-size\s*:\s*0)[^"]{0,200}"[^>]{0,200}>([^<]{0,4000})</gi)) {
182
+ parts.push(match[1]);
183
+ }
184
+ return parts.join(' ');
185
+ }
186
+ /**
187
+ * A word that is Latin except for one or two look-alikes.
188
+ *
189
+ * A whole word in Cyrillic is Russian, not an attack. What this looks for is
190
+ * the mix — `аdmin` with a Cyrillic `а` — which exists only to make a word
191
+ * read as one thing and compare as another.
192
+ */
193
+ export function hasConfusableWord(body) {
194
+ for (const match of body.matchAll(/[\p{L}]{3,40}/gu)) {
195
+ const word = match[0];
196
+ if (!CONFUSABLES.test(word))
197
+ continue;
198
+ if (/[a-zA-Z]/.test(word))
199
+ return true;
200
+ }
201
+ return false;
202
+ }
203
+ /**
204
+ * Every piece of text in a `tools/call` result.
205
+ *
206
+ * Covers the shapes the spec defines: a text block, the text of an embedded
207
+ * resource, and `structuredContent`. An image or a blob is skipped.
208
+ */
209
+ export function textsInResult(result) {
210
+ const texts = [];
211
+ if (typeof result !== 'object' || result === null)
212
+ return texts;
213
+ const typed = result;
214
+ if (Array.isArray(typed.content)) {
215
+ for (const block of typed.content) {
216
+ if (typeof block !== 'object' || block === null)
217
+ continue;
218
+ const entry = block;
219
+ if (entry.type === 'text' && typeof entry.text === 'string')
220
+ texts.push(entry.text);
221
+ if (entry.type === 'resource' && typeof entry.resource === 'object' && entry.resource !== null) {
222
+ const resource = entry.resource;
223
+ if (typeof resource.text === 'string')
224
+ texts.push(resource.text);
225
+ }
226
+ }
227
+ }
228
+ if (typed.structuredContent !== undefined) {
229
+ try {
230
+ texts.push(JSON.stringify(typed.structuredContent));
231
+ }
232
+ catch {
233
+ /* not serialisable: nothing to read */
234
+ }
235
+ }
236
+ return texts;
237
+ }
238
+ /** Scans a whole `tools/call` result. */
239
+ export function scanResult(result, options = {}) {
240
+ const findings = [];
241
+ for (const text of textsInResult(result)) {
242
+ findings.push(...scanResultText(text, options));
243
+ }
244
+ const seen = new Set();
245
+ return findings.filter((finding) => {
246
+ const key = `${finding.rule}|${finding.where}`;
247
+ if (seen.has(key))
248
+ return false;
249
+ seen.add(key);
250
+ return true;
251
+ });
252
+ }
253
+ //# sourceMappingURL=results.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"results.js","sourceRoot":"","sources":["../../../src/mcp/scan/results.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,EAAE,cAAc,EAAoB,MAAM,YAAY,CAAC;AAS9D,MAAM,YAAY,GAA0B;IAC1C;QACE,IAAI,EAAE,qBAAqB;QAC3B,QAAQ,EAAE,MAAM;QAChB,yEAAyE;QACzE,mEAAmE;QACnE,0BAA0B;QAC1B,mEAAmE;QACnE,wEAAwE;QACxE,yCAAyC;QACzC,OAAO,EACL,gOAAgO;QAClO,MAAM,EAAE,uDAAuD;KAChE;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,QAAQ,EAAE,MAAM;QAChB,OAAO,EACL,4HAA4H;QAC9H,MAAM,EAAE,2CAA2C;KACpD;IACD;QACE,IAAI,EAAE,oBAAoB;QAC1B,QAAQ,EAAE,MAAM;QAChB,OAAO,EAAE,+EAA+E;QACxF,MAAM,EAAE,qCAAqC;KAC9C;IACD;QACE,IAAI,EAAE,uBAAuB;QAC7B,QAAQ,EAAE,MAAM;QAChB,OAAO,EACL,+GAA+G;QACjH,MAAM,EAAE,8CAA8C;KACvD;IACD;QACE,IAAI,EAAE,uBAAuB;QAC7B,QAAQ,EAAE,MAAM;QAChB,yEAAyE;QACzE,wEAAwE;QACxE,6CAA6C;QAC7C,OAAO,EACL,sIAAsI;QACxI,MAAM,EAAE,8CAA8C;KACvD;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,QAAQ,EAAE,MAAM;QAChB,uEAAuE;QACvE,sEAAsE;QACtE,yEAAyE;QACzE,aAAa;QACb,OAAO,EACL,0KAA0K;QAC5K,MAAM,EAAE,2DAA2D;KACpE;IACD;QACE,IAAI,EAAE,oBAAoB;QAC1B,QAAQ,EAAE,MAAM;QAChB,OAAO,EACL,+HAA+H;QACjI,MAAM,EAAE,6DAA6D;KACtE;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,QAAQ,EAAE,QAAQ;QAClB,OAAO,EACL,kGAAkG;QACpG,MAAM,EAAE,+CAA+C;KACxD;CACF,CAAC;AAEF,2EAA2E;AAC3E,MAAM,UAAU,GAAG,UAAU,CAAC;AAC9B,gEAAgE;AAChE,MAAM,aAAa,GAAG,UAAU,CAAC;AAEjC,iEAAiE;AACjE,MAAM,WAAW,GAAG,oBAAoB,CAAC;AAOzC;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,UAA6B,EAAE;IAC1E,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,IAAI,cAAc,CAAC;IACjD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/D,MAAM,QAAQ,GAAkB,EAAE,CAAC;IAEnC,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,QAAQ,CAAC,IAAI,CAAC;YACZ,IAAI,EAAE,kBAAkB;YACxB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,KAAK,EAAE,UAAU,KAAK,CAAC,KAAK,GAAG;YAC/B,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CAAC;IACL,CAAC;IAED,yEAAyE;IACzE,wEAAwE;IACxE,oEAAoE;IACpE,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QAC3E,IAAI,WAAW,EAAE,CAAC;YAChB,QAAQ,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,kBAAkB;gBACxB,IAAI,EAAE,qBAAqB;gBAC3B,QAAQ,EAAE,MAAM;gBAChB,KAAK,EAAE,QAAQ;gBACf,MAAM,EAAE,iDAAiD;aAC1D,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjD,QAAQ,CAAC,IAAI,CAAC;YACZ,IAAI,EAAE,kBAAkB;YACxB,IAAI,EAAE,uBAAuB;YAC7B,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,QAAQ;YACf,MAAM,EAAE,iDAAiD;SAC1D,CAAC,CAAC;IACL,CAAC;IACD,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7B,QAAQ,CAAC,IAAI,CAAC;YACZ,IAAI,EAAE,kBAAkB;YACxB,IAAI,EAAE,eAAe;YACrB,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,QAAQ;YACf,MAAM,EAAE,kDAAkD;SAC3D,CAAC,CAAC;IACL,CAAC;IACD,IAAI,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5B,QAAQ,CAAC,IAAI,CAAC;YACZ,IAAI,EAAE,kBAAkB;YACxB,IAAI,EAAE,YAAY;YAClB,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,QAAQ;YACf,MAAM,EAAE,kEAAkE;SAC3E,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,wBAAwB,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAClF,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAC/B,+IAA+I,CAChJ,EAAE,CAAC;QACF,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,SAAS;QACtC,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IACzC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,MAAe;IAC3C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAChE,MAAM,KAAK,GAAG,MAA4D,CAAC;IAE3E,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACjC,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;gBAAE,SAAS;YAC1D,MAAM,KAAK,GAAG,KAA+D,CAAC;YAC9E,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;gBAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACpF,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;gBAC/F,MAAM,QAAQ,GAAG,KAAK,CAAC,QAA8B,CAAC;gBACtD,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ;oBAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,KAAK,CAAC,iBAAiB,KAAK,SAAS,EAAE,CAAC;QAC1C,IAAI,CAAC;YACH,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,uCAAuC;QACzC,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,UAAU,CAAC,MAAe,EAAE,UAA6B,EAAE;IACzE,MAAM,QAAQ,GAAkB,EAAE,CAAC;IACnC,KAAK,MAAM,IAAI,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QACzC,QAAQ,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAClD,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE;QACjC,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAC/C,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QAChC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * What a local scan can find, and what it is allowed to say about it.
3
+ *
4
+ * Everything in `src/mcp/scan/` runs on this machine and sends nothing
5
+ * anywhere. That is not a policy enforced by a check somewhere; it is that
6
+ * these modules take a value and return a finding, and nothing in them can
7
+ * reach the network.
8
+ */
9
+ /** How much of a value is worth scanning. */
10
+ export const MAX_SCAN_BYTES = 512 * 1024;
11
+ /**
12
+ * Every string in a value, with the path that reaches it.
13
+ *
14
+ * Depth-bounded and count-bounded: the value comes from an agent or from a
15
+ * server, and a scanner that recursed without limits would be a way of
16
+ * hanging the proxy with a deeply nested object.
17
+ */
18
+ export function* walkStrings(value, path = '', depth = 0, budget = { remaining: 5000 }) {
19
+ if (depth > 20 || budget.remaining <= 0)
20
+ return;
21
+ if (typeof value === 'string') {
22
+ budget.remaining -= 1;
23
+ yield { path: path || '.', value };
24
+ return;
25
+ }
26
+ if (Array.isArray(value)) {
27
+ for (let index = 0; index < value.length && budget.remaining > 0; index += 1) {
28
+ yield* walkStrings(value[index], `${path}[${index}]`, depth + 1, budget);
29
+ }
30
+ return;
31
+ }
32
+ if (typeof value === 'object' && value !== null) {
33
+ for (const [key, entry] of Object.entries(value)) {
34
+ if (budget.remaining <= 0)
35
+ return;
36
+ yield* walkStrings(entry, path ? `${path}.${key}` : key, depth + 1, budget);
37
+ }
38
+ }
39
+ }
40
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/mcp/scan/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAqCH,6CAA6C;AAC7C,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,GAAG,IAAI,CAAC;AAEzC;;;;;;GAMG;AACH,MAAM,SAAS,CAAC,CAAC,WAAW,CAC1B,KAAc,EACd,IAAI,GAAG,EAAE,EACT,KAAK,GAAG,CAAC,EACT,MAAM,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE;IAE5B,IAAI,KAAK,GAAG,EAAE,IAAI,MAAM,CAAC,SAAS,IAAI,CAAC;QAAE,OAAO;IAChD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,CAAC,SAAS,IAAI,CAAC,CAAC;QACtB,MAAM,EAAE,IAAI,EAAE,IAAI,IAAI,GAAG,EAAE,KAAK,EAAE,CAAC;QACnC,OAAO;IACT,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,IAAI,MAAM,CAAC,SAAS,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YAC7E,KAAK,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,KAAK,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;QAC3E,CAAC;QACD,OAAO;IACT,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;YAC5E,IAAI,MAAM,CAAC,SAAS,IAAI,CAAC;gBAAE,OAAO;YAClC,KAAK,CAAC,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC;AACH,CAAC"}