Skip to content

[BUG] SECUSCAN_ALLOW_LOOPBACK_SCANS is ignored by Network Policy - README quick-start example fails on a fresh install #2047

Description

@yughpatel

Labels: type:bug, priority:medium

## Summary

`SECUSCAN_ALLOW_LOOPBACK_SCANS` (default `true`) is documented and implemented as the setting that permits scanning `127.0.0.1`/loopback targets. Safe Mode (`validation.py`) honors it, but the independent Network Policy layer (`network_policy.py`) does not — its `network_denylist` unconditionally includes `127.0.0.0/8` with no check against the setting. As a result, loopback scans are always blocked by Network Policy regardless of this setting, on a completely default install.

## Why this matters

This isn't a theoretical edge case — it breaks the project's own Quick Start. The README's literal example under "API Examples" is:

```bash
curl -X POST http://127.0.0.1:8000/api/v1/task/start \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $API_KEY" \
  -d '{
    "plugin_id": "nmap",
    "inputs": {"target": "127.0.0.1"},
    "consent_granted": true
  }'

Any new contributor who follows the README exactly, on a fresh clone with only cp .env.example .env and a generated SECUSCAN_VAULT_KEY, gets an immediate, confusing failure instead of a working first scan. SECUSCAN_ALLOW_LOOPBACK_SCANS=true is even left uncommented/active in .env.example, signaling it should take effect by default — but it silently doesn't for this code path.

Reproduction steps

  1. Fresh clone, cp .env.example .env, set SECUSCAN_VAULT_KEY (all other settings left at their defaults — SECUSCAN_ALLOW_LOOPBACK_SCANS is true by default in both .env.example and config.py).
  2. Start the backend: python -m uvicorn backend.secuscan.main:app --host 127.0.0.1 --port 8000.
  3. Run the exact nmap/127.0.0.1 curl command from the README's "API Examples" section (above), using the generated backend/data/.api_key.
  4. Poll the task status: GET /api/v1/task/{task_id}/status.

Expected behavior

The task should be accepted and (assuming nmap is installed) proceed to execute, since SECUSCAN_ALLOW_LOOPBACK_SCANS=true is the default and is documented as enabling exactly this.

Actual behavior

The task is accepted (status: queued) but fails almost immediately with:

{
  "status": "failed",
  "error_message": "Network policy denied access to 127.0.0.1: Blocked by denylist rule: Operator configured denylist (matched: 127.0.0.0/8)"
}

This happens even though the same request passes Safe Mode's own loopback check — Network Policy is a second, independent gate that never consults allow_loopback_scans.

Scope

  • Suggested files: backend/secuscan/network_policy.py (the check_access/denylist logic — needs to skip or exempt the 127.0.0.0/8 rule when settings.allow_loopback_scans is true), backend/secuscan/config.py (default network_denylist, allow_loopback_scans)
  • For reference, backend/secuscan/validation.py:161 and :200 show the pattern already used to make Safe Mode respect this setting (if ip.is_loopback and not settings.allow_loopback_scans) — Network Policy has no equivalent check.
  • Not the same as [BUG] Network Policy Default Configuration Blocks All External Scanning — Tool Unusable Out of the Box #753 (closed) — that issue was about the empty network_allowlist blocking all public egress; its fix explicitly "preserve[d] denylist protection," which is what still unconditionally blocks loopback today.

Evidence

Verified locally (Windows 11, fresh clone, default .env):

$ curl -s -X POST http://127.0.0.1:8000/api/v1/task/start \
    -H "Content-Type: application/json" -H "X-API-Key: $API_KEY" \
    -d '{"plugin_id": "nmap", "inputs": {"target": "127.0.0.1"}, "consent_granted": true}'
{"task_id":"...","status":"queued", ...}

$ curl -s -H "X-API-Key: $API_KEY" http://127.0.0.1:8000/api/v1/task/{id}/status
{"status":"failed","error_message":"Network policy denied access to 127.0.0.1: Blocked by denylist rule: Operator configured denylist (matched: 127.0.0.0/8)", ...}

Environment

  • OS: Windows 11
  • Python Version: 3.14.5
  • Node Version: 24.16
  • Docker: not used (native dev setup)

Definition of done

  • Network Policy's denylist check exempts loopback ranges when settings.allow_loopback_scans is true, consistent with how Safe Mode already handles it
  • README's Quick Start nmap/127.0.0.1 example succeeds (past the network-policy gate) on a fresh default install
  • Test added covering allow_loopback_scans=true + Network Policy for a 127.0.0.1 target
  • Docs/.env.example comment updated if the interaction between Safe Mode and Network Policy for loopback needs clarifying

Additional context

Two independent guardrail layers (Safe Mode vs. Network Policy) currently implement the loopback exception inconsistently. Worth a short code comment in network_policy.py explaining the intended relationship between the two, to prevent this drifting again.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:backendBackend API, database, or service worklevel:intermediate35 pts difficulty label for moderate contributor PRspriority:mediumImportant issue with normal urgencytype:bugBug fix work category bonus label

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions