Connected-device security
Status: current device product and safety boundary; reconciled 2026-08-29.
ShakerScan treats TVs, cameras, printers, routers, NAS systems, conference equipment, and other network-connected devices as a separate security product surface. A device is not a Web DAST target, even when it exposes one or more web interfaces.
Device capacity is opt-in so an existing DAST installation does not lose worker slots or memory.
Start it with ./scanner.sh devices start; inspect it with ./scanner.sh devices status, and stop it
with ./scanner.sh devices stop.
Product boundary
- Devices live in
device_targets; their interfaces and observed services live indevice_interfacesanddevice_services. Thedevice_targets.idUUID is the durable identity; its current IP address or hostname is mutable and every change is retained indevice_locator_history. - Device scans use
run_kind=device_postureand a dedicated Redis queue and worker. - Web interfaces discovered on any TCP port are checked by hidden
device_web_dastchildren. Those children have no Web target, cannot alter Web target or ASM statistics, and do not appear in the normal scan list or dashboard totals. - Device findings use
source=device, have a device-scoped fingerprint, and are available through the Device filter without changing ordinary DAST posture metrics. - Device-worker build health is stored separately from the Web DAST worker registry. Adding or rebuilding device capacity therefore cannot make the ordinary DAST fleet stale or non-uniform.
Coverage profiles
| Profile | TCP inventory | UDP inventory | Typical use |
|---|---|---|---|
inventory | Naabu priority/device hints plus top 100 TCP ports; Nmap fingerprints open ports | Small common-device set | Fast reachability and first inventory |
posture | Chunked Naabu CONNECT discovery of all 65,535 TCP ports; Nmap fingerprints open ports | Curated discovery/management set | Normal device assessment |
thorough | Chunked Naabu CONNECT discovery of all 65,535 TCP ports; deeper Nmap fingerprinting | Curated discovery/management set | Higher-confidence service posture |
Every profile is scoped to exactly one hostname or IP. URLs, CIDR ranges, paths, credentials, and shell-like locators are rejected. The operator must explicitly confirm authorization before a scan is queued.
Coverage and safety are independent controls. inventory, posture, and thorough select how much
of the device is inventoried; they never grant permission for more invasive actions. The separately
recorded safety profiles are:
observe_only: discovery, banners, TLS/HTTP detection, and SSH posture handshakes. Web origins are inventoried but no Web DAST children are launched.safe_remote: bounded non-destructive network checks and passive device-owned Web DAST. This is the default and preserves the original connected-device behavior.authenticated_active: supplied-credential SSH and web checks with device-bound, encrypted credential profiles. It never guesses credentials. Fixed host review is read-only; model-authored remote SSH commands require a separate exact-plan user confirmation.
Older releases advertised a fourth lab_invasive profile that no worker ever implemented. It has
been removed; a request that still names it is rejected and should use authenticated_active.
Persistent-state, resource-intensive, and destructive action classes remain unavailable to every
profile.
Every device action receives a declared safety class. The device safety governor blocks actions not permitted by the selected profile and records baseline, post-inventory, and final health checkpoints. If a previously healthy device degrades, the scan is halted and cannot produce an allow decision.
Before inventory begins, ShakerScan runs a bounded, multi-signal reachability preflight. It checks
previously observed open TCP ports, operator-supplied hints, policy and credential-bound ports, a
compact common-device set, and a class-specific set for media/TV, camera, printer, router/NAS,
conference, building, or industrial equipment. Nmap host discovery tries ARP/ICMP plus the same TCP hints and curated
UDP probes. One successful TCP connection, an explicit refusal/reset, or a real Nmap response reason
is enough to prove that the network stack answered. DNS resolution, Nmap's user-set assume-up
reason, timeouts, and silence do not. The receipt distinguishes online, unreachable, and
inconclusive, records the evidence and check time, and is shown on the device list and detail page.
Media devices also receive manufacturer-aware hints when the inventory identifies Vizio, LG,
Samsung, TCL, or Hisense. These include Vizio SmartCast 7345/legacy 9000, LG webOS
3000/3001, Samsung Smart View/Tizen 8001/8002, Roku ECP 8060, Android/Google TV remote and
Cast ports used by multi-platform TCL/Hisense models, and Hisense VIDAA MQTT 36669. A probe is only
a discovery hint: it is never rendered or evaluated as an open service without a positive response.
An inconclusive inventory preflight stops without expanding to all TCP ports. For posture and
thorough, which already require all-TCP coverage, the requested all-TCP discovery may begin as a
fallback and its result is reused as the main inventory rather than scanning the range twice. An open
port or explicit closed-port response can then prove the device online; an all-filtered/silent result
remains inconclusive. Until online status is positively proven, authenticated and later protocol
actions do not run, and the scan produces neither a numeric score nor a grade.
TCP assessment is staged. A bounded priority pass checks common administration, media, printing,
messaging, and nonstandard web ports first. Naabu owns TCP discovery for every profile. The
inventory profile follows the priority pass with its top-100 scope; posture and thorough divide
all 65,535 ports into bounded ranges. Connect concurrency is derived from the configured probe rate
and socket timeout so a silently filtered host cannot turn a nominally fast run into an hours-long
one. Each failed range is retried once, while confirmed ports from every attempt are preserved.
Cancellation and repeated health degradation are checked between ranges. Nmap never replaces a
failed all-TCP Naabu run: it runs expensive service/version fingerprinting only against confirmed-open
TCP ports and separately checks the curated UDP set. Missing Naabu is therefore an explicit worker
readiness failure, and an incomplete range stays visible as partial coverage.
The scanner records service name, product/version hints, CPE, transport, port, encryption state,
hostnames, addresses, MAC/vendor evidence when visible, and bounded OS fingerprints. UDP coverage is
deliberately curated because a complete UDP sweep is both slow and ambiguous; the report lists the
exact requested UDP ports instead of claiming full UDP coverage. An Nmap open|filtered UDP result
with no-response is retained as an inconclusive observation, not a listening service. It is
excluded from policy evaluation and scoring unless a protocol response confirms the port as open.
Scan reports and device details present these observations in a separate uncertainty section, so an
operator can inspect the raw evidence without mistaking UDP silence for an exposed service.
Successful tool execution is reported separately from coverage semantics. A completed Naabu scope
means the reachable open-port inventory is complete from the scanner's network vantage point; it
does not claim that silent TCP ports were distinguished as closed versus filtered. Failed ranges and
unresolved UDP observations prevent an allow decision and preserve prior service history. Silence
does not become a service or finding and does not reduce the vulnerability score.
Each report also carries a deterministic device-evidence/v1 graph. It normalizes the device,
interfaces, services, inconclusive observations, web origins, tool executions, and health
checkpoints into stable nodes, edges, and observations. This is the compatibility layer used by
future protocol adapters and the AI-directed device investigator; adapters exchange normalized
observations rather than requiring later stages to parse raw tool strings.
The first protocol-aware adapters cover SSDP/UPnP discovery and mDNS/DNS-SD service enumeration.
They send one bounded unicast discovery message to the exact authorized device rather than widening
scope to a multicast segment. Responses, advertised service types, server metadata, USNs, DNS-SD
records, and UPnP LOCATION values are normalized into the evidence graph. A cross-host LOCATION
is recorded as out of scope and is never followed automatically. A valid application response can
promote an Nmap open|filtered observation to a validated UDP service; silence remains inconclusive.
Both adapters now run in the fast inventory profile as well as the all-TCP profiles.
Web interfaces on any port
ShakerScan does not assume ports 80 or 443. After service inventory, it sends a bounded HTTP probe to
each eligible open TCP service up to the declared profile probe cap, trying cleartext and TLS in the
order suggested by the fingerprint.
This can discover origins such as http://device:8008, https://device:8443, or an ephemeral vendor
management port.
Discovered origins can receive passive quick, standard, or deep Web DAST coverage. Active Web
DAST families are forcibly disabled, request and time budgets are capped, and at most 32 origins are
handed off. Each merged finding retains the parent device, child scan, origin, connect address, Host
header, and SNI provenance. Any probe or child truncation marks the assessment incomplete and prevents
an allow decision.
SSH and service policies
SSH is checked on the port where it was actually discovered, not only port 22. The scanner records
the banner, server host-key type and size, authentication methods, negotiated cipher/MAC, password
and keyboard-interactive availability, public-key availability, and weak negotiated algorithms. It
never guesses usernames or passwords. Under authenticated_active, an operator may attach one
encrypted, device-bound SSH profile; offered methods are enumerated independently and the supplied
credential is attempted at most once per device scan, subject to persisted cooldown and daily caps.
An authenticated scan may explicitly request the ssh-authenticated-host-review capability. Before
the credential is submitted, ShakerScan requires a SHA-256 SSH host-key fingerprint from an earlier
device observation and fails closed if the key changes. After authentication, the worker runs only
server-owned read-only bundles for identity/runtime, interfaces/listeners, process and service names,
accounts and bounded privilege metadata, mounts/hardening, packages, and update metadata. The model
cannot supply shell text to this fixed capability. Each bundle has a timeout and byte cap; outputs are secret-scrubbed, hashed,
and stored as device evidence. Collection failure is incomplete coverage, never a secure conclusion.
Agentic mode also supports agent-confirmed-ssh-shell when fixed collectors cannot answer the
objective. The model may propose up to eight exact remote-device commands, but it cannot execute or
approve them. ShakerScan shows the immutable command list, risk markers, device and port, pinned host
key, timeout, expiry, and SHA-256 plan digest. A user must separately confirm both the exact commands
and their possible effects. The single-use plan then runs on the isolated device worker without a PTY
or forwarded stdin, with bounded, redacted, hashed output. This authority never grants local
ShakerScan-host shell access and cannot transfer to another device, address generation, port,
credential profile, or SSH host key.
Service policies are ordered rules with four outcomes:
allow: the observed service is expected.deny: the service must not be listening.review: the service needs an operator decision.require: the service is permitted only when controls such as encryption, disabled SSH password authentication, no weak SSH algorithms, or public-key authentication are proven.
Unmatched confirmed-open services default to review. Required controls fail closed when they cannot be verified. ShakerScan ships generic, media-device, camera, printer, and network-appliance baselines. A device can use a selected custom policy; otherwise the closest active built-in policy is chosen by device class, with the generic fail-closed baseline as fallback.
Policy actions determine the final posture decision: deny and failed require controls block,
review requires review, and allow is emitted only when all required inventory stages completed
and no confirmed finding remains. The score and decision therefore cannot report an F-grade review
set as policy-conformant.
Findings are auto-resolved only after a successful all-TCP assessment with untruncated web detection and complete web-child coverage. A fast or partial inventory never clears older findings.
REST workflow
# Read device-worker readiness
curl http://localhost:8080/devices/readiness
# Register one device
curl -X POST http://localhost:8080/devices \
-H 'Content-Type: application/json' \
-d '{"name":"Lobby display","primary_locator":"tv.example.lan","device_class":"media"}'
# Keep the same permanent device after DHCP changes its address
curl -X POST http://localhost:8080/devices/DEVICE_ID/locator \
-H 'Content-Type: application/json' \
-d '{
"locator":"192.168.1.45",
"reason":"DHCP assigned a new address",
"confirm_same_device":true
}'
# Queue an authorized full TCP posture scan with passive web handoff
curl -X POST http://localhost:8080/devices/DEVICE_ID/scan \
-H 'Content-Type: application/json' \
-d '{
"profile":"posture",
"confirm_authorized":true,
"include_web_dast":true,
"web_scan_type":"standard",
"max_web_origins":8
}'
Policy management is available at GET/POST /device-policies and
PATCH /device-policies/{policy_id}. Device inventory is available at GET/POST /devices,
GET/PATCH/DELETE /devices/{device_id}, POST /devices/{device_id}/locator, and
GET /device-scans.
Stable identity and changing addresses
A TV or other DHCP client can keep the same ShakerScan device ID while its IP address changes. The device detail page's Change address action updates only the current locator. Policies, credentials, findings, services, scans, agent memory, and history remain attached to the permanent device UUID. Completed and queued scan records retain the exact locator they used.
The operator must confirm that the replacement locator belongs to the same physical device. This is deliberately not inferred from IP reuse: DHCP can give an old address to a different host. Address changes are blocked while a posture scan, service probe, or Device Hunt is active, preventing an in-flight operation from switching hosts. Prefer a stable local DNS/mDNS name where it is reliable; automatic MAC- or sensor-assisted relocation can be added later only with verified identity evidence.
Imported API requests
The device page accepts Postman Collection v2 JSON plus an optional environment, HAR 1.2 traffic, OpenAPI 3.x, and Swagger 2.0 JSON. Imported documents can contain tokens, cookies, authorization headers, IDs, request bodies, and captured responses, so ShakerScan encrypts the complete payload and publishes only a redacted request inventory. Postman pre-request/test scripts and HAR responses are never executed.
During a device scan, selected collections are decrypted only inside the dedicated device worker. Postman variables and authentication definitions are resolved in memory. HAR preserves captured request order, headers, cookies, and bodies. OpenAPI/Swagger generates bounded examples from examples, defaults, enums, and schemas; only local JSON Pointer references are resolved, and no external reference is fetched. An optional device base URL can supply a missing specification server. A separately bound web credential can be inherited in worker memory without entering the document or Device Hunt transcript. Every socket is still pinned to an HTTP(S) origin positively discovered on the registered device; an imported URL, server declaration, redirect, variable, or environment value cannot send the scanner to another host. Imported URL ports are also added to reachability priority hints.
Quick coverage replays saved safe methods. Standard and Deep add an authentication-removal comparison
for safe authenticated requests. POST, PUT, PATCH, and DELETE are skipped by default;
exact replay requires the authenticated_active safety profile and a separate explicit confirmation
for that scan or Device Hunt session. Imported file bodies and unsupported body modes are skipped
with a request-level reason. Results retain redacted per-request status, timing, body size/hash,
header names, skipped reasons, and request-aware findings without persisting request secrets.
HTTPS interfaces are assessed with a separate strict certificate handshake. Self-signed and otherwise
untrusted device TLS does not hide the interface: non-secret checks continue and create a TLS finding.
Selected credentials and imported requests continue under the existing testing authorization;
certificate trust adds no second confirmation or veto. The legacy allow_untrusted_tls_credentials
field remains accepted but does not control execution. Credential and state-changing permissions
remain enforced, and unverified TLS transmission is recorded as evidence, never labeled trusted.
Response cookies, authentication challenges, URL query values, token-like path segments, and
token-like request names are redacted before persistence.
After service discovery, a server-owned platform catalog recognizes Roku ECP, Vizio SmartCast, Samsung Tizen, LG webOS, Philips JointSPACE, Google Cast/DIAL, Panasonic VIERA, and Sony BRAVIA. Same-device SSDP descriptions are fetched and parsed to recover device identity, service schemas, control URLs, and nonstandard web origins. Bounded read-only platform probes then confirm application endpoints and authentication boundaries. Cleartext device APIs, unauthenticated privacy-sensitive reads, exposed version details, TLS failures, cookie defects, CORS behavior, and authenticated-versus- anonymous response equivalence become device findings with request evidence. Control and mutation families remain fully testable through exact confirmed imported requests and Device Hunt authority; they are not silently treated as unsupported merely because automatic discovery is read-only.
The device detail page displays a structured activity feed while a selected scan is running. It shows reachability, discovery, fingerprinting, web/API execution counts, failures, findings, and safety stops while suppressing command noise, payloads, and secrets.
Device targets in Hunt
Connected devices use ShakerScan's canonical, target-kind-aware Hunt runtime. The current Codex,
Claude, or OpenCode session is the planner, while ShakerScan executes a closed device capability
contract. Start through POST /hunts, drive only capabilities returned by that run, and confirm an
immutable SSH plan through POST /hunts/{hunt_id}/shell-plans/{plan_id}/confirm. The former
/devices/{device_id}/agent/session and /device-agent/session/* writes are quarantined migration
surfaces; their UI URL redirects to /hunt.
Device Hunt compatibility wording refers to the device-target Hunt capability pack derived from the Smart TV assessment
playbooks. GET /devices/{device_id}/capabilities resolves each capability as ready, completed,
blocked, planned, sensor-required, lab-only, or not applicable using current device evidence,
credentials, platform hints, and sensor readiness. inspect_capabilities refreshes this view during
an investigation. The catalog guides planning. Registered deterministic capabilities execute within
their contracts; the SSH shell capability additionally requires a separately user-confirmed immutable
plan.
The Device Hunt tools can inspect the registered device, capability pack, and user-bound redacted
request collections; queue a deterministic device or request-aware scan; inspect a device-owned
scan; query normalized graph evidence; and retain bounded notes. A run is fixed
to one device_target_id and one safety profile at creation. Tool arguments contain no locator,
credential, arbitrary URL, local-host shell, plugin, or safety-escalation field. The planner can only
propose remote-device SSH commands; confirmation is not a planner tool. Sessions are capped at 30 turns,
36 tool actions, six calls per turn, and three queued scans. Concurrent agent sessions and concurrent
device scans for the same device fail closed.
Device Hunt cannot create authoritative findings directly. A final AI debrief may retain evidence-backed,
typed candidates only when they cite real devref_N references created by device context,
scan-result, or evidence-graph reads. Candidates have a durable lifecycle (new, queued/verifying,
verified, refuted, inconclusive, blocked, or expired), a canonical device locus, and a registered
verifier contract; notes, queue acknowledgements, and model prose are not proof. The
verify_candidate tool resolves scope and probe inputs from the persisted candidate. Registered
server-owned verifiers cover policy-denied service exposure, strict TLS identity failure,
authenticated-versus-anonymous imported-request equivalence with a negative control, pinned-host-key
SSH policy violations, and exact CPE/version matches against a SHA-256-pinned offline advisory
snapshot. Each promotion requires fresh or hash-pinned deterministic evidence satisfying Proof
Contract v2 before it can create a device finding, verification record, and typed evidence instance.
Control-authorization claims abstain unless an exact read/mutate/read/restore/read contract exists.
The verifier supports only fixed server-validated restoration adapters bound to an imported request:
an explicit inverse request, one query parameter, one JSON field, or one form field. The restoration
value comes from the pre-test response at a declared JSON pointer, never from model text. Device Hunt
cannot select arbitrary cleanup code or invent a mutation. Every posture scan re-correlates the pinned
advisory snapshot, and resolves an old advisory finding only when the same service locus was observed
again and no longer matches. Silence is never treated as remediation.
Firmware and package advisories also preserve evidence tiers. Unauthenticated banners, Nmap product strings, SSDP metadata, and model names remain candidates; they cannot establish an exact vulnerable version. Promotion requires an authenticated host review, signed manifest, or another authoritative identity source tied to the exact observed service locus.
Offline advisory snapshot
Exact CPE/version promotion is backed by a compact, hash-pinned advisory snapshot rather than a
live vulnerability feed, so device workers make no external calls and no unverified data can
silently change matching behavior. The bundled snapshot lives at
scanner/data/device_advisories.json under the shakerscan-device-advisories/v1 schema. It is
loaded only through the real loader (scanner/scanner_tools/device_advisories.py), which requires
a regular file whose SHA-256 matches the pinned digest; a mismatched or missing file fails closed
instead of degrading to unpinned data.
Only advisories with explicit NVD version bounds (or an exact version) are included; unbounded
wildcard configurations are signal-only and are never emitted into the snapshot, so any promotable
match is provably version-bounded. The release image pins the bundled copy through
DEVICE_INTEL_DB_PATH and DEVICE_INTEL_DB_SHA256 in scanner/Dockerfile, and tests reject drift
between the file, the loader constant, and the Dockerfile pin.
An operator can substitute a newer or site-specific snapshot without rebuilding by pointing the
same two environment variables at a regular file and its SHA-256; DEVICE_INTEL_DB_SHA256 is
mandatory, so an unpinned override is rejected. Values are resolved at read time with the
environment taking precedence over the bundled fallback.
The snapshot is refreshed at release time with scripts/generate_device_advisories.py (stdlib
only, no API key; it honors the unauthenticated NVD rate limit). Typical refresh:
# Curated CVE selection against the live NVD API 2.0
python3 scripts/generate_device_advisories.py \
--cve CVE-2017-17562 --cve CVE-2023-38545 ... \
--output scanner/data/device_advisories.json --self-check
# Or product-wide queries for an embedded product
python3 scripts/generate_device_advisories.py --vendor mosquitto --output /tmp/mosquitto.json
The generator prints the new SHA-256 plus the exact DEVICE_INTEL_DB_PATH/DEVICE_INTEL_DB_SHA256
override lines. --self-check validates the written file through the real scanner loader and
confirms every record is bounded and promotable; --verify PATH runs the same validation against
an existing snapshot; --offline emits only the generator's built-in curated seed with no network
access; and --from-raw DIR rebuilds deterministically from cached NVD API responses. After a
refresh, copy the printed SHA-256 into both BUNDLED_SNAPSHOT_SHA256 in
scanner/scanner_tools/device_advisories.py and the ENV DEVICE_INTEL_DB_SHA256 line in
scanner/Dockerfile; the drift tests fail until both match.
Wireless and non-IP extensions
Bluetooth, BLE, Zigbee, Thread, and passive network telemetry require hardware or network placement that a normal Docker worker cannot safely assume. The readiness response advertises these as optional sensor capabilities, but this release does not claim radio coverage. The intended extension point is a separately enrolled, capability-labeled sensor that submits normalized device/interface/service evidence into the same device model while preserving the dedicated queue, authorization, provenance, and policy boundary.
Current limits
- The scanner observes the network path visible from its device worker; NAT, firewall rules, VLANs, and client isolation can hide services.
- A silent reachability check is inconclusive, not proof that a device is offline. Wake the device or move the worker to a network path that can reach it, then scan again.
- Service and OS fingerprints are evidence, not guaranteed product identity. Stable MAC identity is unavailable across routed networks and can be randomized.
- UDP coverage is a declared curated set, not all 65,535 ports.
- UDP silence is inconclusive. Firewalls can make closed and open UDP ports look identical from the worker's network path, so only a protocol response is treated as confirmed open.
- Cloud metadata/control-plane addresses are denied by default after DNS is pinned. Authorized public devices remain supported; operators can extend the deny CIDRs for their environment.
- No credential guessing, firmware extraction, destructive protocol testing, radio probing, or active XSS/SQLi is performed by the device workflow.
- Postman scripts, HAR responses, external OpenAPI references, and imported external hosts never execute. State-changing request replay is disabled unless the user explicitly binds collections and grants that fixed authority under an authenticated-active scan or Device Hunt session.
- Fixed authenticated host collection accepts only server-owned read-only bundles. Agent-authored remote SSH commands execute only after an earlier host key is pinned and a user separately confirms the exact digest-bound plan; local-host shell is never exposed.
Hunt service selection and managed authentication
An authorized active Hunt may select HTTP or HTTPS on any valid port of its existing canonical host. This is a per-action service selection: target UUID, frozen IP addresses, scope, credential version, and revocation checks remain unchanged. A redirect or imported script cannot authorize a different destination.
auth.session.establish accepts an optional origin for relative saved login endpoints;
absolute operator-saved endpoints select their own same-host service. New Hunt sessions
retain the admitted asset binding plus their login service, so an explicitly selected
session works in subsequent same-asset requests and refresh returns to the original login
port. Historical exact-bound sessions remain readable; Scan sessions retain exact binding.
browser.login_check accepts an optional origin, or derives it from the immutable saved
workflow. Credential decryption still occurs only in the worker. Device credentials are
revalidated against the live device inventory, not the separate web-target table.
Request-collection replay resolves only the selected, persisted collection origins against the same admitted asset, then narrows the replay transport to those origins. Collection ownership, selection digests, frozen addresses, budgets, and secret handling are unchanged. This does not authorize reuse between unrelated target UUIDs.
Device authorization investigations use the same API/service/repository as web Hunts.
Their graph records belong to device_target_id; an additive migration supports device
HTTP sessions and graph ownership without manufacturing web targets. Native device adapters
inherit the canonical Hunt request and scan limits rather than applying a second legacy
40-request / three-scan ceiling.
Hunt NSE transport and coverage
service.nse_check retains the installed Nmap analyses for http-methods,
http-security-headers, http-trace, and ssl-enum-ciphers. The HTTP analyses
use the worker's pinned transport, preserving Host and TLS SNI on the frozen
address. Same-asset HTTP/HTTPS redirects, including alternate ports and untrusted
certificates, reuse existing network authority; no per-hop approval is created.
A redirect to another asset is recorded as incomplete coverage, and other selected
checks continue. Evidence includes the actual response service and redacted URL.
HTTP discovery uses metered HEAD requests instead of an implicit -sV version
scan. Native TLS enumeration is forced on the explicitly selected port, including
nonstandard ports; broader fingerprinting remains service.fingerprint.
HTTP budgets count every request-header attempt, including connection-library
retries, detector requests, and permitted optional method probes. Unused HTTP
allowances are released. Native port/TLS device cost is still an estimate, not a
claim of exact handshake or packet counting.
The method analysis can probe POST and an unknown method as negative controls.
Those probes use the existing allow_state_changing_http permission and budget.
Without it, Hunt preserves the available read-method observations and explains
which optional probes were omitted instead of refusing the entire capability.
An incomplete script is not a clean security result; observations remain unverified
until a separate deterministic proof contract validates a finding.
NSE coverage outcomes do not stand in for a device health checkpoint. Repeated partial results (closed services, unavailable script output or optional omissions) do not trip the health circuit breaker, and a completed NSE action does not clear a pre-existing failure or operator pause. Traffic usage and pacing still settle; other capabilities retain their actual health-check behavior.