@integsec/agentic-pentest-proxy 0.2.4 → 0.2.6

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 (146) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +250 -54
  3. package/dist/bin/integsec-agentic-pentest-manifest.d.ts +3 -0
  4. package/dist/bin/integsec-agentic-pentest-manifest.d.ts.map +1 -0
  5. package/dist/bin/integsec-agentic-pentest-manifest.js +180 -0
  6. package/dist/bin/integsec-agentic-pentest-manifest.js.map +1 -0
  7. package/dist/bin/integsec-agentic-pentest-proxy.d.ts +1 -1
  8. package/dist/bin/integsec-agentic-pentest-proxy.d.ts.map +1 -1
  9. package/dist/bin/integsec-agentic-pentest-proxy.js +16 -4
  10. package/dist/bin/integsec-agentic-pentest-proxy.js.map +1 -1
  11. package/dist/src/audit/azure-monitor.d.ts +2 -2
  12. package/dist/src/audit/azure-monitor.d.ts.map +1 -1
  13. package/dist/src/audit/azure-monitor.js +8 -5
  14. package/dist/src/audit/azure-monitor.js.map +1 -1
  15. package/dist/src/audit/cloudwatch.d.ts.map +1 -1
  16. package/dist/src/audit/cloudwatch.js.map +1 -1
  17. package/dist/src/audit/gcp-logging.d.ts.map +1 -1
  18. package/dist/src/audit/gcp-logging.js +4 -6
  19. package/dist/src/audit/gcp-logging.js.map +1 -1
  20. package/dist/src/audit/index.d.ts +7 -0
  21. package/dist/src/audit/index.d.ts.map +1 -1
  22. package/dist/src/audit/index.js +11 -1
  23. package/dist/src/audit/index.js.map +1 -1
  24. package/dist/src/audit/local.d.ts.map +1 -1
  25. package/dist/src/audit/local.js +2 -1
  26. package/dist/src/audit/local.js.map +1 -1
  27. package/dist/src/builder/dry-run.d.ts +12 -0
  28. package/dist/src/builder/dry-run.d.ts.map +1 -0
  29. package/dist/src/builder/dry-run.js +103 -0
  30. package/dist/src/builder/dry-run.js.map +1 -0
  31. package/dist/src/builder/manifest-writer.d.ts +7 -0
  32. package/dist/src/builder/manifest-writer.d.ts.map +1 -0
  33. package/dist/src/builder/manifest-writer.js +17 -0
  34. package/dist/src/builder/manifest-writer.js.map +1 -0
  35. package/dist/src/builder/review-display.d.ts +10 -0
  36. package/dist/src/builder/review-display.d.ts.map +1 -0
  37. package/dist/src/builder/review-display.js +55 -0
  38. package/dist/src/builder/review-display.js.map +1 -0
  39. package/dist/src/builder/smart-validator.d.ts +39 -0
  40. package/dist/src/builder/smart-validator.d.ts.map +1 -0
  41. package/dist/src/builder/smart-validator.js +157 -0
  42. package/dist/src/builder/smart-validator.js.map +1 -0
  43. package/dist/src/builder/steps/domains.d.ts +10 -0
  44. package/dist/src/builder/steps/domains.d.ts.map +1 -0
  45. package/dist/src/builder/steps/domains.js +71 -0
  46. package/dist/src/builder/steps/domains.js.map +1 -0
  47. package/dist/src/builder/steps/engagement-info.d.ts +17 -0
  48. package/dist/src/builder/steps/engagement-info.d.ts.map +1 -0
  49. package/dist/src/builder/steps/engagement-info.js +49 -0
  50. package/dist/src/builder/steps/engagement-info.js.map +1 -0
  51. package/dist/src/builder/steps/engagement-window.d.ts +15 -0
  52. package/dist/src/builder/steps/engagement-window.d.ts.map +1 -0
  53. package/dist/src/builder/steps/engagement-window.js +57 -0
  54. package/dist/src/builder/steps/engagement-window.js.map +1 -0
  55. package/dist/src/builder/steps/exclusions.d.ts +13 -0
  56. package/dist/src/builder/steps/exclusions.d.ts.map +1 -0
  57. package/dist/src/builder/steps/exclusions.js +57 -0
  58. package/dist/src/builder/steps/exclusions.js.map +1 -0
  59. package/dist/src/builder/steps/ip-ranges.d.ts +10 -0
  60. package/dist/src/builder/steps/ip-ranges.d.ts.map +1 -0
  61. package/dist/src/builder/steps/ip-ranges.js +64 -0
  62. package/dist/src/builder/steps/ip-ranges.js.map +1 -0
  63. package/dist/src/builder/steps/review.d.ts +10 -0
  64. package/dist/src/builder/steps/review.d.ts.map +1 -0
  65. package/dist/src/builder/steps/review.js +29 -0
  66. package/dist/src/builder/steps/review.js.map +1 -0
  67. package/dist/src/builder/steps/techniques.d.ts +13 -0
  68. package/dist/src/builder/steps/techniques.d.ts.map +1 -0
  69. package/dist/src/builder/steps/techniques.js +68 -0
  70. package/dist/src/builder/steps/techniques.js.map +1 -0
  71. package/dist/src/builder/steps/urls-and-cloud.d.ts +15 -0
  72. package/dist/src/builder/steps/urls-and-cloud.d.ts.map +1 -0
  73. package/dist/src/builder/steps/urls-and-cloud.js +53 -0
  74. package/dist/src/builder/steps/urls-and-cloud.js.map +1 -0
  75. package/dist/src/builder/web/api.d.ts +9 -0
  76. package/dist/src/builder/web/api.d.ts.map +1 -0
  77. package/dist/src/builder/web/api.js +40 -0
  78. package/dist/src/builder/web/api.js.map +1 -0
  79. package/dist/src/builder/web/client-form.html +222 -0
  80. package/dist/src/builder/web/server.d.ts +14 -0
  81. package/dist/src/builder/web/server.d.ts.map +1 -0
  82. package/dist/src/builder/web/server.js +85 -0
  83. package/dist/src/builder/web/server.js.map +1 -0
  84. package/dist/src/builder/wizard.d.ts +9 -0
  85. package/dist/src/builder/wizard.d.ts.map +1 -0
  86. package/dist/src/builder/wizard.js +49 -0
  87. package/dist/src/builder/wizard.js.map +1 -0
  88. package/dist/src/config.d.ts +11 -1
  89. package/dist/src/config.d.ts.map +1 -1
  90. package/dist/src/config.js +15 -2
  91. package/dist/src/config.js.map +1 -1
  92. package/dist/src/dns-resolver.d.ts +10 -1
  93. package/dist/src/dns-resolver.d.ts.map +1 -1
  94. package/dist/src/dns-resolver.js +41 -3
  95. package/dist/src/dns-resolver.js.map +1 -1
  96. package/dist/src/extractor.d.ts +12 -0
  97. package/dist/src/extractor.d.ts.map +1 -1
  98. package/dist/src/extractor.js +386 -0
  99. package/dist/src/extractor.js.map +1 -1
  100. package/dist/src/index.d.ts +1 -1
  101. package/dist/src/index.js +1 -1
  102. package/dist/src/ip-matcher.d.ts +23 -0
  103. package/dist/src/ip-matcher.d.ts.map +1 -1
  104. package/dist/src/ip-matcher.js +96 -23
  105. package/dist/src/ip-matcher.js.map +1 -1
  106. package/dist/src/manifest-schema.d.ts +12 -62
  107. package/dist/src/manifest-schema.d.ts.map +1 -1
  108. package/dist/src/manifest.d.ts +6 -0
  109. package/dist/src/manifest.d.ts.map +1 -1
  110. package/dist/src/manifest.js +21 -6
  111. package/dist/src/manifest.js.map +1 -1
  112. package/dist/src/proxy.d.ts +19 -4
  113. package/dist/src/proxy.d.ts.map +1 -1
  114. package/dist/src/proxy.js +111 -33
  115. package/dist/src/proxy.js.map +1 -1
  116. package/dist/src/safe-filename.d.ts +3 -0
  117. package/dist/src/safe-filename.d.ts.map +1 -0
  118. package/dist/src/safe-filename.js +8 -0
  119. package/dist/src/safe-filename.js.map +1 -0
  120. package/dist/src/sanitizer.d.ts.map +1 -1
  121. package/dist/src/sanitizer.js +36 -10
  122. package/dist/src/sanitizer.js.map +1 -1
  123. package/dist/src/technique-checker.d.ts +14 -0
  124. package/dist/src/technique-checker.d.ts.map +1 -1
  125. package/dist/src/technique-checker.js +123 -2
  126. package/dist/src/technique-checker.js.map +1 -1
  127. package/dist/src/transports/http.d.ts +6 -2
  128. package/dist/src/transports/http.d.ts.map +1 -1
  129. package/dist/src/transports/http.js +101 -13
  130. package/dist/src/transports/http.js.map +1 -1
  131. package/dist/src/transports/sse.d.ts +13 -0
  132. package/dist/src/transports/sse.d.ts.map +1 -0
  133. package/dist/src/transports/sse.js +161 -0
  134. package/dist/src/transports/sse.js.map +1 -0
  135. package/dist/src/transports/stdio.d.ts +2 -2
  136. package/dist/src/transports/stdio.d.ts.map +1 -1
  137. package/dist/src/transports/stdio.js +77 -48
  138. package/dist/src/transports/stdio.js.map +1 -1
  139. package/dist/src/types.d.ts +1 -1
  140. package/dist/src/types.d.ts.map +1 -1
  141. package/dist/src/validator.d.ts +19 -28
  142. package/dist/src/validator.d.ts.map +1 -1
  143. package/dist/src/validator.js +315 -113
  144. package/dist/src/validator.js.map +1 -1
  145. package/examples/claude-desktop-burp-config.json +6 -6
  146. package/package.json +21 -11
@@ -0,0 +1,161 @@
1
+ import { createInterface } from "readline";
2
+ import { ScopeEnforcementProxy } from "../proxy.js";
3
+ /**
4
+ * SSE transport — connects to an upstream MCP server via SSE protocol.
5
+ *
6
+ * MCP SSE protocol:
7
+ * 1. GET <upstream> → SSE stream, first event is "endpoint" with sessionId
8
+ * 2. POST <upstream><sessionId> with JSON-RPC body → sends messages
9
+ * 3. Responses arrive on the SSE stream as "message" events
10
+ *
11
+ * Agent communicates with us via stdio (stdin/stdout).
12
+ */
13
+ export async function runSseProxy(proxy, upstreamUrl) {
14
+ const auditLogger = proxy.getAuditLogger();
15
+ auditLogger.start();
16
+ const TAG = "[integsec-agentic-pentest-proxy]";
17
+ // Step 1: Connect to SSE endpoint and get session ID
18
+ console.error(`${TAG} Connecting to upstream SSE at ${upstreamUrl}...`);
19
+ let sessionEndpoint;
20
+ let sseAbortController = new AbortController();
21
+ async function connectSse() {
22
+ return new Promise(async (resolve, reject) => {
23
+ try {
24
+ const resp = await fetch(upstreamUrl, {
25
+ headers: { Accept: "text/event-stream" },
26
+ signal: sseAbortController.signal,
27
+ });
28
+ if (!resp.ok) {
29
+ reject(new Error(`SSE connection failed: ${resp.status} ${resp.statusText}`));
30
+ return;
31
+ }
32
+ if (!resp.body) {
33
+ reject(new Error("SSE response has no body"));
34
+ return;
35
+ }
36
+ const reader = resp.body.getReader();
37
+ const decoder = new TextDecoder();
38
+ let buffer = "";
39
+ let currentEvent = "";
40
+ let resolved = false;
41
+ // Read SSE stream in background
42
+ (async () => {
43
+ try {
44
+ while (true) {
45
+ const { done, value } = await reader.read();
46
+ if (done)
47
+ break;
48
+ buffer += decoder.decode(value, { stream: true });
49
+ const lines = buffer.split("\n");
50
+ buffer = lines.pop() ?? "";
51
+ for (const line of lines) {
52
+ if (line.startsWith("event: ")) {
53
+ currentEvent = line.slice(7).trim();
54
+ }
55
+ else if (line.startsWith("data: ")) {
56
+ const data = line.slice(6);
57
+ if (currentEvent === "endpoint" && !resolved) {
58
+ // data is like "?sessionId=xxx"
59
+ resolved = true;
60
+ resolve(data);
61
+ }
62
+ else if (currentEvent === "message") {
63
+ // JSON-RPC response from upstream — forward to agent via stdout
64
+ // Capture server name from initialize response
65
+ if (!proxy.getServerName()) {
66
+ try {
67
+ const msg = JSON.parse(data);
68
+ const name = msg?.result?.serverInfo?.name;
69
+ if (name && typeof name === "string") {
70
+ proxy.setServerName(name);
71
+ console.error(`${TAG} Upstream server: ${name}`);
72
+ }
73
+ }
74
+ catch {
75
+ // Not parseable — ignore
76
+ }
77
+ }
78
+ process.stdout.write(data + "\n");
79
+ }
80
+ currentEvent = "";
81
+ }
82
+ }
83
+ }
84
+ }
85
+ catch (err) {
86
+ if (err.name !== "AbortError") {
87
+ console.error(`${TAG} SSE stream error: ${err.message}`);
88
+ }
89
+ }
90
+ })();
91
+ }
92
+ catch (err) {
93
+ reject(err);
94
+ }
95
+ });
96
+ }
97
+ try {
98
+ sessionEndpoint = await connectSse();
99
+ console.error(`${TAG} SSE connected, session: ${sessionEndpoint}`);
100
+ }
101
+ catch (err) {
102
+ console.error(`${TAG} Failed to connect to SSE upstream: ${err.message}`);
103
+ process.exit(1);
104
+ }
105
+ // Step 2: Read agent messages from stdin, validate, POST to upstream
106
+ const postUrl = new URL(sessionEndpoint, upstreamUrl).toString();
107
+ console.error(`${TAG} POST endpoint: ${postUrl}`);
108
+ const agentInput = createInterface({ input: process.stdin, crlfDelay: Infinity });
109
+ agentInput.on("line", async (line) => {
110
+ if (line.trim() === "")
111
+ return;
112
+ let message;
113
+ try {
114
+ message = JSON.parse(line);
115
+ }
116
+ catch {
117
+ // Never forward what we could not inspect — fail closed.
118
+ process.stdout.write(JSON.stringify(ScopeEnforcementProxy.parseErrorResponse()) + "\n");
119
+ return;
120
+ }
121
+ let forward;
122
+ let response;
123
+ try {
124
+ ({ forward, response } = await proxy.handleMessage(message));
125
+ }
126
+ catch (err) {
127
+ console.error(`${TAG} Dropped message after proxy error: ${err.message}`);
128
+ return;
129
+ }
130
+ if (!forward) {
131
+ // Blocked — return error to agent
132
+ if (response)
133
+ process.stdout.write(JSON.stringify(response) + "\n");
134
+ return;
135
+ }
136
+ try {
137
+ // Forward to upstream via HTTP POST
138
+ const resp = await fetch(postUrl, {
139
+ method: "POST",
140
+ headers: { "Content-Type": "application/json" },
141
+ body: JSON.stringify(message),
142
+ });
143
+ if (!resp.ok) {
144
+ console.error(`${TAG} Upstream POST failed: ${resp.status} ${resp.statusText}`);
145
+ }
146
+ // Response comes back via SSE stream, not the POST response
147
+ }
148
+ catch (err) {
149
+ console.error(`${TAG} Failed to forward message: ${err.message}`);
150
+ }
151
+ });
152
+ // Cleanup
153
+ const cleanup = async () => {
154
+ sseAbortController.abort();
155
+ await auditLogger.stop();
156
+ process.exit(0);
157
+ };
158
+ process.on("SIGINT", cleanup);
159
+ process.on("SIGTERM", cleanup);
160
+ }
161
+ //# sourceMappingURL=sse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse.js","sourceRoot":"","sources":["../../../src/transports/sse.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import type { ScopeEnforcementProxy } from "../proxy.js";
2
- export declare function runStdioProxy(proxy: ScopeEnforcementProxy, upstreamCommand: string, upstreamArgs?: string[]): Promise<void>;
1
+ import { ScopeEnforcementProxy } from "../proxy.js";
2
+ export declare function runStdioProxy(proxy: ScopeEnforcementProxy, upstreamCommand: string, upstreamArgs?: string[], startupDelayMs?: number): Promise<void>;
3
3
  //# sourceMappingURL=stdio.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../../src/transports/stdio.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEzD,wBAAsB,aAAa,CACjC,KAAK,EAAE,qBAAqB,EAC5B,eAAe,EAAE,MAAM,EACvB,YAAY,GAAE,MAAM,EAAO,GAC1B,OAAO,CAAC,IAAI,CAAC,CA+Gf"}
