fix(security): C1 — auth-gate GET /workspaces + middleware test coverage (C4/C8/C10/C11) - #99
Merged
Merged
Conversation
…iddleware tests Security Auditor confirmed C1 (GET /workspaces) exposes workspace topology without any authentication. The endpoint was intentionally left open for the canvas browser frontend; this PR closes that gap. Router change: - Move GET /workspaces from the bare root router into the wsAdmin AdminAuth group alongside POST /workspaces and DELETE /workspaces/:id. - AdminAuth uses the same fail-open bootstrap contract as all other auth gates: fresh installs (no live tokens) pass through; once any workspace has registered with a token, a valid bearer is required. Status of findings C2–C11 (documented here for audit trail): - C2 POST /workspaces/:id/activity → already in wsAuth group (Cycle 5) - C3 POST /workspaces/:id/delegations/record → already in wsAuth group (Cycle 5) - C4 POST /workspaces/:id/delegations/:id/update → already in wsAuth group (Cycle 5) - C5 GET /workspaces/:id/delegations → already in wsAuth group (Cycle 5) - C7 GET /workspaces/:id/memories → already in wsAuth group (Cycle 5) - C8 POST /workspaces/:id/memories → already in wsAuth group (Cycle 5) - C9 POST /workspaces/:id/delegate → already in wsAuth group (Cycle 5) - C10 GET /admin/secrets → already in adminAuth group (Cycle 7) - C11 POST+DELETE /admin/secrets → already in adminAuth group (Cycle 7) Tests (platform/internal/middleware/wsauth_middleware_test.go — 13 new): WorkspaceAuth: - fail-open when workspace has no tokens (bootstrap path) - C4: no bearer on /delegations/:id/update → 401 - C8: no bearer on /memories POST → 401 - invalid bearer → 401 - cross-workspace token replay → 401 - valid bearer for correct workspace → 200 AdminAuth: - fail-open when no tokens exist globally (fresh install) - C10: no bearer on GET /admin/secrets → 401 - C11: no bearer on POST /admin/secrets → 401 - C11: no bearer on DELETE /admin/secrets/:key → 401 - valid bearer → 200 - invalid bearer → 401 Note: did NOT touch DELETE /admin/secrets in production — no destructive calls to live secrets endpoints were made during this work. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
C1 fix (#99) moved GET /workspaces behind AdminAuth. Three late-script calls that run after tokens exist now include Authorization headers; the post-delete-all call stays anonymous since revoked tokens trigger the no-live-token fail-open path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… gate Soft-delete leaves workspace_auth_tokens rows alive, so HasAnyLiveTokenGlobal stays non-zero and admin-auth 401s an unauth GET /workspaces. The assertion was verifying deletion, not auth; the bundle round-trip below still covers the deletion path end-to-end. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This was referenced Apr 15, 2026
Closed
HongmingWang-Rabbit
pushed a commit
that referenced
this pull request
Apr 15, 2026
#167) PR #167 gated /events and /bundles/export/:id behind AdminAuth. The e2e script's 3 calls to these routes were unauthenticated and broke when the runner picked them up for the first time on PR #186 (self-hosted runner migration). Same admin-gate contract, same fix pattern as the #99/#110 e2e hotfixes. POST /bundles/import is left unauthenticated because by that point in the script both workspaces have been deleted and #110 revoked their tokens, so HasAnyLiveTokenGlobal=0 and AdminAuth fails-open. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
HongmingWang-Rabbit
pushed a commit
that referenced
this pull request
Apr 15, 2026
…ht sweep Captures ~27 PRs merged across both repos this session: security hardening cluster (#94/#99/#106/#110/#119/#162/#155/#167/#185/#200/#203/ #209/#233), data-integrity fixes (#212/#224/#236), CI runner migration (#186), platform/scheduler reliability (#95/#149/#207/#206), workspace runtime features (#205/#208/#198/#216/#225/#235/#231), code-review follow-ups (#228/#232). Updated counts: 816 Go (+70), 1180 Python (+40), 453 vitest (unchanged — UI/a11y patches), 97 jest (unchanged). CLAUDE.md additions: - Idle Loop section (#205) under Architectural Patterns - Admin auth middleware variants section linking docs/runbooks/admin-auth.md - Migration runner section explaining the .down.sql filter (#212) - Per-route auth notes in the API table (PATCH field-whitelist, CanvasOrBearer on PUT /canvas/viewport, AdminAuth on bundles/events/templates-import/ approvals-pending/admin-liveness) - Database section updated with workspace_auth_tokens auto-revoke (#110), scheduler.error_detail surfacing (#206), workspace_schedules.last_status 'skipped' state (#207) PLAN.md additions: - New Recently launched (overnight sweep) section with full PR/issue index - Phase status updated (B–G now complete, H partial) - Live infrastructure deltas (migration fix, token rotation, legal pages) - Outstanding items consolidated Edit-history file expanded from the tick-9 stub to a full session record covering malware cleanup, CI runner migration, security cluster, data integrity, infra/feature/code-review batches, and outstanding user actions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
molecule-ai Bot
pushed a commit
that referenced
this pull request
Apr 21, 2026
C1 fix (#99) moved GET /workspaces behind AdminAuth. Three late-script calls that run after tokens exist now include Authorization headers; the post-delete-all call stays anonymous since revoked tokens trigger the no-live-token fail-open path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
molecule-ai Bot
pushed a commit
that referenced
this pull request
Apr 21, 2026
… gate Soft-delete leaves workspace_auth_tokens rows alive, so HasAnyLiveTokenGlobal stays non-zero and admin-auth 401s an unauth GET /workspaces. The assertion was verifying deletion, not auth; the bundle round-trip below still covers the deletion path end-to-end. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
molecule-ai Bot
pushed a commit
that referenced
this pull request
Apr 21, 2026
fix(security): C1 — auth-gate GET /workspaces + middleware test coverage (C4/C8/C10/C11)
molecule-ai Bot
pushed a commit
that referenced
this pull request
Apr 21, 2026
#167) PR #167 gated /events and /bundles/export/:id behind AdminAuth. The e2e script's 3 calls to these routes were unauthenticated and broke when the runner picked them up for the first time on PR #186 (self-hosted runner migration). Same admin-gate contract, same fix pattern as the #99/#110 e2e hotfixes. POST /bundles/import is left unauthenticated because by that point in the script both workspaces have been deleted and #110 revoked their tokens, so HasAnyLiveTokenGlobal=0 and AdminAuth fails-open. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
molecule-ai Bot
pushed a commit
that referenced
this pull request
Apr 21, 2026
…ht sweep Captures ~27 PRs merged across both repos this session: security hardening cluster (#94/#99/#106/#110/#119/#162/#155/#167/#185/#200/#203/ #209/#233), data-integrity fixes (#212/#224/#236), CI runner migration (#186), platform/scheduler reliability (#95/#149/#207/#206), workspace runtime features (#205/#208/#198/#216/#225/#235/#231), code-review follow-ups (#228/#232). Updated counts: 816 Go (+70), 1180 Python (+40), 453 vitest (unchanged — UI/a11y patches), 97 jest (unchanged). CLAUDE.md additions: - Idle Loop section (#205) under Architectural Patterns - Admin auth middleware variants section linking docs/runbooks/admin-auth.md - Migration runner section explaining the .down.sql filter (#212) - Per-route auth notes in the API table (PATCH field-whitelist, CanvasOrBearer on PUT /canvas/viewport, AdminAuth on bundles/events/templates-import/ approvals-pending/admin-liveness) - Database section updated with workspace_auth_tokens auto-revoke (#110), scheduler.error_detail surfacing (#206), workspace_schedules.last_status 'skipped' state (#207) PLAN.md additions: - New Recently launched (overnight sweep) section with full PR/issue index - Phase status updated (B–G now complete, H partial) - Live infrastructure deltas (migration fix, token rotation, legal pages) - Outstanding items consolidated Edit-history file expanded from the tick-9 stub to a full session record covering malware cleanup, CI runner migration, security cluster, data integrity, infra/feature/code-review batches, and outstanding user actions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
GET /workspaceswas the only completely unprotected endpoint in the findings table. Moved it into thewsAdminAdminAuth group (same middleware already guardingPOST /workspacesandDELETE /workspaces/:id).WorkspaceAuth(Cycle 5) orAdminAuth(Cycle 7). This PR documents their status and adds missing test coverage.platform/internal/middleware/wsauth_middleware_test.go— 13 tests covering WorkspaceAuth and AdminAuth for the exact C4/C8/C10/C11 attack vectors confirmed by the Security Auditor.Endpoints protected by this PR
/workspaces/workspaces/:id/activity/workspaces/:id/delegations/record/workspaces/:id/delegations/:id/update/workspaces/:id/delegations/workspaces/:id/memories/workspaces/:id/memories/workspaces/:id/delegate/admin/secrets/admin/secretsAuth contract (fail-open bootstrap)
Both
WorkspaceAuthandAdminAuthuse the Phase 30 lazy-bootstrap contract:Authorization: Bearer <token>is mandatory. Missing or invalid →401 Unauthorized.Test plan
go test ./internal/middleware/— 16/16 pass (13 new + 3 existing)go test ./...— all packages pass, zero failuresDELETE /admin/secretsagainst production secrets🤖 Generated with Claude Code