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
- Start the backend with default settings (`SECUSCAN_SAFE_MODE_DEFAULT=true`).
- 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
}'
```
- 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.
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
```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
}'
```
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.