Skip to content

Harden third-party dependency boundaries - #71

Merged
rthellend merged 5 commits into
mainfrom
security-dependency-remediations
Oct 25, 2026
Merged

rthellend merged 5 commits into
mainfrom
security-dependency-remediations

Conversation

@rthellend

@rthellend rthellend commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

This PR upgrades github.com/pkg/sftp to v1.13.12, adds RSA SHA-2 signing support for user certificates and forwarded agents, rejects deprecated SHA-1/DSA CA signatures, and hardens sshterm and sshterm-server against terminal, auto-completion, and proxy edge cases.

Changes

1. SFTP Client (github.com/pkg/sftp v1.13.12)

  • Upgrade github.com/pkg/sftp to v1.13.12: Fixes upstream slice bounds panics on truncated/malformed server packets and Client.RemoveAll directory symlink traversal.

2. SSH Client, Certificates, & Forwarded Agent (golang.org/x/crypto/ssh)

  • RSA SHA-2 (rsa-sha2-256 / rsa-sha2-512) Support:
    • Implements ssh.MultiAlgorithmSigner on dynSigner so RSA keys and RSA-backed user certificates advertise and sign with rsa-sha2-512 and rsa-sha2-256.
    • Implements agent.ExtendedAgent (SignWithFlags) on keyRing and forwardedAgent so remote hosts requesting SHA-2 signatures via SSH_AGENTC_SIGN_REQUEST flags receive rsa-sha2-256 / rsa-sha2-512 instead of falling back to SHA-1 (ssh-rsa).
  • Certificate Signature Validation: Rejects deprecated ssh-rsa (SHA-1) and ssh-dss (DSA) CA signatures in checkCertificate.

3. Tab Auto-Completion & Standalone Server (internal/shellwords, sshterm-server, go/build.sh)

  • Trailing Backslash Token Parsing: Fixes shellwords.Parse so a trailing unquoted \ keeps raw and args aligned instead of panicking with an out-of-bounds slice during tab auto-completion.
  • Go Toolchain Alignment: Aligns go/go.mod (go 1.27.3) and go/build.sh (GOTOOLCHAIN) with .goversion so local builds do not fall back to an older host toolchain, and strips stale docroot/xterm.js from the embedded server docroot.
  • WebSocket Proxy Timeouts: Sets HandshakeTimeout: 10 * time.Second on websocket.Upgrader and applies a write deadline (tcpDeadlineWriter) on upstream TCP writes in proxyConn.

4. Frontend Terminal Hardening (@xterm/xterm in docroot/ssh.mjs)

  • csiRepGuard: Intercepts CSI Ps b (REP) and clamps Ps to term.cols, preventing String.prototype.repeat(2147483647) from throwing an uncaught RangeError that wedges WriteBuffer and deadlocks WASM Terminal.Write.
  • csiLoopGuard: Clamps parameters on CSI I (CHT), CSI Z (CBT), CSI L (IL), CSI M (DL), CSI S (SU), and CSI T (SD) to terminal dimensions to prevent 2^31 - 1 synchronous main-thread loops.
  • Title Toast Sanitization & Terminal Reset: Sanitizes control characters and truncates OSC 0/OSC 2 titles to 128 characters while reusing a single .sshterm-toast DOM node per screen, and resets terminal modes and pending input buffers (ResetSessionState) when an SSH or SFTP session ends.

Verification

  • Unit tests in go/internal/shellwords/..., go/internal/app/..., and go/sshterm-server/...
  • WASM / Chrome browser tests in go/internal/tests/remediations_test.go

- Go toolchain & build hygiene:
  - Update go/go.mod to go 1.27.3 to match .goversion and export GOTOOLCHAIN in go/build.sh.
  - Exclude stale xterm.js from sshterm-server's embedded docroot.

