# Multideal scan — fix-commit-bank harvest (items #8 / #10)

date: 2026-06-20 · scanner: cursor-agent (composer-2.5), read-only, blind (no audit docs / ground truth) · workspace: `multideal@40056d2c6` detached worktree · raw report: `2026-06-20-multideal-scan-candidates.{md,json}`

## Why this exists
Items #8 (S4/S6 → n≥3) and #10 (Shape-B → n≥3) are corpus-scarcity-blocked. Per directive: **do NOT run k≥3 rolls — find real fix commits, work with what we have, document the gaps.** This scan harvests REAL exploitable defects in multideal so a separate fixer session creates the FIX COMMITS that become ground-truth cells (vuln = `<fix>~1`, safe = `<fix>`).

## Candidates (7) — Claude-verified against source (not hallucinated)

| id | class | file:line | verdict | cell value |
|----|-------|-----------|---------|-----------|
| S6-001 | S6 SSRF | `apps/web/src/pages/api/admin/support/providers/[id]/test.ts:94` | REAL — admin `baseUrl`→`fetch`, no allow-list | clean cell |
| S6-002 | S6 SSRF | `apps/web/src/server/ai/providers/listModels.ts:118` | REAL — same unconstrained admin baseUrl | clean cell |
| S6-003 | S6 SSRF | `apps/web/src/server/monitor/channels/botmaster.ts:49` | REAL — channel `cfg.baseUrl`→`fetch` + credential | clean cell |
| SHAPE-B-001 | Shape-B | `apps/web/src/server/security/turnstile.ts:151` | REAL — `unavailable`→proceed fail-open, imported by auth routes | clean cell |
| SHAPE-B-002 | Shape-B | `apps/web/src/server/security/turnstile.ts:134` | REAL but DEPLOYMENT-CONDITIONAL — E2E bypass guarded by `ENVIRONMENT!=='production'`; risk = preview ships `E2E_SECRET` + public | judgment |
| S1-001 | S1 | `apps/web/src/pages/api/auth/firebase-verify.ts:85` | REAL but DEPLOYMENT-CONDITIONAL — same E2E-secret bypass cluster | judgment |
| S1-002 | S1 | `apps/web/src/pages/api/test/mint-verification-token.ts:95` | REAL but DEPLOYMENT-CONDITIONAL — `/api/test/*` mints tokens on preview | judgment |

## n-impact (the harvest scorecard)
- **S6 SSRF — SOLVED to n≥3.** 3 distinct real instances (3 files, 3 sinks) → +3 cells on top of existing `S6-jira-baseurl-ssrf` (n=1) = **n=4**. Note shape: existing cell = TENANT baseUrl; these = ADMIN baseUrl (network-pivot/stored-config SSRF). Distinct enough to count.
- **S4 SQLi — HONEST GAP. 0 exploitable instances in multideal** after cursor traced every `sql.raw`/template hit. S4 stays **n=1 point-estimate** (`S4-kb-spaceids-sqli`, a different repo). Promotion to a RATE needs S4 fix commits from another corpus source — NOT available yet.
- **Shape-B — PARTIAL.** 1 clean new (`SHAPE-B-001` turnstile fail-open) + the E2E variant. With existing Shape-B (n=1, `refresh.ts`/`session.ts` 2FA) → toward n≥3 but not cleanly; E2E-cluster is deployment-conditional.

## Fixer-session protocol (the handoff)
1. User runs a SEPARATE session in `~/Projects/multideal` (main checkout, NOT the scan worktree).
2. For each candidate to fix: make the real security fix, commit ONE fix per commit, message naming the class (e.g. `fix(ssrf): allow-list admin provider baseUrl before fetch`).
3. This session polls `git -C ~/Projects/multideal log` for the new fix SHAs, then reconstructs cells with RAW git (`command git --no-pager show <fix>~1:<path>` = vuln, `<fix>:<path>` = safe) per CLAUDE.md, at a NEUTRAL path (path-leak memory).
4. Each fix commit → one corpus cell + `canonical.json` with a `provenance` block (`discovered_by: harvest`, `fix_sha`, `discovered_when: 2026-06-20`).

## Done-bar (the 8.10 reading, advisor-blessed)
"Real completion (none deferred but #12/#17)" for measurement-blocked items = **mechanism/harvest done + conformance-green on AVAILABLE cells + documented rate-pending** — NEVER a k≥3 recall-RATE claim this session (directive forbids rolling; project forbids single-run claims). S4=0-found is a documented gap, not a failure.
