Skip to content

Security fix: authenticate /api/feedback/[id] GET + PATCH endpoints #30

@weilies

Description

@weilies

Summary

The GET and PATCH handlers for /api/feedback/[id] were shipping without any authentication or tenant-isolation checks. Both handlers used createAdminClient() (bypasses RLS entirely), and the middleware explicitly skips all /api/ routes, leaving the endpoint fully open to any HTTP caller with a session UUID.

Detected by: Automated security review (Claude Code /security-review) on 2026-04-10.


Vulnerability Detail

Property Value
Endpoint GET /api/feedback/:id, PATCH /api/feedback/:id
Auth before fix None
Client used before fix createAdminClient() — RLS bypassed
Middleware protection None — middleware passes all /api/ routes through

GET exploit: Any caller with a known session UUID could retrieve all feedback items for that session, including outer_html (raw HTML of internal admin pages), css_classes, parent_chain, comment, and page paths — internal UI structure of the tenant's admin dashboard.

PATCH exploit: Any caller with a known session UUID could send {"status":"completed"} to irreversibly close feedback sessions belonging to any tenant.


Fix Applied

Both handlers now go through resolveApiContext(request) — the same auth middleware used by all other /api/ routes (e.g. /api/content-catalogs). This supports:

  • Mode A: App credential JWT (for integrations)
  • Mode B: Supabase user Bearer token + X-Tenant-Id header

After auth, both handlers explicitly verify session.tenant_id === auth.ctx.tenantId before returning data or mutating state, providing full tenant isolation even when called with a valid token from a different tenant.

The admin client is retained (required for admin-level reads), but it is now backed by application-layer tenant checks rather than running unauthenticated.


Files Changed

  • src/app/api/feedback/[id]/route.ts — added resolveApiContext auth + tenant check to GET and PATCH

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions