@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
@@ -4,44 +4,103 @@
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.
18
26
  */
19
- import { extractTarget } from "./extractor.js";
27
+ import { isIP } from "node:net";
28
+ import { extractTargets } from "./extractor.js";
20
29
  import { DnsResolver } from "./dns-resolver.js";
21
- import { isIpInCidr } from "./ip-matcher.js";
30
+ import { isCidr, isIpInCidr, isRangeWithin, isRestrictedIp, rangesOverlap } from "./ip-matcher.js";
22
31
  import { matchesDomain } from "./domain-matcher.js";
23
32
  import { TechniqueChecker } from "./technique-checker.js";
33
+ const SAFE_TARGETLESS_TOOLS = new Set([
34
+ "whoami", "date", "ls", "list_tools", "get_version", "list_pentests",
35
+ ]);
36
+ const UNSTRUCTURED_KEYS = new Set([
37
+ "command", "cmd", "command_line", "commandline", "cmdline", "shell_command",
38
+ "args", "extra_args", "additional_args",
39
+ ]);
24
40
  export class ScopeValidator {
25
41
  manifest;
26
42
  dnsResolver;
27
43
  techniqueChecker;
28
- constructor(manifest, dnsResolver, techniqueChecker) {
44
+ /** URL scope entries paired with their hostnames for prefix checks. */
45
+ urlHosts;
46
+ allowUnstructuredCommands;
47
+ constructor(manifest, dnsResolver, techniqueChecker, allowUnstructuredCommands = false) {
29
48
  this.manifest = manifest;
30
49
  this.dnsResolver = dnsResolver ?? new DnsResolver();
31
50
  this.techniqueChecker = techniqueChecker ?? new TechniqueChecker();
51
+ this.allowUnstructuredCommands = allowUnstructuredCommands;
52
+ this.urlHosts = manifest.authorized_targets.urls
53
+ .map((url) => ({ host: hostOf(url), url }))
54
+ .filter((u) => u.host !== null);
32
55
  }
33
56
  async validate(toolName, params) {
34
57
  const startTime = Date.now();
35
58
  // ─────────────────────────────────────────────────────────────────────────
36
- // Step 1: Technique block check
59
+ // Step 0: Request shape — anything we cannot inspect is blocked
37
60
  // ─────────────────────────────────────────────────────────────────────────
38
- if (this.techniqueChecker.isBlocked(toolName, this.manifest.excluded_techniques)) {
39
- const category = this.techniqueChecker.getCategory(toolName) ?? "unknown";
61
+ if (typeof toolName !== "string" || toolName === "") {
62
+ return this.result(startTime, {
63
+ decision: "BLOCKED_INVALID_REQUEST",
64
+ reason: "Tool name is missing or not a string; cannot validate.",
65
+ });
66
+ }
67
+ if (typeof params !== "object" || params === null || Array.isArray(params)) {
68
+ return this.result(startTime, {
69
+ decision: "BLOCKED_INVALID_REQUEST",
70
+ reason: `Tool arguments must be a JSON object (got ${Array.isArray(params) ? "array" : typeof params}); cannot validate.`,
71
+ });
72
+ }
73
+ if (hasUninspectableDepth(params)) {
74
+ return this.result(startTime, {
75
+ decision: "BLOCKED_INVALID_REQUEST",
76
+ reason: "Tool arguments are nested more deeply than the target extractor can inspect.",
77
+ });
78
+ }
79
+ // ─────────────────────────────────────────────────────────────────────────
80
+ // Step 1: Technique checks
81
+ // ─────────────────────────────────────────────────────────────────────────
82
+ const category = this.techniqueChecker.getCategory(toolName);
83
+ if (category !== null && this.manifest.excluded_techniques.includes(category)) {
40
84
  return this.result(startTime, {
41
85
  decision: "BLOCKED_TECHNIQUE",
42
86
  reason: `Tool "${toolName}" belongs to the blocked technique category "${category}".`,
43
87
  });
44
88
  }
89
+ const authorizedTechniques = this.manifest.authorized_techniques;
90
+ if (category !== null &&
91
+ authorizedTechniques.length > 0 &&
92
+ !authorizedTechniques.includes(category)) {
93
+ return this.result(startTime, {
94
+ decision: "BLOCKED_TECHNIQUE",
95
+ reason: `Tool "${toolName}" belongs to technique category "${category}", which is not in authorized_techniques (${authorizedTechniques.join(", ")}).`,
96
+ });
97
+ }
98
+ if (!this.allowUnstructuredCommands && hasUnstructuredCommand(params)) {
99
+ return this.result(startTime, {
100
+ decision: "BLOCKED_UNINSPECTABLE_COMMAND",
101
+ reason: "Free-form command or argument fields cannot be reliably checked against engagement scope.",
102
+ });
103
+ }
45
104
  // ─────────────────────────────────────────────────────────────────────────
46
105
  // Step 2: Time window check
47
106
  // ─────────────────────────────────────────────────────────────────────────
@@ -55,137 +114,172 @@ export class ScopeValidator {
55
114
  });
56
115
  }
57
116
  // ─────────────────────────────────────────────────────────────────────────
58
- // Step 3: Target extraction
59
- // ─────────────────────────────────────────────────────────────────────────
60
- const extraction = extractTarget(toolName, params);
61
- // ─────────────────────────────────────────────────────────────────────────
62
- // Step 4: If no target found → ALLOWED_NO_TARGET
117
+ // Steps 3–4: Extract every target
63
118
  // ─────────────────────────────────────────────────────────────────────────
64
- if (extraction === null) {
65
- return this.result(startTime, {
66
- decision: "ALLOWED_NO_TARGET",
67
- reason: "No target-like parameter found in tool call; allowing by default.",
68
- });
119
+ const extractions = extractTargets(toolName, params);
120
+ if (extractions.length === 0) {
121
+ return this.result(startTime, SAFE_TARGETLESS_TOOLS.has(toolName.toLowerCase())
122
+ ? { decision: "ALLOWED_NO_TARGET", reason: `Targetless local tool "${toolName}" is explicitly allowed.` }
123
+ : { decision: "BLOCKED_INVALID_REQUEST", reason: `No target could be verified for tool "${toolName}".` });
69
124
  }
70
- const target = extraction.target;
71
125
  // ─────────────────────────────────────────────────────────────────────────
72
- // Step 5: DNS resolution
126
+ // Steps 5–10: Every target must be in scope
73
127
  // ─────────────────────────────────────────────────────────────────────────
128
+ const allowed = [];
129
+ const requestUrls = collectHttpUrls(params);
130
+ for (const { target } of extractions) {
131
+ const r = await this.validateTarget(target, requestUrls);
132
+ if (r.decision !== "ALLOWED") {
133
+ return this.result(startTime, r);
134
+ }
135
+ allowed.push(r);
136
+ }
137
+ if (allowed.length === 1) {
138
+ return this.result(startTime, allowed[0]);
139
+ }
140
+ return this.result(startTime, {
141
+ decision: "ALLOWED",
142
+ reason: `All ${allowed.length} targets are in scope: ${allowed.map((r) => r.reason).join(" ")}`,
143
+ matchedScopeItem: [...new Set(allowed.map((r) => r.matchedScopeItem))].join(", "),
144
+ extractedTarget: allowed.map((r) => r.extractedTarget).join(", "),
145
+ resolvedIps: [...new Set(allowed.flatMap((r) => r.resolvedIps ?? []))],
146
+ });
147
+ }
148
+ // ---------------------------------------------------------------------------
149
+ // Per-target pipeline
150
+ // ---------------------------------------------------------------------------
151
+ async validateTarget(rawTarget, requestUrls) {
152
+ const target = normalizeHost(rawTarget);
153
+ const { ip_ranges: authorizedIpRanges, domains: authorizedDomains, cloud_accounts } = this.manifest.authorized_targets;
154
+ const excluded = this.manifest.excluded_targets;
155
+ const urlsForTarget = requestUrls.filter((url) => normalizeHost(url.hostname) === target);
156
+ // An explicit hostname or account exclusion does not need DNS. Check it
157
+ // first so an excluded target cannot turn into a DNS timeout or be
158
+ // authorized as a cloud account before the exclusion is considered.
159
+ const hostHit = excluded.find((entry) => matchesExclusion(target, entry));
160
+ if (hostHit !== undefined) {
161
+ return {
162
+ decision: "BLOCKED_EXCLUDED_TARGET",
163
+ reason: `Target "${target}" matches excluded target "${hostHit}".`,
164
+ extractedTarget: target,
165
+ resolvedIps: [],
166
+ };
167
+ }
168
+ // URL scope entries authorize only their scheme, host, port and path.
169
+ if (this.urlHosts.some((u) => u.host === target) &&
170
+ urlsForTarget.some((url) => !this.urlHosts.some((u) => u.host === target && urlWithinScope(url, u.url)))) {
171
+ return {
172
+ decision: "BLOCKED_NOT_IN_SCOPE",
173
+ reason: `A requested URL for "${target}" is outside its authorized URL prefix.`,
174
+ extractedTarget: target,
175
+ resolvedIps: [],
176
+ };
177
+ }
178
+ // Step 5: Cloud accounts (e.g. prowler/scoutsuite account IDs)
179
+ const matchedAccount = cloud_accounts.find((entry) => matchesCloudAccount(target, entry));
180
+ if (matchedAccount !== undefined) {
181
+ return {
182
+ decision: "ALLOWED",
183
+ reason: `Target "${target}" matches authorized cloud account "${matchedAccount}".`,
184
+ matchedScopeItem: matchedAccount,
185
+ extractedTarget: target,
186
+ resolvedIps: [],
187
+ };
188
+ }
189
+ // Step 6: CIDR targets — the whole range is what the tool will touch
190
+ if (isCidr(target)) {
191
+ const hit = excluded.find((entry) => rangesOverlap(target, entry));
192
+ if (hit !== undefined) {
193
+ return {
194
+ decision: "BLOCKED_EXCLUDED_TARGET",
195
+ reason: `Target range "${target}" includes excluded target "${hit}".`,
196
+ extractedTarget: target,
197
+ resolvedIps: [target],
198
+ };
199
+ }
200
+ const range = authorizedIpRanges.find((r) => isRangeWithin(target, r));
201
+ if (range !== undefined) {
202
+ return {
203
+ decision: "ALLOWED",
204
+ reason: `Target range "${target}" is within authorized range "${range}".`,
205
+ matchedScopeItem: range,
206
+ extractedTarget: target,
207
+ resolvedIps: [target],
208
+ };
209
+ }
210
+ return {
211
+ decision: "BLOCKED_NOT_IN_SCOPE",
212
+ reason: `Target range "${target}" is not fully contained in any authorized IP range.`,
213
+ extractedTarget: target,
214
+ resolvedIps: [target],
215
+ };
216
+ }
217
+ // Step 7: DNS resolution
74
218
  const resolvedIps = await this.dnsResolver.resolve(target);
75
219
  // For hostnames (not raw IPs), an empty resolution means NXDOMAIN — fail closed.
76
220
  // For raw IPs the resolver returns [ip] so resolvedIps will never be empty.
77
221
  if (resolvedIps.length === 0) {
78
- return this.result(startTime, {
222
+ return {
79
223
  decision: "BLOCKED_DNS_FAILED",
80
224
  reason: `DNS resolution for "${target}" returned no addresses (NXDOMAIN or resolution failure). Failing closed.`,
81
225
  extractedTarget: target,
82
226
  resolvedIps: [],
83
- });
227
+ };
84
228
  }
85
- // ─────────────────────────────────────────────────────────────────────────
86
- // Step 6: Exclusion check (exclusions win — checked before authorization)
87
- // ─────────────────────────────────────────────────────────────────────────
88
- const excluded = this.manifest.excluded_targets;
89
- // Check hostname/IP target against excluded list (case-insensitive exact match)
90
- if (this.isExcluded(target, excluded)) {
91
- return this.result(startTime, {
92
- decision: "BLOCKED_EXCLUDED_TARGET",
93
- reason: `Target "${target}" matches an excluded target.`,
94
- extractedTarget: target,
95
- resolvedIps,
96
- });
97
- }
98
- // Check each resolved IP against excluded list
229
+ // Step 8: Exclusion check (exclusions win — checked before authorization)
99
230
  for (const ip of resolvedIps) {
100
- if (this.isExcluded(ip, excluded)) {
101
- return this.result(startTime, {
231
+ const ipHit = excluded.find((entry) => matchesExclusion(ip, entry));
232
+ if (ipHit !== undefined) {
233
+ return {
102
234
  decision: "BLOCKED_EXCLUDED_TARGET",
103
- reason: `Resolved IP "${ip}" for target "${target}" matches an excluded target.`,
235
+ reason: `Resolved IP "${ip}" for target "${target}" matches excluded target "${ipHit}".`,
104
236
  extractedTarget: target,
105
237
  resolvedIps,
106
- });
238
+ };
107
239
  }
108
240
  }
109
- // ─────────────────────────────────────────────────────────────────────────
110
- // Step 7: Authorization check
111
- // ─────────────────────────────────────────────────────────────────────────
112
- const authorizedIpRanges = this.manifest.authorized_targets.ip_ranges;
113
- const authorizedDomains = this.manifest.authorized_targets.domains;
114
- // 7a: Check hostname against authorized domain patterns
115
- const matchedDomain = this.findMatchingDomain(target, authorizedDomains);
241
+ // Step 9a: Hostname against authorized domain patterns and URL hosts
242
+ const matchedDomain = authorizedDomains.find((pattern) => matchesDomain(target, pattern)) ??
243
+ this.urlHosts.find((u) => u.host === target &&
244
+ urlsForTarget.some((url) => urlWithinScope(url, u.url)))?.url ??
245
+ null;
116
246
  if (matchedDomain !== null) {
117
- return this.result(startTime, {
247
+ const restricted = resolvedIps.filter((ip) => isRestrictedIp(ip) && !authorizedIpRanges.some((r) => isIpInCidr(ip, r)));
248
+ if (restricted.length > 0) {
249
+ return {
250
+ decision: "BLOCKED_RESTRICTED_IP",
251
+ reason: `Target "${target}" matches "${matchedDomain}" but resolves to restricted address(es) ${restricted.join(", ")} (loopback/link-local/cloud metadata) that are not explicitly authorized in ip_ranges.`,
252
+ extractedTarget: target,
253
+ resolvedIps,
254
+ };
255
+ }
256
+ return {
118
257
  decision: "ALLOWED",
119
- reason: `Target "${target}" matches authorized domain pattern "${matchedDomain}".`,
258
+ reason: `Target "${target}" matches authorized scope item "${matchedDomain}".`,
120
259
  matchedScopeItem: matchedDomain,
121
260
  extractedTarget: target,
122
261
  resolvedIps,
123
- });
262
+ };
124
263
  }
125
- // 7b: Check resolved IPs against authorized IP ranges.
126
- // For RFC-1918 and cloud metadata IPs: only allow if explicitly in authorized ip_ranges.
127
- for (const ip of resolvedIps) {
128
- const matchedRange = this.findMatchingIpRange(ip, authorizedIpRanges);
129
- if (matchedRange !== null) {
130
- return this.result(startTime, {
131
- decision: "ALLOWED",
132
- reason: `Resolved IP "${ip}" for target "${target}" is in authorized range "${matchedRange}".`,
133
- matchedScopeItem: matchedRange,
134
- extractedTarget: target,
135
- resolvedIps,
136
- });
137
- }
264
+ // Step 9b: Resolved IPs against authorized IP ranges. Private, loopback
265
+ // and metadata IPs are only allowed when an ip_range explicitly covers them.
266
+ const matchedRanges = resolvedIps.map((ip) => authorizedIpRanges.find((r) => isIpInCidr(ip, r)));
267
+ if (matchedRanges.every((range) => range !== undefined)) {
268
+ return {
269
+ decision: "ALLOWED",
270
+ reason: `All resolved IPs for target "${target}" are within authorized IP ranges.`,
271
+ matchedScopeItem: [...new Set(matchedRanges)].join(", "),
272
+ extractedTarget: target,
273
+ resolvedIps,
274
+ };
138
275
  }
139
- // ─────────────────────────────────────────────────────────────────────────
140
- // Step 8: No match → BLOCKED_NOT_IN_SCOPE
141
- // ─────────────────────────────────────────────────────────────────────────
142
- return this.result(startTime, {
276
+ // Step 10: No match → BLOCKED_NOT_IN_SCOPE
277
+ return {
143
278
  decision: "BLOCKED_NOT_IN_SCOPE",
144
279
  reason: `Target "${target}" (resolved IPs: ${resolvedIps.join(", ")}) does not match any authorized target or domain.`,
145
280
  extractedTarget: target,
146
281
  resolvedIps,
147
- });
148
- }
149
- // ---------------------------------------------------------------------------
150
- // Private helpers
151
- // ---------------------------------------------------------------------------
152
- /**
153
- * Check whether `target` matches any entry in `excluded` (case-insensitive
154
- * exact string match).
155
- */
156
- isExcluded(target, excluded) {
157
- const lower = target.toLowerCase();
158
- return excluded.some((entry) => entry.toLowerCase() === lower);
159
- }
160
- /**
161
- * Find the first authorized domain pattern that matches `hostname`.
162
- * Returns the matching pattern string, or null if no match.
163
- */
164
- findMatchingDomain(hostname, patterns) {
165
- for (const pattern of patterns) {
166
- if (matchesDomain(hostname, pattern)) {
167
- return pattern;
168
- }
169
- }
170
- return null;
171
- }
172
- /**
173
- * Find the first authorized CIDR range that contains `ip`.
174
- * Returns the matching CIDR string, or null if no match.
175
- *
176
- * Note: RFC-1918 and cloud metadata IPs are only allowed if they explicitly
177
- * appear within an authorized ip_range entry. This function performs an
178
- * exact `isIpInCidr` check — there is no implicit deny for private ranges
179
- * because the exclusion of a private IP from the authorized list naturally
180
- * means it will fall through to BLOCKED_NOT_IN_SCOPE in Step 8.
181
- */
182
- findMatchingIpRange(ip, ranges) {
183
- for (const range of ranges) {
184
- if (isIpInCidr(ip, range)) {
185
- return range;
186
- }
187
- }
188
- return null;
282
+ };
189
283
  }
190
284
  /**
191
285
  * Build a ValidationResult, automatically populating durationMs.
@@ -197,4 +291,112 @@ export class ScopeValidator {
197
291
  };
198
292
  }
199
293
  }
294
+ // ---------------------------------------------------------------------------
295
+ // Helpers
296
+ // ---------------------------------------------------------------------------
297
+ /**
298
+ * Canonical form for comparisons: lower-case, IPv6 brackets removed, trailing
299
+ * DNS dots stripped ("hr.acme.com." and "HR.ACME.COM" both → "hr.acme.com").
300
+ */
301
+ function normalizeHost(value) {
302
+ let s = value.trim().toLowerCase();
303
+ if (s.startsWith("[") && s.endsWith("]"))
304
+ s = s.slice(1, -1);
305
+ while (s.endsWith("."))
306
+ s = s.slice(0, -1);
307
+ return s;
308
+ }
309
+ /** Hostname of a URL scope entry, or null if it is not a parseable URL. */
310
+ function hostOf(url) {
311
+ try {
312
+ const host = new URL(url).hostname;
313
+ return host ? normalizeHost(host) : null;
314
+ }
315
+ catch {
316
+ return null;
317
+ }
318
+ }
319
+ function urlWithinScope(request, scope) {
320
+ try {
321
+ const allowed = new URL(scope);
322
+ const basePath = allowed.pathname.replace(/\/$/, "");
323
+ return request.origin === allowed.origin &&
324
+ (request.pathname === basePath || request.pathname.startsWith(`${basePath}/`));
325
+ }
326
+ catch {
327
+ return false;
328
+ }
329
+ }
330
+ /** Find URLs in structured arguments and free-form command strings. */
331
+ function collectHttpUrls(value, depth = 0) {
332
+ if (depth > 8)
333
+ return [];
334
+ if (typeof value === "string") {
335
+ const urls = [];
336
+ for (const match of value.matchAll(/https?:\/\/[^\s"'`<>]+/gi)) {
337
+ try {
338
+ urls.push(new URL(match[0]));
339
+ }
340
+ catch { /* invalid URLs fail target validation */ }
341
+ }
342
+ return urls;
343
+ }
344
+ if (Array.isArray(value))
345
+ return value.flatMap((item) => collectHttpUrls(item, depth + 1));
346
+ if (value !== null && typeof value === "object") {
347
+ return Object.values(value).flatMap((item) => collectHttpUrls(item, depth + 1));
348
+ }
349
+ return [];
350
+ }
351
+ function hasUnstructuredCommand(value, depth = 0) {
352
+ if (depth > 8 || value === null || typeof value !== "object")
353
+ return false;
354
+ if (Array.isArray(value))
355
+ return value.some((item) => hasUnstructuredCommand(item, depth + 1));
356
+ return Object.entries(value).some(([key, item]) => UNSTRUCTURED_KEYS.has(key.toLowerCase()) || hasUnstructuredCommand(item, depth + 1));
357
+ }
358
+ function hasUninspectableDepth(value, depth = 0) {
359
+ if (value === null || typeof value !== "object")
360
+ return false;
361
+ if (depth > 4)
362
+ return true;
363
+ return Object.values(value).some((item) => hasUninspectableDepth(item, depth + 1));
364
+ }
365
+ /**
366
+ * Does `target` (normalized hostname or IP) match an excluded_targets entry?
367
+ * - IP / CIDR entries: target IP must fall inside the range.
368
+ * - "*.domain" entries: any subdomain of domain, at any depth.
369
+ * - URL entries: compared by hostname.
370
+ * - Anything else: exact hostname match.
371
+ */
372
+ function matchesExclusion(target, entry) {
373
+ const e = normalizeHost(entry);
374
+ if (!e)
375
+ return false;
376
+ if (isIP(e) !== 0 || isCidr(e)) {
377
+ return isIP(target) !== 0 && isIpInCidr(target, e);
378
+ }
379
+ if (e.startsWith("*.")) {
380
+ const base = e.slice(2);
381
+ return base.length > 0 && target.endsWith("." + base);
382
+ }
383
+ if (e.includes("://")) {
384
+ const host = hostOf(e);
385
+ return host !== null && host === target;
386
+ }
387
+ return e === target;
388
+ }
389
+ /**
390
+ * Cloud account entries look like "aws:123456789012". A target matches when it
391
+ * equals the entry or the part after the provider prefix.
392
+ */
393
+ function matchesCloudAccount(target, entry) {
394
+ const e = entry.trim().toLowerCase();
395
+ if (!e)
396
+ return false;
397
+ if (e === target)
398
+ return true;
399
+ const colon = e.indexOf(":");
400
+ return colon !== -1 && e.slice(colon + 1) === target;
401
+ }
200
402
  //# sourceMappingURL=validator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/validator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/validator.ts"],"names":[],"mappings":"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"}
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "mcpServers": {
3
3
  "burp-scoped": {
4
- "command": "C:\\Users\\MichelChamberland\\AppData\\Roaming\\npm\\integsec-agentic-pentest-proxy.cmd",
5
- "args": [],
4
+ "command": "npx",
5
+ "args": ["-y", "@integsec/agentic-pentest-proxy"],
6
6
  "env": {
7
- "SCOPE_MANIFEST_PATH": "C:/Work/mcp-scope-proxy/examples/scope-test-integsec.json",
7
+ "SCOPE_MANIFEST_PATH": "C:/path/to/scope.json",
8
8
  "MCP_TRANSPORT": "stdio",
9
- "UPSTREAM_MCP_COMMAND": "c:\\users\\michelchamberland\\appdata\\local\\programs\\burpsuitepro\\jre\\bin\\java.exe",
10
- "UPSTREAM_MCP_ARGS": "-jar,C:\\Users\\MichelChamberland\\AppData\\Roaming\\BurpSuite\\mcp-proxy\\mcp-proxy-all.jar,--sse-url,http://127.0.0.1:9876",
11
- "AUDIT_LOG_PATH": "C:/Work/mcp-scope-proxy/audit"
9
+ "UPSTREAM_MCP_COMMAND": "java",
10
+ "UPSTREAM_MCP_ARGS": "-jar,C:/path/to/mcp-proxy-all.jar,--sse-url,http://127.0.0.1:9876",
11
+ "AUDIT_LOG_PATH": "C:/path/to/audit"
12
12
  }
13
13
  }
14
14
  }
package/package.json CHANGED
@@ -1,24 +1,31 @@
1
1
  {
2
2
  "name": "@integsec/agentic-pentest-proxy",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "IntegSec Agentic Pentest MCP Proxy — enforce penetration testing engagement scope for AI agents",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/IntegSec/agentic-pentest-proxy.git"
8
+ },
5
9
  "type": "module",
6
10
  "bin": {
7
11
  "integsec-agentic-pentest-proxy": "dist/bin/integsec-agentic-pentest-proxy.js",
8
- "integsec-agentic-pentest-tui": "dist/bin/integsec-agentic-pentest-tui.js"
12
+ "integsec-agentic-pentest-tui": "dist/bin/integsec-agentic-pentest-tui.js",
13
+ "integsec-agentic-pentest-manifest": "dist/bin/integsec-agentic-pentest-manifest.js"
9
14
  },
10
15
  "files": [
11
16
  "dist/",
12
17
  "examples/",
13
- "README.md"
18
+ "README.md",
19
+ "LICENSE"
14
20
  ],
15
21
  "main": "./dist/src/index.js",
16
22
  "types": "./dist/src/index.d.ts",
17
23
  "scripts": {
18
- "build": "tsc",
24
+ "build": "tsc && node -e \"const fs=require('fs'),path=require('path');const src='src/builder/web/client-form.html',dst='dist/src/builder/web/client-form.html';fs.mkdirSync(path.dirname(dst),{recursive:true});fs.copyFileSync(src,dst);console.log('Copied',src,'->',dst);\"",
19
25
  "dev": "tsc --watch",
20
26
  "test": "vitest run",
21
27
  "test:watch": "vitest",
28
+ "driver": "vitest run --config vitest.driver.config.ts",
22
29
  "lint": "tsc --noEmit",
23
30
  "start": "node dist/bin/integsec-agentic-pentest-proxy.js"
24
31
  },
@@ -35,29 +42,32 @@
35
42
  "offensive-security"
36
43
  ],
37
44
  "author": "IntegSec",
38
- "license": "MIT",
45
+ "license": "Apache-2.0",
39
46
  "dependencies": {
40
47
  "@modelcontextprotocol/sdk": "^1.12.0",
41
48
  "dotenv": "^16.4.0",
42
49
  "ink": "^5.2.1",
43
50
  "ink-spinner": "^5.0.0",
44
- "ip-cidr": "^4.0.1",
51
+ "ipaddr.js": "^2.5.0",
45
52
  "react": "^18.3.1",
46
- "zod": "^3.24.0"
53
+ "zod": "^4.6.7"
47
54
  },
48
55
  "devDependencies": {
49
- "@types/node": "^20.0.0",
56
+ "@types/node": "^22.20.5",
50
57
  "@types/react": "^18.3.28",
51
58
  "typescript": "^5.7.0",
52
- "vitest": "^3.0.0"
59
+ "vitest": "^5.1.0"
53
60
  },
54
61
  "optionalDependencies": {
55
62
  "@aws-sdk/client-cloudwatch-logs": "^3.700.0",
63
+ "@aws-sdk/client-secrets-manager": "^3.1164.0",
56
64
  "@azure/identity": "^4.5.0",
65
+ "@azure/keyvault-secrets": "^4.12.0",
57
66
  "@azure/monitor-ingestion": "^1.1.0",
58
- "@google-cloud/logging": "^11.0.0"
67
+ "@google-cloud/logging": "^12.3.0",
68
+ "@google-cloud/secret-manager": "^7.2.0"
59
69
  },
60
70
  "engines": {
61
- "node": ">=20.0.0"
71
+ "node": ">=22.0.0"
62
72
  }
63
73
  }