Problem
The proxy vuln-testers (proxy-tester-injection and siblings) confirm and weaponize findings by constructing curl command strings in bash. This is fragile in ways that hurt result quality:
- Two-layer escaping. A payload passes through the shell and the target parser. The LLM must escape both layers perfectly on every call. Quotes, backticks,
$, newlines routinely break the request — or worse, get interpreted by the local shell (e.g. a `...` payload executes locally and never reaches the target).
- State handling. Cookies / CSRF tokens / auth refresh must be re-pasted per request; a dropped header silently invalidates the test.
- Concurrency. Race-condition / single-packet tests are hard to time with
curl one-liners.
Net effect: false positives (broken request read as "safe") and missed findings (payload never landed intact). The inject_probe tool already demonstrates the correct pattern — it sends via a real HTTP engine (fetch), never a shell — but only for its fixed enumeration batteries. The agent's confirm/weaponize step still falls back to curl.
Proposed direction
Introduce a first-class, agent-callable HTTP replay engine where the payload travels as data, not as part of a command line. Two backends:
undici — normal requests: HTTP/1.1 + HTTP/2, streaming, connection pool, proxy, correct encoding, cookie handling. Covers the large majority of targets.
- raw TCP/TLS socket (
net/tls) — byte-exact replay for request smuggling / desync and intentionally-malformed requests (which undici normalizes and thus cannot send).
Exposed as two tools, mirroring Caido's RequestSpec / RequestSpecRaw:
http_replay(request_id, mutations[]) — take a captured request, mutate named fields, send.
http_replay_raw(raw_bytes) — send exact bytes verbatim.
Reliability requirements (must-haves)
- Timeout ≠ error semantics: always return elapsed ms; timeout threshold > max intended
SLEEP so time-based injection isn't masked as a failure.
- Idempotency guard: never auto-retry state-changing methods (POST/PUT/PATCH/DELETE) unless explicitly flagged safe.
- Structured error taxonomy:
dns | conn_refused | tls | timeout | reset | http_error | rate_limited — returned as data, not swallowed.
- Circuit breaker per host; concurrency limiter + global request budget; scope check before every send (reuse existing matcher).
- Hard per-request
AbortController; response-body size cap.
Scope / non-goals
- Additive & feature-flagged. No existing path (curl,
inject_probe, testers) changes until the engine is wired in behind a flag; curl stays as fallback during transition.
- HTTP/3 (QUIC) and JA3 fingerprint mimicry are out of core (they'd require a native/binary dependency, against the project's clean-
npm-install goal). Handled later via an optional external-tool bridge (e.g. detect an installed h3-capable curl / curl-impersonate), with a clean "install X for this target" message when absent — mirroring how hackbrowser optionally uses Chromium.
Acceptance criteria
Problem
The proxy vuln-testers (
proxy-tester-injectionand siblings) confirm and weaponize findings by constructingcurlcommand strings inbash. This is fragile in ways that hurt result quality:$, newlines routinely break the request — or worse, get interpreted by the local shell (e.g. a`...`payload executes locally and never reaches the target).curlone-liners.Net effect: false positives (broken request read as "safe") and missed findings (payload never landed intact). The
inject_probetool already demonstrates the correct pattern — it sends via a real HTTP engine (fetch), never a shell — but only for its fixed enumeration batteries. The agent's confirm/weaponize step still falls back tocurl.Proposed direction
Introduce a first-class, agent-callable HTTP replay engine where the payload travels as data, not as part of a command line. Two backends:
undici— normal requests: HTTP/1.1 + HTTP/2, streaming, connection pool, proxy, correct encoding, cookie handling. Covers the large majority of targets.net/tls) — byte-exact replay for request smuggling / desync and intentionally-malformed requests (whichundicinormalizes and thus cannot send).Exposed as two tools, mirroring Caido's
RequestSpec/RequestSpecRaw:http_replay(request_id, mutations[])— take a captured request, mutate named fields, send.http_replay_raw(raw_bytes)— send exact bytes verbatim.Reliability requirements (must-haves)
SLEEPso time-based injection isn't masked as a failure.dns | conn_refused | tls | timeout | reset | http_error | rate_limited— returned as data, not swallowed.AbortController; response-body size cap.Scope / non-goals
inject_probe, testers) changes until the engine is wired in behind a flag;curlstays as fallback during transition.npm-installgoal). Handled later via an optional external-tool bridge (e.g. detect an installed h3-capablecurl/curl-impersonate), with a clean "install X for this target" message when absent — mirroring how hackbrowser optionally uses Chromium.Acceptance criteria
$/newlines land intact).proxy-tester-injection) migrated behind a flag as proof;curlfallback intact.