Missing access checks on caller-supplied video/space IDs (4 endpoints, PRs open)
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 25/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Estancado
- Stack tecnológico
- next.js, typescript
- Área
- api, authorization, security
Línea de trabajo
Revisa los PRs #2029–#2032 antes de empezar y, después, lee VideosPolicy.canView, getSpaceAccess, /api/analytics/route.ts y Analytics.tsx para entender las comprobaciones existentes. Se considera hecho cuando los cuatro puntos de entrada indicados aplican comprobaciones de acceso adecuadas y devuelven respuestas de not-found cuando se deniega el acceso, sin duplicar el trabajo ya cubierto por los PRs abiertos.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
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
- Lenguaje dominante
- Rust
- Estrellas
- 22.8k
- Forks
- 2k
- Merge medio
- 8 h 10 min
- PR fusionados (30 d)
- 83
Preparar el entorno
- Incluye un Dockerfile o un archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de CapSoftware/Cap
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
CapSoftware/Cap#2305 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
CapSoftware/Cap#1714 · 3 comentarios ·
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 3/5 1-2 días Aptitud para principiantes 64/100
CapSoftware/Cap#2360 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Linux: export and editor audio fail with EINVAL under comma-decimal locales (resampler-open)Abiertobug
Dificultad 3/5 1-2 días Aptitud para principiantes 78/100
CapSoftware/Cap#2359 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
[Feature Request] Editor media library + audio processing (speed & pitch for audio segments)Abierto
Dificultad 5/5 Más de una semana Aptitud para principiantes 35/100
CapSoftware/Cap#2357 · 1 comentario ·
Los mantenedores suelen responder en 1 día
Todos los issues de CapSoftware/Cap
Issues similares
-
area:casework bug criticality:p3 triage:needs-implementation
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
registrystack/registry-stack#1623 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
DioxusLabs/anyrender#98 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
leptos-rs/leptos#4885 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
longbridge/gpui-kit#3276 ·
Los mantenedores suelen responder en 1 día