Repository navigation
fix(coderd): store chat ACL keys as canonical UUIDs - #31037
ibetitsmike wants to merge 3 commits into
Conversation
patchChatACL stored user and group IDs as the request spelled them. uuid.Parse accepts uppercase spellings, so the update passed validation, but RBAC matches ACL keys as canonical UUID strings: the share granted nothing, and a deleted role sent with another spelling left the stored entry in place. Rekey both role maps with canonicalACLRoles, as the MCP server config and organization skill ACLs do, and reject requests where two spellings name one principal.
|
@codex review
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 79865b4afc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Releases v2.34.0 through v2.38.0 stored chat ACL keys as the request spelled them. Requests are now rekeyed to canonical IDs, so no request could remove an entry stored under an uppercase key. Before applying a request, delete stored keys that spell a requested principal's ID in a noncanonical form.
|
@codex review
|
|
Codex Review: Didn't find any major issues. 🚀 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Seed uppercase user and group keys straight in the database. Check that a deleted request with the canonical or the uppercase spelling leaves no stored key, and that a read request leaves only the canonical keys, lets the user and a group member read the chat, and notifies the user again.
|
@codex review
|
|
Codex Review: Didn't find any major issues. Keep them coming! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
PATCH /api/v2/chats/{chat}/aclstored user and group IDs as the request spelled them.uuid.Parseaccepts uppercase spellings, so such a request passed validation and returned204, but RBAC matches ACL keys as canonical UUID strings: the share granted nothing, and adeletedrole sent with another spelling left the stored entry in place. This PR rekeys both role maps withcanonicalACLRoles, as the MCP server config and organization skill ACLs do, and returns400when two spellings name one principal.Releases v2.34.0 through v2.38.0 store keys as sent, so before it applies a request, the handler also deletes stored keys that spell a requested principal's ID in a noncanonical form: a
deletedrole then removes every spelling, and areadrole leaves one canonical entry. Principals that the request does not name keep their stored keys, since rekeying them would grant access that RBAC never enforced.Why it is safe: a canonical ID maps to itself, so requests with canonical IDs behave as before. The chat project ACL already canonicalizes its keys.
Red tests:
TestChatACLNoncanonicalIDsshares a chat with a user and a group by uppercase IDs, checks that the user and a group member can read it, then removes both by uppercase IDs and checks that they cannot. It then writes uppercase user and group keys straight to the database, as older servers stored them. Adeletedrequest with either spelling must leave no stored key, and areadrequest must leave only the canonical keys, let both readers in, and notify the user. Two newTestChatACLValidationcases send one user ID or one group ID in two spellings and expect a400. Onmain:With the rekey but without the cleanup (
79865b4afc9), each legacy case fails when run on its own:These tests also fail on seven
go test -overlaymutants. Each skips the rekey, the duplicate check, or the cleanup for users or for groups, or runs the cleanup after theoldChatsnapshot.Review focus: the maps are rekeyed in place after
acl.Validate, which still reports IDs that do not parse, so the role loops below read canonical keys. The cleanup runs before theoldChatsnapshot, so the share notification treats a user whose legacy entry granted nothing as newly added. Onmain, that user is not notified again.#31016 replaces those loops with
applyACLReadRoles. The two merge without conflicts and the merged loops read the rekeyed maps; whichever merges second will mergemainfirst.Validation:
go test ./coderd -run '^(TestChatACLValidation|TestChatACLNoncanonicalIDs)$' -count=1fails onmainand on79865b4afc9as above and passes here (9 tests with subtests). Also passing here:go test ./coderd -run '(?i)acl|mcp|skill' -count=1(65 with subtests),go test ./coderd -run '^(TestChatProjectSharing|TestChatSharingDisabled|TestListChatsSharedScope|TestSharedReaderStreamChat|TestChatFileDownloadURL)$' -count=1(22), andgo test ./enterprise/coderd -run '(?i)acl|mcp|skill|TestEnterpriseAuditLogs' -count=1(46). A local merge with #31016 passesgo test ./coderd -run '^(TestChatACLValidation|TestChatACLNoncanonicalIDs|TestChatACLSharingLifecycle|TestChatProjectSharing)$' -count=1(16 with subtests).go vet ./coderd/is clean on both, and the pre-commit hook passed (make gen, formatting, golangci-lint, slim build).