Skip to main content
Every scanner module declares a scan scope that tells the executor when and how often to invoke it. The scan scope determines the granularity at which the module operates: per parameter, per request, or per host.
Scopes are a bitmask. A module can declare multiple scopes (e.g., ScanScopeRequest | ScanScopeInsertionPoint).

Overview Diagram


The Three Scopes

ScanScopeInsertionPoint

Invoked once for each parameter (insertion point) in the request. The executor parses the raw HTTP request, extracts every injectable location, and hands them to the module one at a time. The module receives a single InsertionPoint with a BuildRequest(payload) method to inject its payload at that exact position.

How it works step by step

Given this request:
Step 1 - The executor calls CreateAllInsertionPoints() and finds 5 insertion points:
Step 2 - For each insertion point, the executor runs all compatible modules in parallel:
Step 3 - Each module uses BuildRequest(payload) to construct the modified request. Only the target parameter changes; everything else stays the same:
What counts as an insertion point: With includeNested=true (the default), the executor also discovers nested structures - for example, a URL parameter whose value is Base64-encoded JSON will produce additional insertion points for each key inside that JSON. Each module also declares which InsertionPointTypes it accepts (via AllowedInsertionPointTypes()), so an SQLi module might only test URL params, body params, and JSON values, while skipping cookies and headers. Typical vulnerabilities found:
  • SQL injection (error-based, blind)
  • Cross-site scripting (XSS)
  • Server-side template injection (SSTI)
  • Command injection
  • Path traversal / LFI
  • SSRF
  • CRLF injection
  • NoSQL injection
  • XML/SAML injection
  • Insecure deserialization
Active modules using this scope (18): sqli_error_based, ssti_detection, reflected_ssti, csti_detection, ssrf_detection, lfi_generic, lfi_path_traversal, crlf_injection, nosqli_error_based, nosqli_operator_injection, xml_saml_security, insecure_deserialization, backslash_transformation, suspect_transform, smart_behavior_detection, input_behavior_probe, race_interference, oast_probe (hybrid)

ScanScopeRequest

Invoked once per unique request/response pair. The module receives the entire HttpRequestResponse and decides on its own what to modify. It is not given a specific parameter - it has full control over the request structure. This scope is used for vulnerabilities that:
  • Don’t map to a single parameter (e.g., changing the HTTP method, adding new headers)
  • Need cross-parameter context (e.g., comparing timing across multiple params)
  • Test request-level properties (e.g., JWT tokens, CSRF tokens, caching behavior)
  • Internally manage their own parameter iteration for specialized logic

How it works step by step

Given this request that returns a 403:
The forbidden_bypass module receives the whole request and tries multiple attack vectors itself:
The host_header_injection module tests header reflection:
The jwt_vulnerability module manipulates the JWT token:
Notice how none of these attacks target a single parameter - they modify the request structure, headers, method, or tokens. That’s why they use ScanScopeRequest instead of ScanScopeInsertionPoint. Typical vulnerabilities found:
  • 403/401 bypass (path tricks, method tampering, header injection)
  • Host header injection
  • Open redirect
  • JWT vulnerabilities (algorithm confusion, weak secrets)
  • CSRF verification bypass
  • Web cache poisoning
  • Prototype pollution
  • XXE (full-body injection)
  • HTTP method override
  • Swagger/API documentation exposure
  • File upload vulnerabilities
  • JSONP callback injection
  • Nginx path escape
Active modules using this scope (20): forbidden_bypass, host_header_injection, open_redirect, jwt_vulnerability, csrf_verify, web_cache_poisoning, prototype_pollution, client_prototype_pollution, xxe_generic, xss_light_scanner (3 sub-modules), sqli_boolean_blind, code_exec, file_upload_scan, spring_actuator_misconfig, nginx_path_escape, path_normalization, jsonp_callback, oast_probe (hybrid) Passive modules using this scope (19): info_disclosure_detect, secret_detect, cookie_security_detect, cors_headers_detect, content_type_mismatch, dom_xss_detect, csrf_detect, mixed_content_detect, auth_headers_detect, jwt_weak_secret, oauth_facebook_detect, openredirect_params, sensitive_url_params, sourcemap_detect, sql_syntax_detect, serialized_object_detect, crypto_weakness_detect, anomaly_ranking, idor_params_detect

ScanScopeHost

Invoked once per unique host. The executor deduplicates by canonical origin (scheme://host:port) - if 500 requests arrive for https://example.com, the module runs only once for that origin. Because the key is the full origin, the same host on a different port is treated independently: example.com:443 (https), example.com:8443, and example.com:8080 are each scanned on their own, so a ScanScopeHost module is no longer suppressed on :8443/:8080 after :443 claims the (module, host) pair. This scope is for expensive one-time checks that apply to the entire origin, not to individual pages or parameters.

How it works step by step

Given 500 different requests to example.com:
The executor runs each ScanScopeHost module only on the first request it sees for each canonical origin (scheme://host:port). The remaining 499 requests to the same origin are skipped — but a request to a different scheme/port claims the module afresh:
Typical vulnerabilities found:
  • CORS misconfiguration
  • Default credentials
  • GraphQL introspection enabled
  • HTTP request smuggling
  • Sensitive file discovery (.env, .git/config, robots.txt)
  • Missing security headers
Active modules using this scope (5): cors_misconfiguration, default_credentials, graphql_scan, http_request_smuggling, sensitive_file_discovery Passive modules using this scope (1): security_headers_missing

Hybrid Scope

A module can declare multiple scopes. Currently, oast_probe is the only module that does this:
This means it runs in both modes for maximum coverage:
OAST callbacks can trigger from either parameter-level vectors (SSRF via URL param) or request-level vectors (blind SSRF via Host header), so it needs both scopes.

What Happens With Different Inputs

Full request with parameters

Simple URL with no parameters

Static file URL

URL with path parameters only (REST-style)

JSON API with nested structures


Execution Order

For each incoming request, the executor runs scopes in this order:
Passive modules run first (sequentially, since they do no network I/O), then all three active scope categories run concurrently.

Choosing a Scope for New Modules

The scope is set in the module constructor: