Severity
HIGH — Unauthenticated mutation endpoints allow injection of arbitrary data into any org.
Problem
apps/scanner/main.py exposes endpoints (/scan, /analyze, /scan/shodan, /telegram/poll, /fingerprint) that accept org_id as a plain POST body field with no authentication. Any party who can reach the scanner's port can:
- Write domains/events/alerts to any org's data by supplying a known
org_id UUID
- Trigger expensive Camoufox renders or Whisper transcription on behalf of any org
- Poison another org's threat feed with fake detection data
SCANNER_CORS_ORIGINS defaults to "*" — CORS is not a security boundary for server-to-server calls.
The README says "the API/dashboard layer is responsible for authenticating it upstream" but no auth layer is present in this repo.
Fix
Add a shared-secret check on all non-/health endpoints:
# apps/scanner/main.py
SCANNER_SECRET = os.environ["SCANNER_SECRET"]
async def verify_scanner_token(x_scanner_secret: str = Header(...)):
if x_scanner_secret != SCANNER_SECRET:
raise HTTPException(status_code=401, detail="Unauthorized")
@app.post("/scan")
async def scan(payload: ScanPayload, _: None = Depends(verify_scanner_token)):
...
The Cloudflare Worker API sends X-Scanner-Secret: ${process.env.SCANNER_SECRET} on all calls to the scanner.
Files
apps/scanner/main.py lines 96–276 (all mutation endpoint handlers)
apps/scanner/.env.example — add SCANNER_SECRET=changeme
apps/api/src/lib/scanner.ts or wherever the API calls the scanner — add header
Severity
HIGH — Unauthenticated mutation endpoints allow injection of arbitrary data into any org.
Problem
apps/scanner/main.pyexposes endpoints (/scan,/analyze,/scan/shodan,/telegram/poll,/fingerprint) that acceptorg_idas a plain POST body field with no authentication. Any party who can reach the scanner's port can:org_idUUIDSCANNER_CORS_ORIGINSdefaults to"*"— CORS is not a security boundary for server-to-server calls.The README says "the API/dashboard layer is responsible for authenticating it upstream" but no auth layer is present in this repo.
Fix
Add a shared-secret check on all non-
/healthendpoints:The Cloudflare Worker API sends
X-Scanner-Secret: ${process.env.SCANNER_SECRET}on all calls to the scanner.Files
apps/scanner/main.pylines 96–276 (all mutation endpoint handlers)apps/scanner/.env.example— addSCANNER_SECRET=changemeapps/api/src/lib/scanner.tsor wherever the API calls the scanner — add header