- Centralized third-party dependency workarounds (go/internal/depfix):
  - Add feature-flagged workarounds and depfix.WithDisabled helper so each vulnerability and its remediation can be verified in dual-mode tests and cleanly removed once fixed upstream.
  - github.com/pkg/sftp (EnableSFTPPacketGuard, EnableSFTPPathAndRemoveGuard, EnableSFTPResourceGuard):
    - Interpose sftpSafeConn via sftp.NewClientPipe to bounds-check incoming SFTP packets (SSH_FXP_VERSION, SSH_FXP_STATUS, SSH_FXP_HANDLE, SSH_FXP_DATA, SSH_FXP_NAME, SSH_FXP_ATTRS) before pkg/sftp unmarshals them with unchecked slice bounds.
    - Reject 0-byte SSH_FXP_DATA responses that trigger an infinite read loop in File.readChunkAt, cap cumulative SSH_FXP_READDIR entries, and reject READDIR filenames containing '/' or resolving to '.' / '..'.
    - Provide Lstat-based depfix.RemoveAll so recursive removal does not follow directory symlinks, and wrap JS callback boundaries in jsutil.TryCatch.
  - golang.org/x/crypto/ssh & ssh/agent (EnableSSHAgentGuard, EnableRSASHA2, EnableSSHSessionExitGuard, EnableCertSignatureGuard):
    - Bound concurrent forwarded agent channels, cap incoming agent request frames to 256 KiB before agent.ServeAgent pre-allocates up to 16 MiB, and reject non-list/sign agent message types before ServeAgent parses attacker-supplied keys.
    - Implement ssh.MultiAlgorithmSigner on dynSigner and agent.ExtendedAgent on keyRing and forwardedAgent so RSA keys and certificates use rsa-sha2-256 / rsa-sha2-512 instead of falling back to SHA-1 (ssh-rsa).
    - Wrap SSH session channels so malformed exit-status or exit-signal requests close the channel and drain remaining requests instead of deadlocking (*ssh.Session).Wait and mux.loop.
    - Reject deprecated SHA-1 (ssh-rsa) and DSA (ssh-dss) CA signatures in certificate verification and support no-touch-required (Flags=0) sk-* CA signatures.
  - golang.org/x/term (EnableTermEscapeGuard):
    - Terminate runaway (>64-byte) unterminated escape sequences in WrapTermReadWriter before Terminal.inBuf ([256]byte) fills up and spins in a synchronous 0-byte Read loop.
  - Document the removal procedure and residual risks in go/internal/depfix/README.md.

- Frontend @xterm/xterm workarounds & terminal hardening (docroot/ssh.mjs, go/internal/terminal):
  - Add window.sshApp.workarounds (csiRepGuard, csiLoopGuard, oscQueryAndLinkGuard) and applyXtermWorkarounds to clamp CSI Ps b (preventing RangeError in repeatPrecedingCharacter from wedging WriteBuffer) and CSI I/Z/L/M/S/T loop counts, and to rate-limit chained OSC 4 color queries and OSC 8 hyperlink markers.
  - Sanitize and cap OSC 0 / OSC 2 window titles and reuse a single toast element in TabManager._showMessage.
  - Reset terminal session modes and drain pending onData responses between SSH/SFTP sessions via Terminal.ResetSessionState.

- Local fixes:
  - Fix duplicate trailing backslash append to bufRaw in go/internal/shellwords.Parse that could cause an out-of-bounds slice panic during tab completion.
  - Set HandshakeTimeout on the WebSocket upgrader and per-write deadlines on upstream TCP connections in sshterm-server.
  - Update CHANGELOG.md.
@rthellend rthellend changed the title Remediate dependency security vulnerabilities and add dual-mode tests Harden third-party dependency boundaries and add dual-mode security regression tests Oct 25, 2026
@rthellend rthellend changed the title Harden third-party dependency boundaries and add dual-mode security regression tests Harden third-party dependency boundaries Oct 25, 2026
@rthellend
rthellend marked this pull request as ready for review October 25, 2026 15:36
@rthellend
rthellend merged commit 40fc4fc into main Oct 25, 2026
5 checks passed
@rthellend
rthellend deleted the security-dependency-remediations branch October 25, 2026 16:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant