Skip to content

[Security] Safe Mode Guardrail Bypass via Crafted Target String Containing '/' Character #267

@advikdivekar

Description

@advikdivekar

Description

A HIGH security vulnerability exists in `backend/secuscan/routes.py` at lines 33–41 and 188–195. The `is_filesystem_target()` helper treats any string containing a `/` that does not start with `http://` or `https://` as a filesystem path, causing the entire target validation block — including safe mode enforcement — to be silently skipped.

Impact

An attacker (or a user who wants to misuse the tool) can bypass the safe mode guardrail — the primary safety control that prevents scanning public internet hosts — by appending any `/` to a target string. For example, passing `8.8.8.8/32` (a valid nmap CIDR target) causes `is_filesystem_target` to return `True`, `validate_target` is never called, and nmap runs the scan against the public Google DNS server even when `SECUSCAN_SAFE_MODE_DEFAULT=true`. Any public IP or hostname followed by a path component bypasses the guardrail.

This undermines a core security premise of the project: that safe mode prevents unauthorized external scanning.

Steps to Reproduce

  1. Start the backend with default settings (`SECUSCAN_SAFE_MODE_DEFAULT=true`).
  2. Submit a task with a crafted target:

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

  1. Observed result: the task is accepted and nmap runs against `8.8.8.8/32` (Google DNS), a public IP, even though safe mode is enabled. The target `8.8.8.8` alone would be correctly rejected with "Public IPs/networks not allowed in safe mode."

Expected Behaviour

CIDR notation and any other URL-like target strings must go through `validate_target`. The `is_filesystem_target` check should only match genuine local filesystem paths (absolute paths like `/home/user/repo` or Windows paths like `C:\`), not network addresses that happen to contain a slash.

Proposed Fix

Tighten `is_filesystem_target` so the generic `"/" in target` branch is removed. Replace it with stricter checks:

```python
def is_filesystem_target(target: str) -> bool:
# Explicit filesystem roots only — not network addresses
if target.startswith(("/", "./", "../", "~/")):
return True
if re.match(r"^[A-Za-z]:[\\/]", target): # Windows paths
return True
return False
```

CIDR notation (`192.168.1.0/24`) is already handled correctly by `ipaddress.ip_network` inside `validate_target` and does not need special-casing in `is_filesystem_target`.

Labels: `type:security` `level:intermediate` `gssoc:approved`

Please assign this issue to me under GSSoC 2026. I will open a PR with a complete fix covering all affected files, proper test coverage, and verification steps.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions