Missing access checks on caller-supplied video/space IDs (4 endpoints, PRs open)
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 25/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Ferma
- Stack tecnologico
- next.js, typescript
- Ambito
- api, authorization, security
Direzione di ricerca
Esamina le PR #2029–#2032 prima di iniziare, poi leggi VideosPolicy.canView, getSpaceAccess, /api/analytics/route.ts e Analytics.tsx per comprendere i controlli esistenti. Il lavoro è completato quando i quattro punti di ingresso elencati applicano controlli di accesso appropriati e restituiscono risposte not-found in caso di diniego, senza duplicare il lavoro già coperto dalle PR aperte.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
While working on #1982 I audited every entry point in apps/web that accepts a caller-supplied resource ID, since that advisory looked like an instance of a pattern rather than a one-off. It was — I found four, and opened a PR for each.
The pattern
Cap has a solid access-control primitive in VideosPolicy.canView, and most code uses it. The failures all have the same shape: a second entry point to the same data that skips the check. Server actions are the main way this happens, because a "use server" function is independently callable by any client and does not inherit whatever gating its usual API route does.
What I found
| PR | Entry point | State before | Impact |
|---|---|---|---|
| #2029 | newComment action |
authenticated only | write comments/reactions into anyone's private video, notifying the owner |
| #2030 | getVideoAnalytics action |
no auth at all | read view counts of any private video |
| #2031 | getSpaceVideoIds / getFolderVideoIds |
authenticated only | enumerate video IDs in spaces of orgs you aren't in |
| #2032 | /api/video/transcribe/status |
authenticated only | read transcription status of anyone's private video |
Two are worth calling out specifically:
#2030 is the sharpest. /api/analytics/route.ts does gate on canView, with a comment stating it exists so private view counts aren't disclosed. But getVideoAnalytics is a server action with zero auth of any kind — no getCurrentUser, no policy — and a "use client" component (Analytics.tsx) already calls it directly. The route's protection is bypassable by calling the action the same way the app's own client code does.
#2031 leaks IDs, which are the key to everything else. Video IDs are what /s/{videoId} and the other video endpoints take, so enumerating a private space's ID set is useful to an attacker even before any per-video check runs.
Sweep result
After these four, I re-swept: no remaining videoId-taking server action or API route in apps/web lacks an access check. Two files still show up in a naive grep but are fine on inspection — /api/notifications takes no ID and only returns the caller's own rows, and /api/tools/loom-download takes a Loom video ID, not a Cap resource.
Notes on the fixes
- Every fix reuses an existing primitive (
VideosPolicy.canView, orgetSpaceAccessfor the space paths) rather than introducing new logic, so they inherit the full existing model — owner, org, space, public, password, email-domain restrictions. - For #2031 I used
getSpaceAccessand notrequireSpaceManager: these are read paths, and requiring manager would have locked out ordinary members. - Denials return "not found" rather than "denied" throughout, so none of them become an oracle for which IDs exist.
- Each PR is 1–2 files. They're independent and can be merged in any order.
Happy to consolidate them into a single PR if you'd prefer to review it that way.
cc @richiemcilroy
- Lingua principale
- Rust
- Stelle
- 22.5k
- Fork
- 1.9k
- Merge medio
- 7h 43m
- PR unite (30g)
- 80
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di CapSoftware/Cap
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
CapSoftware/Cap#2305 · 2 commenti ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
CapSoftware/Cap#1714 · 3 commenti ·
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 45/100
CapSoftware/Cap#2340 · 1 commento ·
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 45/100
CapSoftware/Cap#2339 · 1 commento ·
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 58/100
CapSoftware/Cap#2329 · 2 commenti ·
Tutte le issue di CapSoftware/Cap
Issue simili
-
bug github_actions
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
registrystack/registry-stack#1393 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
longbridge/gpui-kit#3223 ·
-
bug engine
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
rocky-data/rocky#2181 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
oasisprotocol/oasis-sdk#2523 ·
-
[indexer] [QA] Add a focused test for the new NonRetryableError / assertSocketAlive() behavior. Apertabot:ai-assisted component:indexer QA-roadmap status:untriaged
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
midnightntwrk/midnight-indexer#1557 ·