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

未关闭 适合新手
#3,573 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
2/5
预计耗时
1-3 小时
新手友好度
76/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
冷清
技术栈
go, postgres

调研方向

从 packages/api/internal/handlers/template_tags.go 中的 PostTemplatesTags 开始,将其授权顺序与 GetTemplatesTemplateIDTags 和 DeleteTemplatesTags 进行比较。然后检查或添加 packages/api/internal/handlers/template_tags_test.go 中针对该问题的用例,并运行相关的 API 测试。未授权请求能够一致地返回 403,且不会查询 tag 或启动事务,即表示完成。

由索引模型根据 Issue 内容生成。

描述

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
主要语言
Go
星标
1.6k
派生
438
PR 合并指标
30 天内没有已合并 PR

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

e2b-dev/runtime 的其他 Issue

查看 e2b-dev/runtime 的全部 Issue

相似的 Issue

更多 Go Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。