Thanks to visit codestin.com
Credit goes to github.com

Skip to content

support disabling X11 forwarding in the Coder agent SSH server #28948

Description

@blinkagent

Problem

Follow-up to #22275 / #24026, which added --block-reverse-port-forwarding and --block-local-port-forwarding to the Coder agent SSH server.

X11 forwarding remains unconditionally enabled. In agent/agentssh/x11.go, the callback is hardcoded:

// x11Callback is called when the client requests X11 forwarding.
func (*Server) x11Callback(_ ssh.Context, _ ssh.X11) bool {
	// Always allow.
	return true
}

Note the value receiver on *Server — the callback has no access to agentssh.Config at all, so there is currently no way to gate it.

This leaves open the same class of sandbox escape that #22275 addressed, and arguably a more direct one. With ssh -X / ssh -Y, the agent opens x11 channels back to the client's X server. Anything running inside the workspace — an AI agent or any other process that can read the session's Xauthority file and connect to DISPLAY — can then:

  • inject synthetic keystrokes and mouse events into the user's local desktop
  • capture the contents of any window on the user's local machine
  • read the local clipboard

Unlike ssh -R, this does not require the user to have deliberately set up a tunnel; it only requires X11 forwarding to be requested on the connection.

Why existing mitigations don't cover this

  • Agent Boundaries operate at the HTTP/HTTPS layer and do not intercept the X11 protocol.
  • CODER_BROWSER_ONLY=true blocks all SSH connections deployment-wide, which also prevents legitimate CLI/IDE access.
  • sshd_config in the workspace image has no effect — Coder uses its own embedded SSH server, not OpenSSH.
  • The new --block-reverse-port-forwarding / --block-local-port-forwarding flags gate tcpip-forward, direct-tcpip, and the streamlocal variants. They do not gate the x11-req request or the x11 channel type.

Proposed Solution

Mirror the pattern established in #24026:

  1. Add BlockX11Forwarding bool to agentssh.Config (agent/agentssh/agentssh.go).
  2. Add BlockX11Forwarding bool to agent.Options and thread it through in agent/agent.go.
  3. Add a CLI flag in cli/agent.go:
    • Flag: block-x11-forwarding
    • Env: CODER_AGENT_BLOCK_X11_FORWARDING
    • Default: false
    • Description: Block X11 forwarding through the SSH server (ssh -X, ssh -Y).
  4. Change x11Callback to a pointer receiver and return false with a logger.Warn when the option is set, so the x11-req is rejected at request time.
  5. Defensively gate the hasX11 branch in sessionHandler (agent/agentssh/agentssh.go ~L524) so DISPLAY is never injected into the session environment even if a request slips through.

As with #22275, ideally this is controllable at the template level (template admins disable X11 for AI agent templates while leaving it enabled for human developer templates), with a deployment-level flag as a fallback.

Use Case

Organizations running AI coding agents in Coder workspaces with process/network sandboxing need to prevent an agent inside the workspace from reaching back onto the connecting user's local desktop. Blocking ssh -R and ssh -L without also blocking X11 forwarding leaves the isolation incomplete.


Created on behalf of @ericpaulsen

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions