fix(core#2566): refuse concierge/agent set_workspace_secret self-writes on org root #2756
Reference in New Issue
Block a user
Delete Branch "fix/core2566-concierge-self-secret-write"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Adds a fail-closed guard in
SecretsHandler.Set(workspace-server) that refuses the org-root concierge'sset_workspace_secretcall when the target is the concierge's own workspace (kind='platform'). Returns 403 with structured codeCONCIERGE_SELF_WRITE_BLOCKED.Why
Live incident (2026-06-11 00:08Z) — concierge called
mcp__platform__mint_org_tokenthenmcp__platform__set_workspace_secretagainst its own workspace; the secret-change auto-restart killed the concierge mid-turn (EOF), the org root went offline, and operator hand-repair was required.This is a STRONGER defense than #2573 (auto-restart skip for kind='platform') and #2574 (approval gate for admin-token callers). It refuses the self-targeted write outright instead of just deferring the restart. Failures:
platformCONCIERGE_SELF_WRITE_BLOCKEDTest plan
TestSecretsSet_AdminTokenSelfWrite_Refused— admin-token + kind='platform' → 403, code set, no INSERT, no approval createdTestSecretsSet_AdminTokenOnOtherWorkspace_NotBlocked— admin-token + kind='workspace' → falls through to approval gate (202)TestSecretsSet_AdminTokenKindLookupError_FailsClosed— admin-token + DB error → 403 (no retry loop on a fundamentally-unsafe path)TestSecretsSet_SessionCookieCaller_NotBlocked— operator session → not blocked, writes through normallyTestSecretsSet_AdminToken_GatedByApproval(#2574) — updated to also mock the new kind lookup (guard runs before gate; non-platform targets pass through)internal/handlerspackage:go test ./internal/handlers/→ ok 23.9sgo vet ./internal/handlers/→ cleango build ./internal/handlers/→ cleanAudit
Refused writes emit a
secret.set.refusedaudit event withissue=core#2566andreason=concierge_self_write_blockedso security review can correlate with the 2026-06-11 incident signature.Scope
Set only. The DELETE path has the same restart-on-remove side effect (#2573) and could be guarded the same way; left for a follow-up ticket to keep this PR's diff focused on the reported incident.
Closes core#2566 (closes only the self-DoS finding; the approval-gate-applicability finding is owned by the existing #2574 fix).
APPROVED on head
650c1d1a.Security-focused 5-axis review:
conciergeSelfSecretWriteBlockedis scoped to admin-token callers and checks the target workspace kind before the approval gate/INSERT. Admin-token + kind=platformreturns 403 withCONCIERGE_SELF_WRITE_BLOCKED; regular workspaces fall through to #2574 approval gating; non-admin-token session/workspace callers do not hit the guard.secret.set.refusedwith workspace/key/reason/issue on the blocked path. Workspace-token and session callers are not overblocked becausecallerIsAdminTokenis a strict bool context check.set_workspace_secretincident path.CI/all-required is green on current head. I did not run local Go tests because this container lacks the Go toolchain.
/sop-ack
/sop-ack
Confirmed independent security 5-axis review on current head
650c1d1a649e648370bc468951106d2b0906f38d: fail-closed admin-token + platform-root Set guard, kind lookup failure blocks, regular workspace still goes to #2574 approval gate, session/workspace callers unaffected, no secret-value exposure, required CI green.Post-merge security audit for #2756 (head
650c1d1a649e648370bc468951106d2b0906f38d): CLEAN.The PR merged before I could post a formal second-review approval, so I am recording the independent security audit here. The implemented
conciergeSelfSecretWriteBlockedpath is invoked inSecretsHandler.Setbefore the #2574 approval gate and before anyworkspace_secretsINSERT. Admin-token caller + targetkind='platform'returns 403 withCONCIERGE_SELF_WRITE_BLOCKED; kind lookup errors also fail closed with 403, so the unsafe org-root self-write path cannot create an approval or persist a secret.Scope is appropriately narrow: the guard keys on
caller_is_admin_tokenonly. Session-cookie/human-operator and ordinary workspace-token callers bypass the new guard; admin-token writes to regular workspaces fall through to the existing approval gate (202). DELETE remains unchanged, which matches the stated Set-only scope with #2573 deferred.Security/privacy check: the diff adds no credential-shaped material; tests use placeholder values only. The refusal response/audit includes workspace id, key, reason, and issue, but not secret value. Required CI was green on the reviewed head (
CI / all-required, Platform Go, handlers Postgres, API smoke, peer visibility). I could not run local Go tests because this container has nogobinary.