SSH agent forwarding hangs in devcontainers on Windows (fs.readFileSync blocks on named pipe)

Where does the bug appear (feature/product)?

Somewhere else…

Describe the Bug

SSH agent forwarding into Docker devcontainers on Windows hangs indefinitely. Running ssh-add -l inside the container never returns — it blocks forever with no output and no error.

The host-side SSH agent works correctly: keys are loaded (ssh-add -l works in PowerShell), and SSH connections succeed from the host. The Cursor logs confirm the forwarding is detected and set up:

Windows detected: using OpenSSH agent at \\.\pipe\openssh-ssh-agent
Forwarding SSH agent \\.\pipe\openssh-ssh-agent socket
[ssh_auth_socket] created socket server in container and bound forwarder to it
====socketForward=success====

On the first client connection from inside the container, the log shows:

handleClient stderr: Connection established 0

Then complete silence. No error, no data relayed, no timeout. The forwarder process is frozen.

Root cause: The forwarder process that bridges the container socket to the host’s SSH agent has a function (createLocalSocketConnection) that, before connecting to the local socket, passes the path to another function (parseWindowsAssuanSocket) which calls fs.readFileSync() on it. This is intended for GPG Assuan socket files (regular text files containing connection info), but on Windows the SSH agent path is \\.\pipe\openssh-ssh-agent — a named pipe, not a regular file. Calling readFileSync on a named pipe opens a connection and blocks waiting for the pipe server to send data. Since the SSH agent expects the client to speak first, this deadlocks. Because readFileSync is synchronous, it freezes the entire Node.js event loop of the forwarder, and no data ever flows through.

The fix is to skip the Assuan socket file parsing for paths that are Windows named pipes (matching \\.\pipe\*) and go straight to net.createConnection(), which handles named pipes correctly.

After applying this fix locally, SSH agent forwarding works perfectly — ssh-add -l shows the host keys and SSH connections succeed from inside the container.

Steps to Reproduce

  1. Use Windows 11 with the built-in OpenSSH agent service running (Set-Service ssh-agent -StartupType Automatic; Start-Service ssh-agent)
  2. Load keys into the agent (e.g. via KeePassXC or ssh-add)
  3. Verify ssh-add -l works in PowerShell on the host
  4. Open a Docker devcontainer in Cursor
  5. Open a terminal in the container
  6. Run ssh-add -l
  7. Result: Hangs forever (no output, no error, no timeout)

Standalone reproduction of the underlying issue (standard Node.js, no Cursor code — run on any Windows machine with the OpenSSH agent service running):

node -e "require('fs').readFileSync('//./pipe/openssh-ssh-agent')"

This hangs forever, demonstrating that fs.readFileSync deadlocks on the SSH agent named pipe.

Expected Behavior

ssh-add -l inside the devcontainer should list keys from the host’s SSH agent. SSH connections from the container should authenticate using the forwarded agent.

Operating System

Windows 10/11

Version Information

Version: 2.4.31 (user setup)
VSCode Version: 1.105.1
Commit: 3578107fdf149b00059ddad37048220e41681000
Date: 2026-02-08T07:42:24.999Z
Build Type: Stable
Release Track: Default
Electron: 39.2.7
Chromium: 142.0.7444.235
Node.js: 22.21.1
V8: 14.2.231.21-electron.0
OS: Windows_NT x64 10.0.26200

Extension: anysphere.remote-containers 1.0.32
Docker Desktop: latest (WSL2 backend)
OpenSSH: OpenSSH_for_Windows_10.0p2
SSH agent: Windows OpenSSH agent service

Additional Information

This bug was debugged with the help of Claude (Anthropic) running via Claude Code on the Windows host. The process was:

  1. Verified the Windows OpenSSH agent worked on the host (ssh-add -l showed keys, SSH to remote server succeeded).
  2. Inspected the container-side relay process — it was running and accepting connections, but returning no data.
  3. Checked the Cursor Dev Containers log at %APPDATA%\Cursor\logs\...\exthost\anysphere.remote-containers\Remote - Dev Containers.log, which showed the forwarder spawning successfully with \\.\pipe\openssh-ssh-agent as the local socket argument.
  4. Claude read the locally-installed file %USERPROFILE%\.cursor\extensions\anysphere.remote-containers-1.0.32\dist\scripts\forwarder.js on my machine to trace the code path. The function names referenced in this report (createLocalSocketConnection, parseWindowsAssuanSocket) were identified by Claude from this shipped JavaScript file. No decompilation or reverse engineering tools were used — the file is distributed as readable (minified) JavaScript.
  5. Claude identified that parseWindowsAssuanSocket calls fs.readFileSync on whatever socket path it receives, and hypothesized this would deadlock on a Windows named pipe.
  6. Confirmed the hypothesis with the standalone Node.js reproduction above — fs.readFileSync on the SSH agent named pipe hangs indefinitely.
  7. Patched the local extension file to skip the Assuan check for named pipe paths, reloaded Cursor, and verified ssh-add -l and SSH connections work from inside the container.

Does this stop you from using Cursor

No - Cursor works, but with this issue

Hey, thanks for the report, and especially for the root cause analysis. It really helps.

The bug is confirmed: fs.readFileSync on a Windows named pipe does indeed deadlock. The team is aware of the SSH agent forwarding issues in devcontainers on Windows. I shared the details from your analysis with them, specifically the parseWindowsAssuanSocket logic and the named pipe path check.

For now, your local patch, skipping the Assuan check for \\.\pipe\* paths, is a solid workaround.

I’ll post an update here once the fix makes it into a release.

1 Like

This topic was automatically closed 22 days after the last reply. New replies are no longer allowed.