@integsec/agentic-pentest-proxy 0.2.5 → 0.2.7
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.
- package/LICENSE +201 -0
- package/README.md +85 -717
- package/dist/bin/integsec-agentic-pentest-manifest.d.ts +3 -0
- package/dist/bin/integsec-agentic-pentest-manifest.d.ts.map +1 -0
- package/dist/bin/integsec-agentic-pentest-manifest.js +180 -0
- package/dist/bin/integsec-agentic-pentest-manifest.js.map +1 -0
- package/dist/bin/integsec-agentic-pentest-proxy.d.ts +1 -1
- package/dist/bin/integsec-agentic-pentest-proxy.d.ts.map +1 -1
- package/dist/bin/integsec-agentic-pentest-proxy.js +32 -4
- package/dist/bin/integsec-agentic-pentest-proxy.js.map +1 -1
- package/dist/bin/integsec-agentic-pentest-setup.d.ts +3 -0
- package/dist/bin/integsec-agentic-pentest-setup.d.ts.map +1 -0
- package/dist/bin/integsec-agentic-pentest-setup.js +92 -0
- package/dist/bin/integsec-agentic-pentest-setup.js.map +1 -0
- package/dist/src/audit/azure-monitor.d.ts +2 -2
- package/dist/src/audit/azure-monitor.d.ts.map +1 -1
- package/dist/src/audit/azure-monitor.js +8 -5
- package/dist/src/audit/azure-monitor.js.map +1 -1
- package/dist/src/audit/cloudwatch.d.ts.map +1 -1
- package/dist/src/audit/cloudwatch.js.map +1 -1
- package/dist/src/audit/gcp-logging.d.ts.map +1 -1
- package/dist/src/audit/gcp-logging.js +6 -7
- package/dist/src/audit/gcp-logging.js.map +1 -1
- package/dist/src/audit/index.d.ts +7 -0
- package/dist/src/audit/index.d.ts.map +1 -1
- package/dist/src/audit/index.js +11 -1
- package/dist/src/audit/index.js.map +1 -1
- package/dist/src/audit/local.d.ts.map +1 -1
- package/dist/src/audit/local.js +2 -1
- package/dist/src/audit/local.js.map +1 -1
- package/dist/src/builder/dry-run.d.ts +12 -0
- package/dist/src/builder/dry-run.d.ts.map +1 -0
- package/dist/src/builder/dry-run.js +103 -0
- package/dist/src/builder/dry-run.js.map +1 -0
- package/dist/src/builder/manifest-writer.d.ts +7 -0
- package/dist/src/builder/manifest-writer.d.ts.map +1 -0
- package/dist/src/builder/manifest-writer.js +17 -0
- package/dist/src/builder/manifest-writer.js.map +1 -0
- package/dist/src/builder/review-display.d.ts +10 -0
- package/dist/src/builder/review-display.d.ts.map +1 -0
- package/dist/src/builder/review-display.js +55 -0
- package/dist/src/builder/review-display.js.map +1 -0
- package/dist/src/builder/smart-validator.d.ts +39 -0
- package/dist/src/builder/smart-validator.d.ts.map +1 -0
- package/dist/src/builder/smart-validator.js +157 -0
- package/dist/src/builder/smart-validator.js.map +1 -0
- package/dist/src/builder/steps/domains.d.ts +10 -0
- package/dist/src/builder/steps/domains.d.ts.map +1 -0
- package/dist/src/builder/steps/domains.js +71 -0
- package/dist/src/builder/steps/domains.js.map +1 -0
- package/dist/src/builder/steps/engagement-info.d.ts +17 -0
- package/dist/src/builder/steps/engagement-info.d.ts.map +1 -0
- package/dist/src/builder/steps/engagement-info.js +49 -0
- package/dist/src/builder/steps/engagement-info.js.map +1 -0
- package/dist/src/builder/steps/engagement-window.d.ts +15 -0
- package/dist/src/builder/steps/engagement-window.d.ts.map +1 -0
- package/dist/src/builder/steps/engagement-window.js +57 -0
- package/dist/src/builder/steps/engagement-window.js.map +1 -0
- package/dist/src/builder/steps/exclusions.d.ts +13 -0
- package/dist/src/builder/steps/exclusions.d.ts.map +1 -0
- package/dist/src/builder/steps/exclusions.js +57 -0
- package/dist/src/builder/steps/exclusions.js.map +1 -0
- package/dist/src/builder/steps/ip-ranges.d.ts +10 -0
- package/dist/src/builder/steps/ip-ranges.d.ts.map +1 -0
- package/dist/src/builder/steps/ip-ranges.js +64 -0
- package/dist/src/builder/steps/ip-ranges.js.map +1 -0
- package/dist/src/builder/steps/review.d.ts +10 -0
- package/dist/src/builder/steps/review.d.ts.map +1 -0
- package/dist/src/builder/steps/review.js +29 -0
- package/dist/src/builder/steps/review.js.map +1 -0
- package/dist/src/builder/steps/techniques.d.ts +13 -0
- package/dist/src/builder/steps/techniques.d.ts.map +1 -0
- package/dist/src/builder/steps/techniques.js +68 -0
- package/dist/src/builder/steps/techniques.js.map +1 -0
- package/dist/src/builder/steps/urls-and-cloud.d.ts +15 -0
- package/dist/src/builder/steps/urls-and-cloud.d.ts.map +1 -0
- package/dist/src/builder/steps/urls-and-cloud.js +53 -0
- package/dist/src/builder/steps/urls-and-cloud.js.map +1 -0
- package/dist/src/builder/web/api.d.ts +9 -0
- package/dist/src/builder/web/api.d.ts.map +1 -0
- package/dist/src/builder/web/api.js +40 -0
- package/dist/src/builder/web/api.js.map +1 -0
- package/dist/src/builder/web/client-form.html +222 -0
- package/dist/src/builder/web/server.d.ts +14 -0
- package/dist/src/builder/web/server.d.ts.map +1 -0
- package/dist/src/builder/web/server.js +85 -0
- package/dist/src/builder/web/server.js.map +1 -0
- package/dist/src/builder/wizard.d.ts +9 -0
- package/dist/src/builder/wizard.d.ts.map +1 -0
- package/dist/src/builder/wizard.js +49 -0
- package/dist/src/builder/wizard.js.map +1 -0
- package/dist/src/config.d.ts +11 -1
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +33 -3
- package/dist/src/config.js.map +1 -1
- package/dist/src/dns-resolver.d.ts +10 -1
- package/dist/src/dns-resolver.d.ts.map +1 -1
- package/dist/src/dns-resolver.js +41 -3
- package/dist/src/dns-resolver.js.map +1 -1
- package/dist/src/extractor.d.ts +12 -0
- package/dist/src/extractor.d.ts.map +1 -1
- package/dist/src/extractor.js +386 -0
- package/dist/src/extractor.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/ip-matcher.d.ts +23 -0
- package/dist/src/ip-matcher.d.ts.map +1 -1
- package/dist/src/ip-matcher.js +96 -23
- package/dist/src/ip-matcher.js.map +1 -1
- package/dist/src/manifest-schema.d.ts +12 -62
- package/dist/src/manifest-schema.d.ts.map +1 -1
- package/dist/src/manifest.d.ts +6 -0
- package/dist/src/manifest.d.ts.map +1 -1
- package/dist/src/manifest.js +21 -6
- package/dist/src/manifest.js.map +1 -1
- package/dist/src/proxy.d.ts +19 -4
- package/dist/src/proxy.d.ts.map +1 -1
- package/dist/src/proxy.js +111 -33
- package/dist/src/proxy.js.map +1 -1
- package/dist/src/safe-filename.d.ts +3 -0
- package/dist/src/safe-filename.d.ts.map +1 -0
- package/dist/src/safe-filename.js +8 -0
- package/dist/src/safe-filename.js.map +1 -0
- package/dist/src/sanitizer.d.ts.map +1 -1
- package/dist/src/sanitizer.js +36 -10
- package/dist/src/sanitizer.js.map +1 -1
- package/dist/src/technique-checker.d.ts +14 -0
- package/dist/src/technique-checker.d.ts.map +1 -1
- package/dist/src/technique-checker.js +123 -2
- package/dist/src/technique-checker.js.map +1 -1
- package/dist/src/transports/http.d.ts +6 -2
- package/dist/src/transports/http.d.ts.map +1 -1
- package/dist/src/transports/http.js +101 -13
- package/dist/src/transports/http.js.map +1 -1
- package/dist/src/transports/sse.d.ts +1 -1
- package/dist/src/transports/sse.d.ts.map +1 -1
- package/dist/src/transports/sse.js +28 -18
- package/dist/src/transports/sse.js.map +1 -1
- package/dist/src/transports/stdio.d.ts +2 -2
- package/dist/src/transports/stdio.d.ts.map +1 -1
- package/dist/src/transports/stdio.js +77 -48
- package/dist/src/transports/stdio.js.map +1 -1
- package/dist/src/tui/audit-tailer.d.ts.map +1 -1
- package/dist/src/tui/audit-tailer.js +2 -1
- package/dist/src/tui/audit-tailer.js.map +1 -1
- package/dist/src/tui/useAuditWatcher.d.ts.map +1 -1
- package/dist/src/tui/useAuditWatcher.js +2 -1
- package/dist/src/tui/useAuditWatcher.js.map +1 -1
- package/dist/src/types.d.ts +1 -1
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/validator.d.ts +19 -28
- package/dist/src/validator.d.ts.map +1 -1
- package/dist/src/validator.js +315 -113
- package/dist/src/validator.js.map +1 -1
- package/examples/claude-desktop-burp-config.json +5 -7
- package/examples/claude-desktop-config.json +3 -4
- package/examples/scope-manifest.json +11 -11
- package/package.json +33 -13
- package/scripts/postinstall.cjs +14 -0
- package/examples/scope-test-integsec.json +0 -32
package/dist/src/sanitizer.js
CHANGED
|
@@ -12,10 +12,37 @@ const REDACTED = "[REDACTED]";
|
|
|
12
12
|
* Regex that matches a key name that is *exactly* one of the sensitive words
|
|
13
13
|
* (case-insensitive, full-string match).
|
|
14
14
|
*/
|
|
15
|
-
const SENSITIVE_KEY_RE = /^(password|passwd|token|secret|key|credential|auth|apikey|
|
|
15
|
+
const SENSITIVE_KEY_RE = /^(password|passwd|token|secret|key|credential|auth|apikey|authorization)$/i;
|
|
16
|
+
const COMMAND_KEY_RE = /^(command|cmd|command_line|commandline|cmdline|shell_command|args|extra_args|additional_args)$/i;
|
|
17
|
+
const UNSTRUCTURED_VALUE_KEY_RE = /^(body|payload|data|request|raw_request|headers|cookie|cookies)$/i;
|
|
16
18
|
/** Returns true if the given key should have its value redacted. */
|
|
17
19
|
function isSensitive(key) {
|
|
18
|
-
|
|
20
|
+
const words = key
|
|
21
|
+
.replace(/([a-z])([A-Z])/g, "$1_$2")
|
|
22
|
+
.split(/[^a-z0-9]+/i)
|
|
23
|
+
.filter(Boolean);
|
|
24
|
+
return words.some((word) => SENSITIVE_KEY_RE.test(word)) ||
|
|
25
|
+
/password|passwd|token|secret|credential|apikey|authorization|auth/i.test(key);
|
|
26
|
+
}
|
|
27
|
+
/** Remove URL userinfo and sensitive query values without altering the call. */
|
|
28
|
+
function sanitizeString(value) {
|
|
29
|
+
if (!/^https?:\/\//i.test(value))
|
|
30
|
+
return value;
|
|
31
|
+
try {
|
|
32
|
+
const url = new URL(value);
|
|
33
|
+
if (url.username)
|
|
34
|
+
url.username = "REDACTED";
|
|
35
|
+
if (url.password)
|
|
36
|
+
url.password = "REDACTED";
|
|
37
|
+
for (const key of url.searchParams.keys()) {
|
|
38
|
+
if (isSensitive(key))
|
|
39
|
+
url.searchParams.set(key, REDACTED);
|
|
40
|
+
}
|
|
41
|
+
return url.toString();
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return REDACTED;
|
|
45
|
+
}
|
|
19
46
|
}
|
|
20
47
|
/**
|
|
21
48
|
* Recursively sanitize an unknown value that may be a plain object, an array,
|
|
@@ -32,19 +59,18 @@ function sanitizeValue(value, key) {
|
|
|
32
59
|
if (key !== undefined && isSensitive(key)) {
|
|
33
60
|
return REDACTED;
|
|
34
61
|
}
|
|
62
|
+
if (key !== undefined && (COMMAND_KEY_RE.test(key) || UNSTRUCTURED_VALUE_KEY_RE.test(key))) {
|
|
63
|
+
// A free-form shell command can embed headers, passwords and tokens in
|
|
64
|
+
// arbitrary syntax. There is no reliable way to redact only those pieces.
|
|
65
|
+
return REDACTED;
|
|
66
|
+
}
|
|
35
67
|
if (Array.isArray(value)) {
|
|
36
|
-
return value.map((item) =>
|
|
37
|
-
// Array items do not inherit a key name, so we only recurse into objects.
|
|
38
|
-
if (item !== null && typeof item === "object" && !Array.isArray(item)) {
|
|
39
|
-
return sanitizeObject(item);
|
|
40
|
-
}
|
|
41
|
-
return item;
|
|
42
|
-
});
|
|
68
|
+
return value.map((item) => sanitizeValue(item));
|
|
43
69
|
}
|
|
44
70
|
if (value !== null && typeof value === "object") {
|
|
45
71
|
return sanitizeObject(value);
|
|
46
72
|
}
|
|
47
|
-
return value;
|
|
73
|
+
return typeof value === "string" ? sanitizeString(value) : value;
|
|
48
74
|
}
|
|
49
75
|
/** Shallow-copy an object and recursively sanitize every property. */
|
|
50
76
|
function sanitizeObject(obj) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sanitizer.js","sourceRoot":"","sources":["../../src/sanitizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,QAAQ,GAAG,YAAY,CAAC;AAE9B;;;GAGG;AACH,MAAM,gBAAgB,GACpB,
|
|
1
|
+
{"version":3,"file":"sanitizer.js","sourceRoot":"","sources":["../../src/sanitizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,6 +20,12 @@ export interface TechniqueMapping {
|
|
|
20
20
|
patterns: string[];
|
|
21
21
|
}
|
|
22
22
|
export type TechniqueMappings = Record<string, TechniqueMapping>;
|
|
23
|
+
/**
|
|
24
|
+
* Load custom technique mappings from a JSON file (TECHNIQUE_MAP_PATH).
|
|
25
|
+
* Throws with a descriptive message if the file is unreadable or malformed,
|
|
26
|
+
* so a typo in the map never silently disables a technique block.
|
|
27
|
+
*/
|
|
28
|
+
export declare function loadTechniqueMappings(filePath: string): TechniqueMappings;
|
|
23
29
|
export declare class TechniqueChecker {
|
|
24
30
|
private readonly mappings;
|
|
25
31
|
/**
|
|
@@ -40,6 +46,14 @@ export declare class TechniqueChecker {
|
|
|
40
46
|
* categorised).
|
|
41
47
|
*/
|
|
42
48
|
isBlocked(toolName: string, excludedTechniques: string[]): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Patterns containing a separator (e.g. "nmap_", "shodan-", "msf_") match
|
|
51
|
+
* as plain substrings. Purely alphanumeric patterns (e.g. "dos", "flood")
|
|
52
|
+
* match whole words of the tool name, or the end of a word, so "dos"
|
|
53
|
+
* matches "dos_attack" and "ddos" but not "get_dossier"; "flood" matches
|
|
54
|
+
* "udp_flood" and "icmpflood".
|
|
55
|
+
*/
|
|
56
|
+
private static matchesPattern;
|
|
43
57
|
/**
|
|
44
58
|
* Merges `custom` mappings into `base`, extending per-category arrays rather
|
|
45
59
|
* than replacing them. Returns a deep-copied result so the originals are
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"technique-checker.d.ts","sourceRoot":"","sources":["../../src/technique-checker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;
|
|
1
|
+
{"version":3,"file":"technique-checker.d.ts","sourceRoot":"","sources":["../../src/technique-checker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,MAAM,WAAW,gBAAgB;IAC/B,6DAA6D;IAC7D,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,uFAAuF;IACvF,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;AA0GjE;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,CAezE;AAMD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAE7C;;;;;OAKG;gBACS,cAAc,CAAC,EAAE,iBAAiB;IAQ9C;;;OAGG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAoB5C;;;;OAIG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,GAAG,OAAO;IAalE;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAW7B;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;CAsB7B"}
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
* (they do not replace them). Both exact lists and patterns are extended
|
|
14
14
|
* per-category.
|
|
15
15
|
*/
|
|
16
|
+
import * as fs from "node:fs";
|
|
17
|
+
import { z } from "zod";
|
|
16
18
|
// ---------------------------------------------------------------------------
|
|
17
19
|
// Default technique map
|
|
18
20
|
// ---------------------------------------------------------------------------
|
|
@@ -29,7 +31,108 @@ const DEFAULT_MAPPINGS = {
|
|
|
29
31
|
exact: ["gophish", "setoolkit", "evilginx", "modlishka"],
|
|
30
32
|
patterns: [],
|
|
31
33
|
},
|
|
34
|
+
recon: {
|
|
35
|
+
exact: [
|
|
36
|
+
"amass", "alterx", "assetfinder", "cero", "crtsh",
|
|
37
|
+
"dnsx", "httpx", "katana", "gowitness", "masscan",
|
|
38
|
+
"shuffledns", "subfinder", "uncover", "waybackurls", "notify",
|
|
39
|
+
"nmap", "nmap_scan",
|
|
40
|
+
"trivy", "checkov", "kube-hunter", "kubeaudit", "kube-bench",
|
|
41
|
+
"shodan", "virustotal", "bloodhound",
|
|
42
|
+
// Hex Strike AI MCP
|
|
43
|
+
"rustscan_fast_scan", "subfinder_scan", "katana_crawl",
|
|
44
|
+
// Kali Linux MCP
|
|
45
|
+
"port_scan", "dns_enum", "network_discovery", "subdomain_enum",
|
|
46
|
+
"enum_shares", "ssl_analysis",
|
|
47
|
+
// Shodan MCP (BurtTheCoder)
|
|
48
|
+
"ip_lookup", "shodan_search", "dns_lookup", "reverse_dns_lookup",
|
|
49
|
+
// WireMCP
|
|
50
|
+
"check_ip_threats",
|
|
51
|
+
// VirusTotal MCP
|
|
52
|
+
"get_url_report", "get_ip_report", "get_domain_report", "submit_url",
|
|
53
|
+
"get_url_relationship", "get_ip_relationship", "get_domain_relationship",
|
|
54
|
+
// Awesome Kali MCP Servers (nmap variants)
|
|
55
|
+
"basic_scan", "intense_scan", "stealth_scan", "quick_scan",
|
|
56
|
+
// Semgrep MCP
|
|
57
|
+
"semgrep", "security_check", "semgrep_scan", "semgrep_scan_with_custom_rule", "semgrep_findings",
|
|
58
|
+
// Gitleaks MCP
|
|
59
|
+
"gitleaks", "gitleaks_scan",
|
|
60
|
+
// Ghidra MCP
|
|
61
|
+
"ghidra", "decompile_function",
|
|
62
|
+
// MobSF MCP
|
|
63
|
+
"mobsf", "scanFile",
|
|
64
|
+
// SSLScan MCP
|
|
65
|
+
"sslscan",
|
|
66
|
+
// HTTP headers Custom MCP
|
|
67
|
+
"http_headers", "check_http_headers",
|
|
68
|
+
],
|
|
69
|
+
patterns: [
|
|
70
|
+
// Covers all nmap_* variants from Nmap MCP Server and Hex Strike
|
|
71
|
+
"nmap_",
|
|
72
|
+
// Covers all shodan-* hyphenated tools from Vorota-ai Shodan MCP
|
|
73
|
+
"shodan-",
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
web_app: {
|
|
77
|
+
exact: [
|
|
78
|
+
"nuclei", "sqlmap", "ffuf", "dirb", "gobuster", "nikto",
|
|
79
|
+
"arjun", "smuggler", "wpscan", "nessus", "dalfox", "zap",
|
|
80
|
+
"burpsuite", "burp_scan", "burp_active_scan",
|
|
81
|
+
// Hex Strike AI MCP variants
|
|
82
|
+
"gobuster_scan", "nuclei_scan", "sqlmap_scan", "ffuf_scan", "feroxbuster_scan",
|
|
83
|
+
// Kali Linux MCP
|
|
84
|
+
"vulnerability_scan", "web_enumeration",
|
|
85
|
+
// Burp Suite MCP (PortSwigger official)
|
|
86
|
+
"start_scan",
|
|
87
|
+
// Acunetix MCP
|
|
88
|
+
"acunetix",
|
|
89
|
+
// Next.js CVE scanner / Unified all-in-one
|
|
90
|
+
"nextjs_scan", "nextjs_scanner", "unified_scan",
|
|
91
|
+
],
|
|
92
|
+
patterns: [],
|
|
93
|
+
},
|
|
94
|
+
exploitation: {
|
|
95
|
+
exact: ["metasploit", "hydra", "hashcat",
|
|
96
|
+
// Hex Strike AI MCP
|
|
97
|
+
"hydra_attack", "hashcat_crack", "metasploit_run",
|
|
98
|
+
// Kali Linux MCP
|
|
99
|
+
"payload_generate", "reverse_shell",
|
|
100
|
+
// CrackMapExec
|
|
101
|
+
"crackmapexec",
|
|
102
|
+
// Commix — command injection exploitation
|
|
103
|
+
"commix",
|
|
104
|
+
],
|
|
105
|
+
patterns: ["msf_"],
|
|
106
|
+
},
|
|
107
|
+
cloud_audit: {
|
|
108
|
+
exact: ["prowler", "scoutsuite"],
|
|
109
|
+
patterns: [],
|
|
110
|
+
},
|
|
32
111
|
};
|
|
112
|
+
const TechniqueMappingsSchema = z.record(z.string().min(1), z.object({
|
|
113
|
+
exact: z.array(z.string()).default([]),
|
|
114
|
+
patterns: z.array(z.string()).default([]),
|
|
115
|
+
}));
|
|
116
|
+
/**
|
|
117
|
+
* Load custom technique mappings from a JSON file (TECHNIQUE_MAP_PATH).
|
|
118
|
+
* Throws with a descriptive message if the file is unreadable or malformed,
|
|
119
|
+
* so a typo in the map never silently disables a technique block.
|
|
120
|
+
*/
|
|
121
|
+
export function loadTechniqueMappings(filePath) {
|
|
122
|
+
let raw;
|
|
123
|
+
try {
|
|
124
|
+
raw = JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
throw new Error(`Failed to read technique map at "${filePath}": ${err instanceof Error ? err.message : String(err)}`);
|
|
128
|
+
}
|
|
129
|
+
const parsed = TechniqueMappingsSchema.safeParse(raw);
|
|
130
|
+
if (!parsed.success) {
|
|
131
|
+
const issues = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
|
|
132
|
+
throw new Error(`Technique map at "${filePath}" is invalid: ${issues}`);
|
|
133
|
+
}
|
|
134
|
+
return parsed.data;
|
|
135
|
+
}
|
|
33
136
|
// ---------------------------------------------------------------------------
|
|
34
137
|
// TechniqueChecker class
|
|
35
138
|
// ---------------------------------------------------------------------------
|
|
@@ -60,8 +163,8 @@ export class TechniqueChecker {
|
|
|
60
163
|
if (mapping.exact.some((name) => name.toLowerCase() === lower)) {
|
|
61
164
|
return category;
|
|
62
165
|
}
|
|
63
|
-
// 2.
|
|
64
|
-
if (mapping.patterns.some((pattern) =>
|
|
166
|
+
// 2. Pattern match
|
|
167
|
+
if (mapping.patterns.some((pattern) => TechniqueChecker.matchesPattern(lower, pattern))) {
|
|
65
168
|
return category;
|
|
66
169
|
}
|
|
67
170
|
}
|
|
@@ -83,6 +186,24 @@ export class TechniqueChecker {
|
|
|
83
186
|
// -------------------------------------------------------------------------
|
|
84
187
|
// Private helpers
|
|
85
188
|
// -------------------------------------------------------------------------
|
|
189
|
+
/**
|
|
190
|
+
* Patterns containing a separator (e.g. "nmap_", "shodan-", "msf_") match
|
|
191
|
+
* as plain substrings. Purely alphanumeric patterns (e.g. "dos", "flood")
|
|
192
|
+
* match whole words of the tool name, or the end of a word, so "dos"
|
|
193
|
+
* matches "dos_attack" and "ddos" but not "get_dossier"; "flood" matches
|
|
194
|
+
* "udp_flood" and "icmpflood".
|
|
195
|
+
*/
|
|
196
|
+
static matchesPattern(lowerToolName, pattern) {
|
|
197
|
+
const p = pattern.toLowerCase();
|
|
198
|
+
if (p === "")
|
|
199
|
+
return false;
|
|
200
|
+
if (/[^a-z0-9]/.test(p)) {
|
|
201
|
+
return lowerToolName.includes(p);
|
|
202
|
+
}
|
|
203
|
+
return lowerToolName
|
|
204
|
+
.split(/[^a-z0-9]+/)
|
|
205
|
+
.some((word) => word === p || word.endsWith(p));
|
|
206
|
+
}
|
|
86
207
|
/**
|
|
87
208
|
* Merges `custom` mappings into `base`, extending per-category arrays rather
|
|
88
209
|
* than replacing them. Returns a deep-copied result so the originals are
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"technique-checker.js","sourceRoot":"","sources":["../../src/technique-checker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;
|
|
1
|
+
{"version":3,"file":"technique-checker.js","sourceRoot":"","sources":["../../src/technique-checker.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
1
|
+
import { type IncomingMessage } from "http";
|
|
2
|
+
import { ScopeEnforcementProxy } from "../proxy.js";
|
|
3
|
+
/** Accept only origin-form request targets, never an absolute or // URL. */
|
|
4
|
+
export declare function resolveUpstreamUrl(requestTarget: string, upstreamUrl: string): URL;
|
|
5
|
+
export declare function runHttpProxy(proxy: ScopeEnforcementProxy, upstreamUrl: string, port: number, host?: string, authToken?: string): Promise<void>;
|
|
6
|
+
export declare function hasValidProxyToken(req: IncomingMessage, expected?: string): boolean;
|
|
3
7
|
//# sourceMappingURL=http.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/transports/http.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/transports/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,eAAe,EAAuB,MAAM,MAAM,CAAC;AAG/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAIpD,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,GAAG,CAUlF;AAED,wBAAsB,YAAY,CAChC,KAAK,EAAE,qBAAqB,EAC5B,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,IAAI,SAAc,EAClB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CA+Ef;AAMD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,eAAe,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAOnF"}
|
|
@@ -1,26 +1,82 @@
|
|
|
1
1
|
import { createServer } from "http";
|
|
2
|
-
|
|
2
|
+
import { Readable } from "node:stream";
|
|
3
|
+
import { timingSafeEqual } from "node:crypto";
|
|
4
|
+
import { ScopeEnforcementProxy } from "../proxy.js";
|
|
5
|
+
const MAX_REQUEST_BYTES = 1024 * 1024;
|
|
6
|
+
/** Accept only origin-form request targets, never an absolute or // URL. */
|
|
7
|
+
export function resolveUpstreamUrl(requestTarget, upstreamUrl) {
|
|
8
|
+
if (!requestTarget.startsWith("/") || requestTarget.startsWith("//")) {
|
|
9
|
+
throw new Error("Only origin-form request paths are accepted");
|
|
10
|
+
}
|
|
11
|
+
const upstream = new URL(upstreamUrl);
|
|
12
|
+
const destination = new URL(requestTarget, upstream);
|
|
13
|
+
if (destination.origin !== upstream.origin) {
|
|
14
|
+
throw new Error("Request path cannot change the upstream origin");
|
|
15
|
+
}
|
|
16
|
+
return destination;
|
|
17
|
+
}
|
|
18
|
+
export async function runHttpProxy(proxy, upstreamUrl, port, host = "127.0.0.1", authToken) {
|
|
19
|
+
if (!isLoopback(host) && !authToken) {
|
|
20
|
+
throw new Error("PROXY_AUTH_TOKEN is required when PROXY_HOST is not loopback");
|
|
21
|
+
}
|
|
3
22
|
const auditLogger = proxy.getAuditLogger();
|
|
4
23
|
auditLogger.start();
|
|
5
24
|
const server = createServer(async (req, res) => {
|
|
6
|
-
|
|
25
|
+
if (req.url === "/healthz" && req.method === "GET") {
|
|
26
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
27
|
+
res.end('{"status":"ok"}');
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (!hasValidProxyToken(req, authToken)) {
|
|
31
|
+
res.writeHead(401, { "Content-Type": "application/json" });
|
|
32
|
+
res.end('{"error":"Unauthorized"}');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
let body;
|
|
36
|
+
try {
|
|
37
|
+
resolveUpstreamUrl(req.url ?? "/", upstreamUrl);
|
|
38
|
+
body = await readBody(req);
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
const oversized = err instanceof Error && err.message === "Request body too large";
|
|
42
|
+
res.writeHead(oversized ? 413 : 400, { "Content-Type": "application/json" });
|
|
43
|
+
res.end(JSON.stringify({ error: oversized ? "Request body too large" : "Invalid request target" }));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
// Bodiless requests (GET for the SSE stream, DELETE to end a session)
|
|
47
|
+
// carry no tool call and pass straight through.
|
|
48
|
+
if (body.trim() === "") {
|
|
49
|
+
return forwardRaw(upstreamUrl, req, body, res);
|
|
50
|
+
}
|
|
7
51
|
let message;
|
|
8
52
|
try {
|
|
9
53
|
message = JSON.parse(body);
|
|
10
54
|
}
|
|
11
55
|
catch {
|
|
12
|
-
|
|
56
|
+
// Never forward a body we could not inspect — fail closed.
|
|
57
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
58
|
+
res.end(JSON.stringify(ScopeEnforcementProxy.parseErrorResponse()));
|
|
59
|
+
return;
|
|
13
60
|
}
|
|
14
|
-
|
|
15
|
-
|
|
61
|
+
let forward;
|
|
62
|
+
let response;
|
|
63
|
+
try {
|
|
64
|
+
({ forward, response } = await proxy.handleMessage(message));
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
68
|
+
res.end(JSON.stringify({ error: `Scope proxy error: ${err.message}` }));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (!forward) {
|
|
16
72
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
17
|
-
res.end(JSON.stringify(response));
|
|
73
|
+
res.end(JSON.stringify(response ?? null));
|
|
18
74
|
return;
|
|
19
75
|
}
|
|
20
|
-
return forwardRaw(upstreamUrl, req,
|
|
76
|
+
return forwardRaw(upstreamUrl, req, JSON.stringify(message), res);
|
|
21
77
|
});
|
|
22
|
-
server.listen(port, () => {
|
|
23
|
-
console.error(`[integsec-agentic-pentest-proxy] HTTP proxy listening on
|
|
78
|
+
server.listen(port, host, () => {
|
|
79
|
+
console.error(`[integsec-agentic-pentest-proxy] HTTP proxy listening on ${host}:${port}, forwarding to ${upstreamUrl}`);
|
|
24
80
|
});
|
|
25
81
|
process.on("SIGINT", async () => {
|
|
26
82
|
await auditLogger.stop();
|
|
@@ -33,31 +89,63 @@ export async function runHttpProxy(proxy, upstreamUrl, port) {
|
|
|
33
89
|
process.exit(0);
|
|
34
90
|
});
|
|
35
91
|
}
|
|
92
|
+
function isLoopback(host) {
|
|
93
|
+
return host === "127.0.0.1" || host === "localhost" || host === "::1";
|
|
94
|
+
}
|
|
95
|
+
export function hasValidProxyToken(req, expected) {
|
|
96
|
+
if (!expected)
|
|
97
|
+
return true;
|
|
98
|
+
const supplied = req.headers["x-proxy-token"];
|
|
99
|
+
if (typeof supplied !== "string")
|
|
100
|
+
return false;
|
|
101
|
+
const left = Buffer.from(supplied);
|
|
102
|
+
const right = Buffer.from(expected);
|
|
103
|
+
return left.length === right.length && timingSafeEqual(left, right);
|
|
104
|
+
}
|
|
36
105
|
function readBody(req) {
|
|
37
106
|
return new Promise((resolve, reject) => {
|
|
38
107
|
const chunks = [];
|
|
39
|
-
|
|
108
|
+
let size = 0;
|
|
109
|
+
req.on("data", (chunk) => {
|
|
110
|
+
size += chunk.length;
|
|
111
|
+
if (size > MAX_REQUEST_BYTES) {
|
|
112
|
+
req.pause();
|
|
113
|
+
reject(new Error("Request body too large"));
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
chunks.push(chunk);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
40
119
|
req.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
|
|
41
120
|
req.on("error", reject);
|
|
42
121
|
});
|
|
43
122
|
}
|
|
44
123
|
async function forwardRaw(upstreamUrl, originalReq, body, clientRes) {
|
|
45
124
|
try {
|
|
46
|
-
const url =
|
|
125
|
+
const url = resolveUpstreamUrl(originalReq.url ?? "/", upstreamUrl);
|
|
47
126
|
const headers = {};
|
|
48
127
|
for (const [key, value] of Object.entries(originalReq.headers)) {
|
|
49
128
|
if (typeof value === "string")
|
|
50
129
|
headers[key] = value;
|
|
51
130
|
}
|
|
52
131
|
delete headers.host;
|
|
132
|
+
delete headers["x-proxy-token"];
|
|
133
|
+
delete headers.connection;
|
|
134
|
+
delete headers["content-length"];
|
|
135
|
+
delete headers["transfer-encoding"];
|
|
136
|
+
headers["accept-encoding"] = "identity"; // disable compression — Node fetch re-adds br/gzip otherwise
|
|
53
137
|
const resp = await fetch(url.toString(), {
|
|
54
138
|
method: originalReq.method ?? "POST",
|
|
55
139
|
headers,
|
|
56
140
|
body: originalReq.method !== "GET" ? body : undefined,
|
|
57
141
|
});
|
|
58
142
|
clientRes.writeHead(resp.status, Object.fromEntries(resp.headers.entries()));
|
|
59
|
-
|
|
60
|
-
|
|
143
|
+
if (resp.body) {
|
|
144
|
+
Readable.fromWeb(resp.body).pipe(clientRes);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
clientRes.end();
|
|
148
|
+
}
|
|
61
149
|
}
|
|
62
150
|
catch (err) {
|
|
63
151
|
clientRes.writeHead(502, { "Content-Type": "application/json" });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/transports/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA6C,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/transports/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../../src/transports/sse.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../../src/transports/sse.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEpD;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,qBAAqB,EAC5B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CA6Jf"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createInterface } from "readline";
|
|
2
|
+
import { ScopeEnforcementProxy } from "../proxy.js";
|
|
2
3
|
/**
|
|
3
4
|
* SSE transport — connects to an upstream MCP server via SSE protocol.
|
|
4
5
|
*
|
|
@@ -106,19 +107,38 @@ export async function runSseProxy(proxy, upstreamUrl) {
|
|
|
106
107
|
console.error(`${TAG} POST endpoint: ${postUrl}`);
|
|
107
108
|
const agentInput = createInterface({ input: process.stdin, crlfDelay: Infinity });
|
|
108
109
|
agentInput.on("line", async (line) => {
|
|
110
|
+
if (line.trim() === "")
|
|
111
|
+
return;
|
|
112
|
+
let message;
|
|
109
113
|
try {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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)
|
|
114
133
|
process.stdout.write(JSON.stringify(response) + "\n");
|
|
115
|
-
|
|
116
|
-
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
117
137
|
// Forward to upstream via HTTP POST
|
|
118
138
|
const resp = await fetch(postUrl, {
|
|
119
139
|
method: "POST",
|
|
120
140
|
headers: { "Content-Type": "application/json" },
|
|
121
|
-
body:
|
|
141
|
+
body: JSON.stringify(message),
|
|
122
142
|
});
|
|
123
143
|
if (!resp.ok) {
|
|
124
144
|
console.error(`${TAG} Upstream POST failed: ${resp.status} ${resp.statusText}`);
|
|
@@ -126,17 +146,7 @@ export async function runSseProxy(proxy, upstreamUrl) {
|
|
|
126
146
|
// Response comes back via SSE stream, not the POST response
|
|
127
147
|
}
|
|
128
148
|
catch (err) {
|
|
129
|
-
|
|
130
|
-
try {
|
|
131
|
-
await fetch(postUrl, {
|
|
132
|
-
method: "POST",
|
|
133
|
-
headers: { "Content-Type": "application/json" },
|
|
134
|
-
body: line,
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
catch {
|
|
138
|
-
console.error(`${TAG} Failed to forward message: ${err.message}`);
|
|
139
|
-
}
|
|
149
|
+
console.error(`${TAG} Failed to forward message: ${err.message}`);
|
|
140
150
|
}
|
|
141
151
|
});
|
|
142
152
|
// Cleanup
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse.js","sourceRoot":"","sources":["../../../src/transports/sse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"sse.js","sourceRoot":"","sources":["../../../src/transports/sse.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import
|
|
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,
|
|
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"}
|