Skip to content

feat(coderd): enforce DLP policy at workspace traffic gates#25537

Closed
jscottmiller wants to merge 2 commits into
feat/dlp-policy-plumbingfrom
feat/dlp-policy-enforcement
Closed

feat(coderd): enforce DLP policy at workspace traffic gates#25537
jscottmiller wants to merge 2 commits into
feat/dlp-policy-plumbingfrom
feat/dlp-policy-enforcement

Conversation

@jscottmiller

Copy link
Copy Markdown
Contributor

Enforces DLP policies at all workspace data-plane gates. Builds on top of #25536 which wires and persists the policy.

  • SSH: deny ConnectToCoordinateAndStartReporting when ssh_access is false.
  • Desktop (tailnet): deny AuthorizeTunnel via the same ssh_access flag.
  • Web terminal: deny token issuance when web_terminal_access is false.
  • Port forwarding: deny token issuance when port_forwarding_access is false.
  • Workspace apps: deny token issuance when slug is not in allowed_applications.
  • Consolidates all app/PTY/port DLP checks into DBTokenProvider.Issue, which is the single enforcement point for both primary and workspace-proxy paths (fixes nil-panic on proxy).

Depends on #25536

Note

Generated by Coder Agents on behalf of @jscottmiller

Adds a new coderd/dlppolicy package whose ForAgent helper loads the
agent's persisted DLP policy under dbauthz.AsSystemRestricted. Callers
have already authorized the request against the workspace; the policy
lookup is a follow-on system-internal read.

Four enforcement gates are wired in:

  * CLI peering. workspaceAgentClientCoordinate returns 403 when
    ssh_access is false. This is the single chokepoint for coder CLI
    peering, so the toggle is coarse and blocks ssh, port-forward, cp,
    and speedtest together.
  * Web terminal. workspaceapps.Server.workspaceAgentPTY returns 403
    before the WebSocket upgrade when web_terminal_access is false.
  * Dashboard Ports tab. workspaceapps.Server.proxyWorkspaceApp returns
    a "Blocked by workspace policy" HTML page when port_forwarding_access
    is false and the request resolves to a port view.
  * Dashboard app proxy. The same handler returns the same HTML page
    when the resolved app slug is not in allowed_applications.

User-facing strings say "workspace policy" and never include the
policy name; internal names and log fields keep "DLP". Browser-facing
denials render site.RenderStaticErrorPage; CLI and JSON callers get
codersdk.Response 403s.

The fix folded in here (originally adbdbfe) reads slugOrPort and
isPort from the signed appToken instead of app.PortInfo() /
app.AppSlugOrPort, because path-based app routing passes an empty
appurl.ApplicationURL into proxyWorkspaceApp and the parsed values are
not reliable on that path.
- Add DLP ssh_access check in rbacAuthorizer.AuthorizeTunnel to gate
  Coder Desktop connections (same data plane as CLI SSH).
- Move app/PTY DLP enforcement from inline proxy.go gates into
  DBTokenProvider.Issue, which is the single source of truth for both
  primary and workspace-proxy token paths.
- Remove Database field from workspaceapps.ServerOptions (no longer
  needed on proxy, fixes nil-panic).
@github-actions github-actions Bot locked and limited conversation to collaborators May 20, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant