fix(api): PostTemplatesTags queries database and begins transaction before team ownership check (tag enumeration oracle)

Abierto Apto para principiantes
#3,573 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
76/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Tranquilo
Stack tecnológico
go, postgres

Línea de trabajo

Comienza en packages/api/internal/handlers/template_tags.go, en PostTemplatesTags, y compara el orden de autorización con GetTemplatesTemplateIDTags y DeleteTemplatesTags. Después, inspecciona o añade el caso específico en packages/api/internal/handlers/template_tags_test.go y ejecuta las pruebas de API relevantes. Se considera terminado cuando las solicitudes no autorizadas devuelven 403 de forma coherente sin consultar el tag ni iniciar una transacción.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

Problem

In POST /templates/tags (packages/api/internal/handlers/template_tags.go), the control plane handler initiates a database transaction via a.sqlcDB.WithTx(ctx) and executes client.GetTemplateWithBuildByTag before validating whether the authenticated user's team owns the requested template (if aliasInfo.TeamID != team.ID).

This ordering defect causes two distinct issues:

  1. Tag Enumeration / Information Disclosure Oracle:
    When a user sends POST /templates/tags targeting a template owned by a different team:

    • If the requested tag does not exist on that template: GetTemplateWithBuildByTag returns sql.ErrNoRows, which triggers ErrTemplateNotFound, responding with 404 Not Found ("Template '<target>' with tag '<tag>' not found").
    • If the requested tag exists on that template: the query succeeds, and only afterwards at line 115 is aliasInfo.TeamID != team.ID checked, responding with 403 Forbidden ("You don't have access to sandbox template '%s'").
      An unauthorized tenant can therefore determine whether arbitrary private build tags (e.g., staging, v2.0.0-rc1, hotfix) exist on other teams' templates by probing the endpoint and observing the difference between HTTP 404 and HTTP 403.
  2. Unnecessary Database Load and Transaction Allocation:
    Every unauthorized or invalid tag request against another tenant's template allocates a Postgres transaction connection from the pool (WithTx), acquires read locks, executes queries, and then rolls back upon failure.

Root Cause

In packages/api/internal/handlers/template_tags.go:L75-L122, tag resolution and database transaction creation precede the team ownership authorization check:

// Current flow in template_tags.go:
aliasInfo, err := a.templateCache.ResolveAlias(ctx, templateID)
if err != nil { ... }

// BUG: Transaction started and DB queried BEFORE checking aliasInfo.TeamID == team.ID
txErr := a.sqlcDB.WithTx(ctx).Exec(func(queries *queries.Queries) error {
    build, err := queries.GetTemplateWithBuildByTag(ctx, ...)
    if err != nil {
        return ErrTemplateNotFound // Returns 404 to unauthorized caller if tag missing
    }
    ...
    if aliasInfo.TeamID != team.ID {
        return a.sendAPIStoreError(c, http.StatusForbidden, ...) // Returns 403 only if tag exists
    }
})

In contrast, peer handlers such as DeleteTemplatesTags (template_tags.go:L139) and GetTemplatesTemplateIDTags (template_tags.go:L21) enforce if aliasInfo.TeamID != team.ID immediately after alias resolution:

Handler Authorization Check Timing Tag Enumeration Vulnerable?
GET /templates/{templateID}/tags Immediate after ResolveAlias No
DELETE /templates/tags Immediate after ResolveAlias No
POST /templates/tags (Current) Deferred after GetTemplateWithBuildByTag DB query Yes (404 vs 403 Oracle)
POST /templates/tags (Expected) Immediate after ResolveAlias No (403 Forbidden)

Reproduction Steps

  1. Create a template template-A under team-1 with tag v1.0.0.
  2. Authenticate as an unrelated user team-2.
  3. Send POST /templates/tags targeting template-A with tag: "v9.9.9" (non-existent).
    • Observed: HTTP 404 Not Found ({"code": 404, "message": "Template 'template-A' with tag 'v9.9.9' not found"})
  4. Send POST /templates/tags targeting template-A with tag: "v1.0.0" (existing tag).
    • Observed: HTTP 403 Forbidden ({"code": 403, "message": "You don't have access to sandbox template 'template-A'"})
  5. Expected: Both requests must return HTTP 403 Forbidden without leaking metadata about tag existence.

Technical Context

  • File affected: packages/api/internal/handlers/template_tags.go
  • Subsystem: Control Plane API / Templates & Tags
  • Impact: Medium (Security/Privacy: cross-tenant metadata disclosure & unnecessary database transaction overhead)

Proposed Changes

# Change File(s) Affected Complexity
1 Move if aliasInfo.TeamID != team.ID check immediately after ResolveAlias before WithTx packages/api/internal/handlers/template_tags.go Trivial
2 Add unit test TestPostTemplatesTags_RejectsOtherTeamTemplate verifying 403 Forbidden packages/api/internal/handlers/template_tags_test.go Low
Lenguaje dominante
Go
Estrellas
1.6k
Forks
438
Métricas de merge de PR
Sin PR fusionados en 30 d

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de e2b-dev/runtime

Todos los issues de e2b-dev/runtime

Issues similares

Más issues de Go

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.