Skip to content

fix(metadata): enforce visibility filter in list and get - #72

Merged
SlavaKuntsov merged 6 commits into
mainfrom
fix/issue-44-visibility-filter
Sep 15, 2026
Merged

SlavaKuntsov merged 6 commits into
mainfrom
fix/issue-44-visibility-filter

Conversation

@SlavaKuntsov

Copy link
Copy Markdown
Owner

Closes #44

Summary

P0 security hotfix (phase:16): private video UUIDs leaked through the public metadata feed and direct-ID reads, closing the CRITICAL data-plane bypass chain.

  • metadata List now filters WHERE visibility='public' OR owner_id=$viewer — anonymous users and other users no longer see private/unlisted video IDs; owners see their own videos.
  • metadata Get returns 403 for a private video under a non-owner (and anonymous); unlisted stays reachable by direct link. Internal endpoints (/internal/videos/{id}, VOD mapping) are unchanged for transcoder/gateway HLSAuth.
  • Identity on public reads comes from a metadata-validated JWT, not the X-User-ID header: metadata got its own OptionalAuth middleware (the metadata port is published on 0.0.0.0, so a header-based design was forgeable). Refresh tokens are rejected (type: access check, same as mandatory auth).
  • gateway: public metadata GET routes are wrapped in OptionalAuth — client-supplied X-User-ID is stripped, a valid Bearer is forwarded, an invalid/expired token degrades to anonymous (public feed no longer 401s on a stale frontend token).
  • Swagger regenerated (Get documents 403).

Acceptance criteria (issue #44)

  • Приватное видео отсутствует в ленте (anonymous и чужой юзер)
  • 403 по прямому ID под чужим юзером (и anonymous)
  • Unlisted — не в List, но доступен по ссылке
  • Internal-эндпоинты работают как раньше (transcoder, HLS)

Verification

  • make lint-go — 0 issues (metadata, gateway, upload)
  • make test-go — all pass; new regression tests: TestListVisibilityFilter, TestGetVisibility (incl. forged-X-User-ID and refresh-token cases), gateway TestOptionalAuth* ×4
  • make swagger — metadata docs regenerated
  • gofmt clean
  • make e2e — not run in this session (docker stack not started)

Review cycle

Independent review + re-review (2 iterations). Fixed during review: forgeable X-User-ID trust boundary (→ metadata-side JWT), missing OptionalAuth tests, 401 regression for expired tokens on public reads, refresh-token-as-identity.

Remaining risks

  • Existence oracle: 403 (private, existing) vs 404 (nonexistent) — kept per ticket wording ("403/404 для private не-владельцу").
  • Pre-existing dev fallback (out of scope): /internal/* metadata endpoints are open when INTERNAL_TOKEN is empty.

@SlavaKuntsov SlavaKuntsov self-assigned this Sep 15, 2026
@SlavaKuntsov
SlavaKuntsov merged commit 8f4c26c into main Sep 15, 2026
4 checks passed
@SlavaKuntsov
SlavaKuntsov deleted the fix/issue-44-visibility-filter branch September 17, 2026 18:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

P0 metadata: enforce visibility filter in List and Get

1 participant