fix(chats): enforce desktop connect authorization (#23073)

### Motivation

- The desktop watch handler opened a VNC stream using the chat's
workspace ID while only relying on workspace read permissions, allowing
read-only users to escalate to interactive desktop access.
- Enforce connect-level authorization so only actors with
`ActionApplicationConnect` or `ActionSSH` can open the desktop stream.

### Description

- Added an explicit workspace lookup in `watchChatDesktop` using
`GetWorkspaceByID` to obtain a workspace object for authorization.
- Require the requester to be authorized for either
`policy.ActionApplicationConnect` or `policy.ActionSSH` on the workspace
before proceeding to locate agents or connect to the VNC stream, and
return `403 Forbidden` when neither permission is present.
- The change is minimal and localized to `coderd/chats.go` and does not
alter other code paths or behavior when the requester has the necessary
connect permissions.

### Testing

- Ran `gofmt -w coderd/chats.go` to format the modified file, which
succeeded.
- Attempted to run the unit test `TestWatchChatDesktop/NoWorkspace` via
`go test` in this environment but the test run did not complete within
the environment constraints and did not produce a full pass result.
- Attempted to run the repository pre-commit/gen steps but they could
not complete due to missing developer tooling and services in this
environment (e.g. `sqlc`, `mockgen`, `protoc` plugins and test services
like Docker/Postgres), so full pre-commit validation did not finish
here.
- Code review and static validation confirm the added authorization
check properly prevents read-only access from opening the desktop VNC
stream.

------
[Codex
Task](https://chatgpt.com/codex/tasks/task_b_69b46a4ac5c4832ea9d330aeba43c32d)
This commit is contained in:
Thomas Kosiewski
2026-03-14 17:53:05 +01:00
committed by GitHub
parent ddd1e86a90
commit 3f7f25b3ee
+13
View File
@@ -764,6 +764,19 @@ func (api *API) watchChatDesktop(rw http.ResponseWriter, r *http.Request) {
return
}
workspace, err := api.Database.GetWorkspaceByID(ctx, chat.WorkspaceID.UUID)
if err != nil {
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
Message: "Chat workspace not found.",
})
return
}
if !api.Authorize(r, policy.ActionApplicationConnect, workspace) &&
!api.Authorize(r, policy.ActionSSH, workspace) {
httpapi.Forbidden(rw)
return
}
agents, err := api.Database.GetWorkspaceAgentsInLatestBuildByWorkspaceID(ctx, chat.WorkspaceID.UUID)
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{