Skip to content

Remove all dependencies on github.com/loft-sh modules and harden the SSH server - #22

Merged
renatoathaydes merged 3 commits into
mainfrom
claude/remove-loft-sh-deps-382523
Oct 20, 2026
Merged

renatoathaydes merged 3 commits into
mainfrom
claude/remove-loft-sh-deps-382523

Conversation

@renatoathaydes

@renatoathaydes renatoathaydes commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

The github.com/loft-sh Go modules are no longer maintained, so DevPod no longer depends on any of them. Their code now lives in this repository, and the unmaintained libraries they pulled in are gone too.

Module Replacement
loft-sh/log pkg/log (copied; Apache 2.0 licence kept in pkg/log/LICENSE)
loft-sh/ssh (fork of gliderlabs/ssh) pkg/ssh/sshd: gliderlabs/ssh v0.3.8 plus loft-sh's unix socket forwarding, agent listener and port-0 fix (BSD licence kept)
loft-sh/programming-language-detection pkg/language/detect.go (own code)

Transitive dependencies removed: AlecAivazis/survey (archived), mgutz/ansi, acarl005/stripansi, k0kubun/go-ansi, anmitsu/go-shlex, kballard/go-shellquote, mattn/go-colorable and olekukonko/tablewriter v0.0.5. Replacements:

  • Prompts use charmbracelet/huh, which was already a dependency.
  • Tables are rendered by our own code in the same layout. tablewriter v1 would have added seven modules, including the unmaintained olekukonko/ts.
  • Colours and escape stripping are a few lines of our own code. On Windows, the console's VT processing is enabled through x/sys/windows.
  • Session.Command() was removed from sshd; it had no callers, and callers use RawCommand().

Fixes found on the way (see CHANGELOG):

  • Language detection now recognizes C++, C# and PHP projects. The old library returned names that never matched devpod's own, and it skipped any file whose name contained env, dist or cache.
  • A required provider option without allowed values can be prompted for again. The old survey code got an empty option list and failed with "please provide options to select from".
  • The file logger rotates at 10 MB as intended (it was set to 10 TB).

The stripped linux/amd64 binary is about 390 KB smaller. go-licenses now ignores only github.com/loft-sh/devpod, so any future loft-sh dependency gets checked.

Security hardening

A security review of the change found no new high or medium severity issues. It found four low-severity issues inherited from the upstream SSH server code that runs in the dev container, and this PR fixes them (last commit):

  • Removed command: the hidden devpod agent container ssh-server command is gone. Only DevPod Pro started it, and it accepted any client without authentication and ran the shell as whichever user the client named.
  • Unix socket forwards: a reverse forward (as GPG agent forwarding uses) only replaces a socket that nothing listens on and that belongs to the server's user (any user when the server runs as root), and is refused otherwise. Before, it deleted whatever was at the path, so concurrent sessions forwarding the same socket stole or removed each other's.
  • Shared ssh-agent socket directory: /tmp/auth-agent-<id> must not be a symlink, must be owned by the server's user and must have mode 0700, and the socket is 0600. A session removes the directory only when it is empty.
  • Forward cancellation: TCP and unix reverse forwards are tracked per connection, so one connection can't cancel another's.

Test plan

  • Rebased onto main (after Embed the Linux agents in the CLI instead of downloading them #19); go build ./..., go vet ./..., cross-builds for windows/amd64 and linux/arm64
  • go test ./pkg/... ./cmd/..., and -race on the changed packages
  • golangci-lint v1.60.1 with the CI flags: clean
  • New tests: SSH server hardening (each fix, also run on Linux as root and as a normal user), language detection, unix socket forwarding in both directions, the table renderer, ANSI colours and stripping
  • Smoke test: devpod provider add/list/options and devpod list output looks as before
  • Interactive prompts (huh select, input and password) were not tried in a real terminal
  • e2e tests (CI)

🤖 Generated with Claude Code

renatoathaydes and others added 3 commits October 20, 2026 10:39
The loft-sh Go modules are no longer maintained, so their code now lives
in this repository:

- loft-sh/log becomes pkg/log. Prompts use charmbracelet/huh instead of
  the archived AlecAivazis/survey, tables are rendered by our own code
  instead of tablewriter v0.0.5, and mgutz/ansi, acarl005/stripansi and
  k0kubun/go-ansi are replaced by a few lines of code.
- loft-sh/ssh becomes pkg/ssh/sshd: gliderlabs/ssh v0.3.8 plus unix
  socket forwarding, without Session.Command (and go-shlex).
- loft-sh/programming-language-detection is replaced by
  pkg/language/detect.go.

This also fixes detection of C++, C# and PHP projects, prompting for
required options without allowed values, and log rotation at 10 MB
instead of 10 TB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fix low-severity issues inherited from upstream in the SSH server that
runs in the dev container:

- Remove the hidden `agent container ssh-server` command. Only DevPod Pro
  started it, and it accepted any client without authentication and ran
  the shell as whichever user the client named.
- A reverse unix socket forward only replaces a socket that nothing
  listens on and that belongs to the server's user (any user when it
  runs as root), and is refused otherwise, so sessions forwarding the
  same socket no longer steal or remove each other's.
- The shared ssh-agent socket directory (/tmp/auth-agent-<id>) must not
  be a symlink, must be owned by the server's user and have mode 0700;
  the socket is 0600. A session removes the directory only when empty.
- Track TCP and unix reverse forwards per connection, so one connection
  can't cancel another's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@renatoathaydes
renatoathaydes force-pushed the claude/remove-loft-sh-deps-382523 branch from cde6493 to 504c238 Compare October 20, 2026 08:40
@renatoathaydes renatoathaydes changed the title Remove all dependencies on github.com/loft-sh modules Remove all dependencies on github.com/loft-sh modules and harden the SSH server Oct 20, 2026
@renatoathaydes
renatoathaydes merged commit 4883368 into main Oct 20, 2026
18 of 19 checks passed
@renatoathaydes
renatoathaydes deleted the claude/remove-loft-sh-deps-382523 branch October 20, 2026 08:50
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