Files
rengine/shared/services/scan_surface/__init__.py
T
Yogesh OjhaandClaude Opus 5 b0a47ba087 feat(oast): an instance-owned callback server, and a tier that pays the wait once
Out-of-band testing is an instance setting — `off`, `self_hosted` or
`public` — with the server, the token (the INTERACTSH API key row) and the
wait resolved once in `shared/services/oast.py` and read on the stage
thread. A mode that cannot be used is off and says why: self-hosted with no
server, or public without the disclosure acknowledged. A fresh instance is
off. `POST /oast/test` asks a public address for `/poll` over HTTPS and
reports that the server answered, never that OAST works.

The engine keeps one switch. `FieldNeeds` puts the resource key on the
field and `GET /engines/catalog` fills `unavailable_reason`, so the builder
renders the instance reason beside a switch that stays settable.

Measured on nuclei v3.11.1: with `-no-interactsh` a check that needs a
callback still loads and the request is refused — 0 requests, exit 0. So
the batch reported COMPLETED and every origin in it read `scanned` for
checks that never touched the target. The selection now drops them when
nothing is listening, one coverage row reports the count and the reason,
and `Tier.OAST` is left out of the planned tiers.

Membership is what a check references, not what it is tagged: 615 of the
12,586 official rows reference an interactsh placeholder and 233 of those
carry no `oast` tag. `vuln_templates.needs_oast` is parsed at index time; a
library resync fills the column.

The wait is paid on out-of-band batches alone, which sweep for 30 minutes
so it is paid fewer times, and the tier names the server on its own rows.
A finding's callback is rendered on the sheet from one label map; the list
path is bared to the metadata.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-21 20:53:01 +05:30

83 lines
1.6 KiB
Python

"""The scan surface plan: what a vulnerability scanner is handed, and why."""
from shared.services.scan_surface.batches import batch_size, batches, chunk
from shared.services.scan_surface.cluster import (
Cluster,
RootCandidate,
cluster_roots,
same_origin,
)
from shared.services.scan_surface.normalize import (
Root,
parse_root,
root_value,
service_value,
)
from shared.services.scan_surface.plan import (
SurfaceItem,
SurfacePlan,
build,
covered_before,
library_tags,
mark,
settle,
split_members,
write,
)
from shared.services.scan_surface.rank import base_rank, cluster_rank
from shared.services.scan_surface.requests import (
FUZZABLE_CLASSES,
Origin,
build_requests,
by_origin,
origins,
)
from shared.services.scan_surface.tech import host_tags
from shared.services.scan_surface.tiers import (
TechGroup,
TierPlan,
cost,
split,
tech_groups,
top_paths,
wants_callback,
)
__all__ = [
"FUZZABLE_CLASSES",
"Cluster",
"Origin",
"Root",
"RootCandidate",
"SurfaceItem",
"SurfacePlan",
"TechGroup",
"TierPlan",
"base_rank",
"batch_size",
"batches",
"build",
"build_requests",
"by_origin",
"chunk",
"cluster_rank",
"cluster_roots",
"cost",
"covered_before",
"host_tags",
"library_tags",
"mark",
"origins",
"parse_root",
"root_value",
"same_origin",
"service_value",
"settle",
"split",
"split_members",
"tech_groups",
"top_paths",
"wants_callback",
"write",
]