[
  {
    "id": "S6-001",
    "class": "S6",
    "file": "apps/web/src/pages/api/admin/support/providers/[id]/test.ts",
    "line": 94,
    "symbol": "fetch(url, …)",
    "severity": "high",
    "attacker_path": "Admin sets openai-compat provider base_url to attacker or internal URL, then POST /api/admin/support/providers/{id}/test; worker POSTs to {base_url}/chat/completions with Bearer API key.",
    "why": "base_url is only z.url()-validated; no SSRF allow-list or private-IP block before fetch.",
    "fix_direction": "HTTPS provider hostname allow-list + block private/reserved IPs; validate at save and immediately before fetch.",
    "confidence": "high"
  },
  {
    "id": "S6-002",
    "class": "S6",
    "file": "apps/web/src/server/ai/providers/listModels.ts",
    "line": 118,
    "symbol": "fetchProviderModels",
    "severity": "high",
    "attacker_path": "Admin poisoned base_url; GET /models or POST …/models/refresh triggers fetch to {base_url}/models with Authorization Bearer API key.",
    "why": "Same unconstrained admin-supplied baseUrl passed to fetch.",
    "fix_direction": "Reuse centralized outbound URL guard for all listModels/test/chat completion fetches.",
    "confidence": "high"
  },
  {
    "id": "S6-003",
    "class": "S6",
    "file": "apps/web/src/server/monitor/channels/botmaster.ts",
    "line": 49,
    "symbol": "botmaster.send",
    "severity": "medium",
    "attacker_path": "Admin sets monitor channel config.baseUrl to internal/metadata host; alert delivery POSTs outbound with decrypted channel credential in auth header.",
    "why": "channel.config.baseUrl is concatenated into fetch URL without SSRF controls.",
    "fix_direction": "Allow-list Botmaster HTTPS hosts and block private/reserved destinations before fetch.",
    "confidence": "high"
  },
  {
    "id": "SHAPE-B-001",
    "class": "SHAPE-B",
    "file": "apps/web/src/server/security/turnstile.ts",
    "line": 151,
    "symbol": "applyTurnstileFor",
    "severity": "medium",
    "attacker_path": "When siteverify is unreachable, login/register/magic-link-send proceed without captcha; attacker brute-forces credentials under rate limit only.",
    "why": "Default fail-open on unavailable is defined in turnstile.ts and imported by auth routes (login-email.ts, register, magic-link/send).",
    "fix_direction": "Fail closed on unavailable for credential endpoints or add compensating lockout/stricter limits.",
    "confidence": "high"
  },
  {
    "id": "SHAPE-B-002",
    "class": "SHAPE-B",
    "file": "apps/web/src/server/security/turnstile.ts",
    "line": 134,
    "symbol": "applyTurnstileFor E2E bypass",
    "severity": "high",
    "attacker_path": "On non-production worker with E2E_SECRET, attacker sends x-e2e-secret on auth routes and skips Turnstile entirely.",
    "why": "Bypass default in turnstile.ts consumed by applyTurnstileFor on all credential routes; preview may ship E2E_SECRET.",
    "fix_direction": "Remove public-preview bypass; isolate E2E to local/CI-only flag or host binding.",
    "confidence": "high"
  },
  {
    "id": "S1-001",
    "class": "S1",
    "file": "apps/web/src/pages/api/auth/firebase-verify.ts",
    "line": 85,
    "symbol": "E2E firebase bypass branch",
    "severity": "critical",
    "attacker_path": "With E2E_SECRET, POST firebase-verify using idToken E2E:+phone and x-e2e-secret; obtains session for that phone without Firebase OTP.",
    "why": "Static secret plus token prefix replaces Firebase JWT verification and skips rate limit.",
    "fix_direction": "Disable E2E auth bypass on publicly reachable preview; use CI-local-only endpoints.",
    "confidence": "high"
  },
  {
    "id": "S1-002",
    "class": "S1",
    "file": "apps/web/src/pages/api/test/mint-verification-token.ts",
    "line": 95,
    "symbol": "createToken",
    "severity": "high",
    "attacker_path": "With x-e2e-secret, POST mint-verification-token for victim email; use returned verifyUrl to verify victim mailbox without access.",
    "why": "Live verification tokens minted for arbitrary emails when E2E_SECRET matches on preview host.",
    "fix_direction": "Remove or network-isolate /api/test/* on dev.multi.deal; never deploy E2E_SECRET to shared preview.",
    "confidence": "high"
  }
]
