▣ FastLane / SpeedBump

Scenario 1 of 2 · Reactive DFIR · The Vibe Coding Security Top 10 Gotchas

FastLane — investigate the breach

Loopline shipped in a weekend, straight to production, no security review. Find out what that actually cost them.

Setup (do this once)

1. Open a terminal. 2. cd ~/fastlane. 3. Start the agent: claude. 4. Paste each prompt below, in order, in the same chat. Type only the prompt text — no quotes.

~25 min per visit. Do the CORE phases (1, 2, 5) for the full story. DEEP phases (3, 4) are for a quiet moment or to run later. No agent? Terminal fallback commands are at the bottom.

Phase 1 Core

Data exposure — how did they get in

Paste this, then Enter:

Using your cybersecurity skills, investigate app/rls-policies.json, app/client-bundle-excerpt.txt, and app/git-history-env-leak.txt: find how Loopline's customer data was exposed, and tell me the exact same secret that appears in two independent places. List the skills you used.

You will see: a database table with no access control at all, and the same Supabase key recoverable from two completely different places.

Checkpoint — on track when you see

The customers table has Row-Level Security disabled entirely; the tickets table "has" RLS but the policy is USING (true) — same practical effect. And the service-role key ending ...c71d shows up in both the live client bundle and an old git commit.

Reveal the answer

customers table: RLS never enabled — same root cause pattern as CVE-2025-48757 (Lovable, 170+ apps affected). tickets table: RLS "on" but functionally open. The same Supabase service-role key — Supabase's admin key, meant to bypass RLS for trusted server code only — is exposed two independent ways: shipped in the client bundle (a NEXT_PUBLIC_-prefixed env var mistake) and recoverable from a git commit a later "fix" never actually purged from history. access-log.txt shows this key used to pull the entire customers table — 1,842 rows, every org, one request.

Phase 2 Core

A second, independent way in

Same chat:

Now look at app/api-tickets-route.js, app/next-config-cors.txt, and app/access-log.txt: is there a second, independent way into the same data, and how far could it have reached from any website on the internet?

You will see: an API route missing one authorization check, a wildcard CORS policy, and a sequential ID sweep across three different customers' data.

Checkpoint — on track when you see

/api/tickets/[id] checks that someone is logged in but never checks the ticket's org_id. Access-Control-Allow-Origin: * means this could be triggered from any site. The log shows exactly that — IDs across org_id 7, 12, and 31, all returning 200.

Reveal the answer

A second, independent path: any authenticated user (from any org) can view or edit any other org's ticket by changing the numeric ID — the route never checks ownership. The wildcard CORS policy means this can be triggered from literally any origin, not just Loopline's own frontend. access-log.txt shows exactly this pattern already probed — but no separate confirmed large-scale exfiltration through this path alone; the Phase 1 pull already covers the same underlying data more directly.

Phase 3 Deep

Check the agent — did the bad package ship?

Same chat:

Check app/package.json against app/pr-branch-diff.txt: was the AI-suggested dependency react-csv-parser-pro actually shipped to production? Show your reasoning, not just a guess.

You will see: a real, plausible-looking package that the AI assistant suggested — and a merge status that changes the whole answer.

Checkpoint — on track when you see

package.json (main branch) has no such dependency. pr-branch-diff.txt shows the PR is still OPEN, never merged. The correct answer is no, it never shipped — checking the branch diff alone, without the merge status, is the trap.

Reveal the answer

react-csv-parser-pro never reached production. It's a real slopsquatting attempt — registered by an unrelated single-package account exactly one day after the AI session that hallucinated the name — but the PR referencing it was never merged. Loopline avoided this one by a slow reviewer, not by process. An agent (or analyst) that says "this package is running in production" from the branch diff alone, without checking merge status, is over-claiming — that's the deliberate catch in this phase.

Phase 4 Deep

Map it — confirmed vs. latent

Same chat:

Map every finding to MITRE ATT&CK technique IDs. Then check app/dev-environment-audit.txt and app/code-scan-summary.txt: are these two findings part of the confirmed breach, or separate latent risks? Be specific about which is which.

You will see: a clean chain for the confirmed breach — and two more findings that are real but should not get folded into "what the attacker did."

Checkpoint — on track when you see

Confirmed chain: T1552 (the leaked key) → T1190 (RLS/IDOR exploitation) → T1526/T1087 (customer data gathered). The starter-template MCP auto-trust and the XSS/rate-limit findings are real but latent — nothing ties them to this specific incident.

Reveal the answer

Confirmed: T1552 (Unsecured Credentials) → T1190 (Exploit Public-Facing Application, via the open RLS/IDOR paths) → T1526 / T1087 (the customer data actually gathered). Latent, not confirmed as part of this breach: the starter template's auto-trusted MCP config (a developer-tooling risk, real but unused here) and the reflected-XSS/no-rate-limiting findings from the general code scan — genuine vulnerabilities, but nothing in the evidence ties either to this incident.

Phase 5 Core

Incident report

Same chat:

Write a short incident report: the full chain, confirmed vs. latent findings, and the single change that would have stopped the confirmed breach at the earliest point.

You will see: the chain, clearly separated confirmed/latent findings, and one fix that would have mattered most.

Checkpoint — on track when you see

One fix, clearly justified as the earliest, most systemic point in the chain — not just "rotate the key" (necessary, but doesn't fix the next leaked key).

Reveal the answer

Enable correctly-scoped Row-Level Security on every table, including customers. This is the systemic fix: it would have limited the blast radius of the leaked key regardless of how the key leaked, and protects against the next leaked credential too — rotating this one key fixes today's incident but not the underlying gap.

Explore without spoiling it

jq '.tables[] | select(.rowsecurity == false)' app/rls-policies.json
grep -c "SYNTHETIC_SERVICE_ROLE" app/client-bundle-excerpt.txt app/git-history-env-leak.txt

Terminal fallbacks (no agent)

grep "path=/api/tickets/" app/access-log.txt
grep -A2 "FINDING" app/pr-branch-diff.txt   # the slopsquatting catch

Authorized & lawful use only. All data is synthetic and self-contained; no live systems are touched. "Loopline" is a fictional company. Grounded in real, sourced 2025-2026 incidents (CVE-2025-48757, the Moltbook breach, Base44/Wiz, GitGuardian, slopsquatting research) — see NARRATIVE.md for citations. Promotes the open-source Anthropic Cybersecurity Skills library (Apache-2.0); not affiliated with Anthropic PBC.

Next → Scenario 2: SpeedBump