1
+ {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../../src/transports/stdio.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEpD,wBAAsB,aAAa,CACjC,KAAK,EAAE,qBAAqB,EAC5B,eAAe,EAAE,MAAM,EACvB,YAAY,GAAE,MAAM,EAAO,EAC3B,cAAc,SAAI,GACjB,OAAO,CAAC,IAAI,CAAC,CAkJf"}
@@ -1,6 +1,7 @@
1
1
  import { spawn } from "child_process";
2
2
  import { createInterface } from "readline";
3
- export async function runStdioProxy(proxy, upstreamCommand, upstreamArgs = []) {
3
+ import { ScopeEnforcementProxy } from "../proxy.js";
4
+ export async function runStdioProxy(proxy, upstreamCommand, upstreamArgs = [], startupDelayMs = 0) {
4
5
  // On Windows, commands like "npx" are .cmd wrappers that require shell
5
6
  // resolution, and paths may contain spaces (e.g. "C:\Program Files\...").
6
7
  // Build a single quoted command string and use shell: true with no args
@@ -16,63 +17,79 @@ export async function runStdioProxy(proxy, upstreamCommand, upstreamArgs = []) {
16
17
  }
17
18
  const auditLogger = proxy.getAuditLogger();
18
19
  auditLogger.start();
19
- // Buffer messages until upstream is ready. Some upstream servers (e.g. Burp's
20
- // Java MCP proxy) need time to establish their own connections before they can
21
- // handle JSON-RPC messages. We detect readiness when the upstream produces its
22
- // first stdout output, OR after a timeout (whichever comes first).
23
- let upstreamReady = false;
20
+ // Standard MCP servers print nothing until they receive a request, and the
21
+ // child's stdin pipe buffers anything written before it starts reading, so
22
+ // by default messages are forwarded immediately. Some bridges (e.g. Burp's
23
+ // legacy Java stdio proxy) drop messages sent before they finish connecting;
24
+ // for those, UPSTREAM_STARTUP_DELAY_MS holds messages until the upstream
25
+ // prints its first line or the delay expires.
26
+ let upstreamReady = startupDelayMs <= 0;
24
27
  const pendingMessages = [];
25
- const READY_TIMEOUT_MS = 20_000;
26
28
  function flushPending() {
27
29
  for (const msg of pendingMessages) {
28
30
  upstream.stdin.write(msg + "\n");
29
31
  }
30
32
  pendingMessages.length = 0;
31
33
  }
32
- const readyTimer = setTimeout(() => {
33
- if (!upstreamReady) {
34
- upstreamReady = true;
35
- console.error("[integsec-agentic-pentest-proxy] Upstream ready (timeout)");
36
- flushPending();
34
+ function markReady(why) {
35
+ if (upstreamReady)
36
+ return;
37
+ upstreamReady = true;
38
+ clearTimeout(readyTimer);
39
+ console.error(`[integsec-agentic-pentest-proxy] Upstream ready (${why})`);
40
+ flushPending();
41
+ }
42
+ const readyTimer = setTimeout(() => markReady("startup delay elapsed"), Math.max(startupDelayMs, 0));
43
+ function sendUpstream(line) {
44
+ if (upstreamReady) {
45
+ upstream.stdin.write(line + "\n");
46
+ }
47
+ else {
48
+ pendingMessages.push(line);
37
49
  }
38
- }, READY_TIMEOUT_MS);
50
+ }
51
+ function replyToAgent(message) {
52
+ process.stdout.write(JSON.stringify(message) + "\n");
53
+ }
39
54
  const agentInput = createInterface({ input: process.stdin, crlfDelay: Infinity });
40
55
  const upstreamOutput = createInterface({ input: upstream.stdout, crlfDelay: Infinity });
41
56
  // Agent → Proxy → Upstream
42
- agentInput.on("line", async (line) => {
57
+ const inFlight = new Set();
58
+ agentInput.on("line", (line) => {
59
+ const task = handleAgentLine(line);
60
+ inFlight.add(task);
61
+ void task.finally(() => inFlight.delete(task));
62
+ });
63
+ async function handleAgentLine(line) {
64
+ if (line.trim() === "")
65
+ return;
66
+ let message;
67
+ try {
68
+ message = JSON.parse(line);
69
+ }
70
+ catch {
71
+ // Never forward what we could not inspect — fail closed.
72
+ replyToAgent(ScopeEnforcementProxy.parseErrorResponse());
73
+ return;
74
+ }
43
75
  try {
44
- const message = JSON.parse(line);
45
76
  const { forward, response } = await proxy.handleMessage(message);
46
77
  if (forward) {
47
- if (upstreamReady) {
48
- upstream.stdin.write(line + "\n");
49
- }
50
- else {
51
- pendingMessages.push(line);
52
- }
78
+ // The upstream must receive the same parsed object that was checked.
79
+ // Reserializing removes duplicate-key parser differentials.
80
+ sendUpstream(JSON.stringify(message));
53
81
  }
54
82
  else if (response) {
55
- process.stdout.write(JSON.stringify(response) + "\n");
83
+ replyToAgent(response);
56
84
  }
57
85
  }
58
- catch {
59
- // Malformed JSON — pass through conservatively
60
- if (upstreamReady) {
61
- upstream.stdin.write(line + "\n");
62
- }
63
- else {
64
- pendingMessages.push(line);
65
- }
86
+ catch (err) {
87
+ console.error(`[integsec-agentic-pentest-proxy] Dropped message after proxy error: ${err instanceof Error ? err.message : String(err)}`);
66
88
  }
67
- });
89
+ }
68
90
  // Upstream → Agent (pass through all responses, capture server name)
69
91
  upstreamOutput.on("line", (line) => {
70
- if (!upstreamReady) {
71
- upstreamReady = true;
72
- clearTimeout(readyTimer);
73
- console.error("[integsec-agentic-pentest-proxy] Upstream ready (first output)");
74
- flushPending();
75
- }
92
+ markReady("first output");
76
93
  // Capture server name from the initialize response
77
94
  if (!proxy.getServerName()) {
78
95
  try {
@@ -89,19 +106,31 @@ export async function runStdioProxy(proxy, upstreamCommand, upstreamArgs = []) {
89
106
  }
90
107
  process.stdout.write(line + "\n");
91
108
  });
92
- upstream.on("exit", async (code) => {
109
+ const shutdown = async (code) => {
93
110
  await auditLogger.stop();
94
- process.exit(code ?? 0);
111
+ process.exit(code);
112
+ };
113
+ upstream.on("exit", (code) => {
114
+ void shutdown(code ?? 0);
95
115
  });
96
- process.on("SIGINT", async () => {
97
- await auditLogger.stop();
98
- upstream.kill();
99
- process.exit(0);
100
- });
101
- process.on("SIGTERM", async () => {
102
- await auditLogger.stop();
103
- upstream.kill();
104
- process.exit(0);
116
+ // Agent closed its end (e.g. the MCP client quit): flush the audit trail,
117
+ // close the upstream's stdin so it can exit cleanly, and force-exit if it
118
+ // does not within a few seconds.
119
+ agentInput.on("close", async () => {
120
+ await Promise.allSettled([...inFlight]);
121
+ markReady("agent closed input");
122
+ await auditLogger.flush();
123
+ upstream.stdin?.end();
124
+ setTimeout(() => {
125
+ upstream.kill();
126
+ void shutdown(0);
127
+ }, 3000).unref();
105
128
  });
129
+ for (const signal of ["SIGINT", "SIGTERM"]) {
130
+ process.on(signal, async () => {
131
+ upstream.kill();
132
+ await shutdown(0);
133
+ });
134
+ }
106
135
  }
107
136
  //# sourceMappingURL=stdio.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../../src/transports/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAqB,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAG3C,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAA4B,EAC5B,eAAuB,EACvB,eAAyB,EAAE;IAE3B,uEAAuE;IACvE,0EAA0E;IAC1E,wEAAwE;IACxE,qDAAqD;IACrD,MAAM,KAAK,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9D,MAAM,SAAS,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC,EAAE,GAAG,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjF,MAAM,QAAQ,GAAiB,KAAK,CAAC,SAAS,EAAE;QAC9C,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC;QAClC,KAAK,EAAE,IAAI;KACZ,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,WAAW,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC;IAC3C,WAAW,CAAC,KAAK,EAAE,CAAC;IAEpB,8EAA8E;IAC9E,+EAA+E;IAC/E,+EAA+E;IAC/E,mEAAmE;IACnE,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,MAAM,eAAe,GAAa,EAAE,CAAC;IACrC,MAAM,gBAAgB,GAAG,MAAM,CAAC;IAEhC,SAAS,YAAY;QACnB,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;YAClC,QAAQ,CAAC,KAAM,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;QACpC,CAAC;QACD,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,MAAM,UAAU,GAAG,UAAU,CAAC,GAAG,EAAE;QACjC,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,aAAa,GAAG,IAAI,CAAC;YACrB,OAAO,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;YAC3E,YAAY,EAAE,CAAC;QACjB,CAAC;IACH,CAAC,EAAE,gBAAgB,CAAC,CAAC;IAErB,MAAM,UAAU,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;IAClF,MAAM,cAAc,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;IAExF,2BAA2B;IAC3B,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACnC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACjC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YACjE,IAAI,OAAO,EAAE,CAAC;gBACZ,IAAI,aAAa,EAAE,CAAC;oBAClB,QAAQ,CAAC,KAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;gBACrC,CAAC;qBAAM,CAAC;oBACN,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC7B,CAAC;YACH,CAAC;iBAAM,IAAI,QAAQ,EAAE,CAAC;gBACpB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,+CAA+C;YAC/C,IAAI,aAAa,EAAE,CAAC;gBAClB,QAAQ,CAAC,KAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;YACrC,CAAC;iBAAM,CAAC;gBACN,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,qEAAqE;IACrE,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QACjC,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,aAAa,GAAG,IAAI,CAAC;YACrB,YAAY,CAAC,UAAU,CAAC,CAAC;YACzB,OAAO,CAAC,KAAK,CAAC,gEAAgE,CAAC,CAAC;YAChF,YAAY,EAAE,CAAC;QACjB,CAAC;QAED,mDAAmD;QACnD,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC7B,MAAM,IAAI,GAAG,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC;gBAC3C,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACrC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;oBAC1B,OAAO,CAAC,KAAK,CAAC,qDAAqD,IAAI,EAAE,CAAC,CAAC;gBAC7E,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,oBAAoB;YACtB,CAAC;QACH,CAAC;QAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACjC,MAAM,WAAW,CAAC,IAAI,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QAC9B,MAAM,WAAW,CAAC,IAAI,EAAE,CAAC;QACzB,QAAQ,CAAC,IAAI,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;QAC/B,MAAM,WAAW,CAAC,IAAI,EAAE,CAAC;QACzB,QAAQ,CAAC,IAAI,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../../src/transports/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAqB,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAA4B,EAC5B,eAAuB,EACvB,eAAyB,EAAE,EAC3B,cAAc,GAAG,CAAC;IAElB,uEAAuE;IACvE,0EAA0E;IAC1E,wEAAwE;IACxE,qDAAqD;IACrD,MAAM,KAAK,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9D,MAAM,SAAS,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC,EAAE,GAAG,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjF,MAAM,QAAQ,GAAiB,KAAK,CAAC,SAAS,EAAE;QAC9C,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC;QAClC,KAAK,EAAE,IAAI;KACZ,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,WAAW,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC;IAC3C,WAAW,CAAC,KAAK,EAAE,CAAC;IAEpB,2EAA2E;IAC3E,2EAA2E;IAC3E,2EAA2E;IAC3E,6EAA6E;IAC7E,yEAAyE;IACzE,8CAA8C;IAC9C,IAAI,aAAa,GAAG,cAAc,IAAI,CAAC,CAAC;IACxC,MAAM,eAAe,GAAa,EAAE,CAAC;IAErC,SAAS,YAAY;QACnB,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;YAClC,QAAQ,CAAC,KAAM,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;QACpC,CAAC;QACD,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,SAAS,SAAS,CAAC,GAAW;QAC5B,IAAI,aAAa;YAAE,OAAO;QAC1B,aAAa,GAAG,IAAI,CAAC;QACrB,YAAY,CAAC,UAAU,CAAC,CAAC;QACzB,OAAO,CAAC,KAAK,CAAC,oDAAoD,GAAG,GAAG,CAAC,CAAC;QAC1E,YAAY,EAAE,CAAC;IACjB,CAAC;IAED,MAAM,UAAU,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,uBAAuB,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,CAAC;IAErG,SAAS,YAAY,CAAC,IAAY;QAChC,IAAI,aAAa,EAAE,CAAC;YAClB,QAAQ,CAAC,KAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;QACrC,CAAC;aAAM,CAAC;YACN,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,SAAS,YAAY,CAAC,OAAgB;QACpC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,UAAU,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;IAClF,MAAM,cAAc,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;IAExF,2BAA2B;IAC3B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAiB,CAAC;IAC1C,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QAC7B,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;QACnC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACnB,KAAK,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,KAAK,UAAU,eAAe,CAAC,IAAY;QACzC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO;QAE/B,IAAI,OAAgB,CAAC;QACrB,IAAI,CAAC;YACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;QAAC,MAAM,CAAC;YACP,yDAAyD;YACzD,YAAY,CAAC,qBAAqB,CAAC,kBAAkB,EAAE,CAAC,CAAC;YACzD,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YACjE,IAAI,OAAO,EAAE,CAAC;gBACZ,qEAAqE;gBACrE,4DAA4D;gBAC5D,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;YACxC,CAAC;iBAAM,IAAI,QAAQ,EAAE,CAAC;gBACpB,YAAY,CAAC,QAAQ,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CACX,uEAAuE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAC1H,CAAC;QACJ,CAAC;IACH,CAAC;IAED,qEAAqE;IACrE,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QACjC,SAAS,CAAC,cAAc,CAAC,CAAC;QAE1B,mDAAmD;QACnD,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC7B,MAAM,IAAI,GAAG,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC;gBAC3C,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACrC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;oBAC1B,OAAO,CAAC,KAAK,CAAC,qDAAqD,IAAI,EAAE,CAAC,CAAC;gBAC7E,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,oBAAoB;YACtB,CAAC;QACH,CAAC;QAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,KAAK,EAAE,IAAY,EAAkB,EAAE;QACtD,MAAM,WAAW,CAAC,IAAI,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC,CAAC;IAEF,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QAC3B,KAAK,QAAQ,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;IAEH,0EAA0E;IAC1E,0EAA0E;IAC1E,iCAAiC;IACjC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE;QAChC,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;QACxC,SAAS,CAAC,oBAAoB,CAAC,CAAC;QAChC,MAAM,WAAW,CAAC,KAAK,EAAE,CAAC;QAC1B,QAAQ,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC;QACtB,UAAU,CAAC,GAAG,EAAE;YACd,QAAQ,CAAC,IAAI,EAAE,CAAC;YAChB,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC;QACnB,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;IAEH,KAAK,MAAM,MAAM,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAU,EAAE,CAAC;QACpD,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE;YAC5B,QAAQ,CAAC,IAAI,EAAE,CAAC;YAChB,MAAM,QAAQ,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
@@ -1,4 +1,4 @@
1
- export type Decision = "ALLOWED" | "BLOCKED_EXCLUDED_TARGET" | "BLOCKED_NOT_IN_SCOPE" | "BLOCKED_OUTSIDE_WINDOW" | "BLOCKED_TECHNIQUE" | "BLOCKED_DNS_FAILED" | "ALLOWED_NO_TARGET";
1
+ export type Decision = "ALLOWED" | "BLOCKED_EXCLUDED_TARGET" | "BLOCKED_NOT_IN_SCOPE" | "BLOCKED_OUTSIDE_WINDOW" | "BLOCKED_TECHNIQUE" | "BLOCKED_DNS_FAILED" | "BLOCKED_RESTRICTED_IP" | "BLOCKED_INVALID_REQUEST" | "BLOCKED_UNINSPECTABLE_COMMAND" | "BLOCKED_INTERNAL_ERROR" | "ALLOWED_NO_TARGET";
2
2
  export interface ValidationResult {
3
3
  decision: Decision;
4
4
  reason: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAChB,SAAS,GACT,yBAAyB,GACzB,sBAAsB,GACtB,wBAAwB,GACxB,mBAAmB,GACnB,oBAAoB,GACpB,mBAAmB,CAAC;AAExB,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,QAAQ,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE;QAClB,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,IAAI,EAAE,MAAM,EAAE,CAAC;QACf,cAAc,EAAE,MAAM,EAAE,CAAC;KAC1B,CAAC;IACF,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,iBAAiB,EAAE;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;CACH"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAChB,SAAS,GACT,yBAAyB,GACzB,sBAAsB,GACtB,wBAAwB,GACxB,mBAAmB,GACnB,oBAAoB,GACpB,uBAAuB,GACvB,yBAAyB,GACzB,+BAA+B,GAC/B,wBAAwB,GACxB,mBAAmB,CAAC;AAExB,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,QAAQ,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE;QAClB,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,IAAI,EAAE,MAAM,EAAE,CAAC;QACf,cAAc,EAAE,MAAM,EAAE,CAAC;KAC1B,CAAC;IACF,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,iBAAiB,EAAE;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;CACH"}
@@ -4,14 +4,22 @@
4
4
  * ScopeValidator — the core orchestrator that ties all validation together.
5
5
  *
6
6
  * Validation steps (in exact order):
7
- * 1. Technique block check
7
+ * 0. Request shape check (tool name string, arguments object) — fail closed
8
+ * 1. Technique check (excluded_techniques, then authorized_techniques)
8
9
  * 2. Time window check
9
- * 3. Target extraction
10
+ * 3. Target extraction — EVERY target in the call (arrays, lists, nested
11
+ * options, command lines)
10
12
  * 4. If no target found → ALLOWED_NO_TARGET
11
- * 5. DNS resolution (fail closed on NXDOMAIN)
12
- * 6. Exclusion check (exclusions win over authorizations)
13
- * 7. Authorization check (domain pattern match OR IP CIDR match)
14
- * 8. No match → BLOCKED_NOT_IN_SCOPE
13
+ * Then, for each target (the call is blocked if ANY target is blocked):
14
+ * 5. Cloud account match (authorized_targets.cloud_accounts)
15
+ * 6. CIDR targets: must not overlap an exclusion, must sit inside an
16
+ * authorized range (no DNS)
17
+ * 7. DNS resolution (fail closed on NXDOMAIN)
18
+ * 8. Exclusion check (exclusions win over authorizations)
19
+ * 9. Authorization check (domain / URL host match, or IP CIDR match);
20
+ * authorized hostnames resolving to loopback / link-local / metadata
21
+ * addresses are blocked unless those IPs are explicitly in ip_ranges
22
+ * 10. No match → BLOCKED_NOT_IN_SCOPE
15
23
  *
16
24
  * SECURITY NOTE: This module is the gatekeeper for all tool calls. Every
17
25
  * check order matters — do not reorder without updating tests.
@@ -23,29 +31,12 @@ export declare class ScopeValidator {
23
31
  private readonly manifest;
24
32
  private readonly dnsResolver;
25
33
  private readonly techniqueChecker;
26
- constructor(manifest: ScopeManifest, dnsResolver?: DnsResolver, techniqueChecker?: TechniqueChecker);
34
+ /** URL scope entries paired with their hostnames for prefix checks. */
35
+ private readonly urlHosts;
36
+ private readonly allowUnstructuredCommands;
37
+ constructor(manifest: ScopeManifest, dnsResolver?: DnsResolver, techniqueChecker?: TechniqueChecker, allowUnstructuredCommands?: boolean);
27
38
  validate(toolName: string, params: Record<string, unknown>): Promise<ValidationResult>;
28
- /**
29
- * Check whether `target` matches any entry in `excluded` (case-insensitive
30
- * exact string match).
31
- */
32
- private isExcluded;
33
- /**
34
- * Find the first authorized domain pattern that matches `hostname`.
35
- * Returns the matching pattern string, or null if no match.
36
- */
37
- private findMatchingDomain;
38
- /**
39
- * Find the first authorized CIDR range that contains `ip`.
40
- * Returns the matching CIDR string, or null if no match.
41
- *
42
- * Note: RFC-1918 and cloud metadata IPs are only allowed if they explicitly
43
- * appear within an authorized ip_range entry. This function performs an
44
- * exact `isIpInCidr` check — there is no implicit deny for private ranges
45
- * because the exclusion of a private IP from the authorized list naturally
46
- * means it will fall through to BLOCKED_NOT_IN_SCOPE in Step 8.
47
- */
48
- private findMatchingIpRange;
39
+ private validateTarget;
49
40
  /**
50
41
  * Build a ValidationResult, automatically populating durationMs.
51
42
  */
@@ -1 +1 @@
1
- {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAElE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;IACzC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;gBAGlD,QAAQ,EAAE,aAAa,EACvB,WAAW,CAAC,EAAE,WAAW,EACzB,gBAAgB,CAAC,EAAE,gBAAgB;IAO/B,QAAQ,CACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,gBAAgB,CAAC;IA0I5B;;;OAGG;IACH,OAAO,CAAC,UAAU;IAKlB;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IAY1B;;;;;;;;;OASG;IACH,OAAO,CAAC,mBAAmB;IAS3B;;OAEG;IACH,OAAO,CAAC,MAAM;CASf"}
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAElE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAY1D,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;IACzC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;IACpD,uEAAuE;IACvE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkC;IAC3D,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAU;gBAGlD,QAAQ,EAAE,aAAa,EACvB,WAAW,CAAC,EAAE,WAAW,EACzB,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,yBAAyB,UAAQ;IAW7B,QAAQ,CACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,gBAAgB,CAAC;YAyGd,cAAc;IAuJ5B;;OAEG;IACH,OAAO,CAAC,MAAM;CAMf"}