SSRF OAST query review V1
The non-default ssrf-oast-review feature adds one explicitly configured
native action to the existing WebAssessmentRuntime. It is a narrow
correlation review, not a general SSRF fuzzer. The operator supplies a strict
--ssrf-oast-review enable flag and a strict
security.ssrf-oast-review-policy/v1 file through --ssrf-oast-policy,
acknowledges the outbound callback
test, and supplies the self-hosted native provider administrator token through
one bounded environment, regular-file, or stdin source. No credential value is
accepted on the command line. The shared
credential-input guarantees and limits apply to that
source and the policy-file loader.
The target and provider authorities remain separate. The target must be the
assessment's exact origin. The provider must be a different, exact HTTPS DNS
origin selected by the operator; there is no Termivar-hosted or other public
default. Provider management traffic uses the narrowing authority, shared
parent RuntimeBudget, cancellation token, and deadline introduced by the
native OAST provider adapter. The provider remains an auxiliary raw-free
callback mailbox and never becomes a scanner.
Candidate boundary
V1 selects at most one query parameter from one of two structural sources:
- an exact-origin
GETtarget containing exactly one occurrence whose current value is an absolute HTTP or HTTPS URL; or - one optional
url/uriquery parameter on an anonymous, bodyless, zero-required-input exact-originGETfrom a complete replay-stable OpenAPI catalog already committed by the same assessment.
OpenAPI is never fetched or enabled on behalf of this review. A parameter name, example, default, description, or model guess is not eligibility. Duplicate names, malformed encoding, required inputs, authentication, request bodies, templated or cross-origin servers, and path/header/body/cookie candidates fail closed. Unrelated query pairs keep their order and exact encoded values.
Bounded execution
One review is bounded to at most one logical active verification and at most three target request legs. A completed positive path uses all three legs:
Control, using a case-bound HTTPS URL under the reserved.invalidTLD;Candidate, using a freshly allocated provider callback;Replay, using a second independently allocated callback.
All three target requests are anonymous, bodyless GETs to the same exact
origin and path. Redirects, retries, cookies, authorization, forwarding
headers, alternate schemes, internal/private/link-local/cloud destinations,
redirectors, DNS rebinding, and timing inference are absent.
The provider lifecycle is fixed: register one session, allocate the two
callbacks, require one clean preflight poll, dispatch and poll Candidate,
dispatch and poll Replay, then explicitly clean up. The policy permits one to
four polls per phase, but the scheduler also enforces the stricter whole-review
ceiling: at most seven post-dispatch polls. Together with register, two
allocations, preflight, and cleanup, provider HTTP requests can never exceed
twelve. There is no background or post-finalization polling and no network work
in Drop.
Candidate polling ends when the candidate event is present. Replay polling ends only when both the candidate and replay events are present; an empty first replay poll therefore does not consume the phase as a success. Existing terminal states, cancellation, deadline, and shared poll/request ceilings can still stop either phase. This completion rule changes the polling window, not the positive claim contract below.
Evidence and claim
A positive observation requires both independently allocated callback IDs to produce distinct exact event IDs after their corresponding target dispatches. They must bind the same assessment, action, case, resource, parameter, and authority epoch; preflight must be clean; cleanup and all parent accounting must reconcile. Candidate-only, Replay-only, duplicate-only, stale, wrong-case, wrong-session, preflight, expired, malformed, rate-limited, unauthenticated, cancelled, budget-exhausted, or cleanup-incomplete states produce no item. Target timing and target status are never callback evidence.
The strongest V1 item is:
- capability:
ssrf.oast-repeated-outbound-interaction@1; - title:
Repeated out-of-band interaction observed; - disposition:
NeedsReview; - authority:
KnowledgeOnly; - severity: none.
Two callbacks show a repeated, correlated outbound interaction only. They do not confirm SSRF, identify the server-side component, prove internal-service or cloud-metadata reachability, demonstrate data exposure, or establish business impact.
The private feature-gated audit contains only bounded counts, typed states, opaque fingerprints, and boolean reconciliation facts. It never retains or emits the target URL, raw query, provider origin, callback URL/path, provider or session token, clear session/callback/event IDs, IP, port, header, cookie, body, timestamp, or reverse-proxy metadata. Projection still ends in the one composed assessment report.
This feature remains outside release-bundle. The operator must self-host the
provider behind an HTTPS reverse proxy. V1 observes HTTP callbacks only; it has
no DNS-only detection, XXE path, automatic chaining, public deployment, or
public-network CI.