A critical path traversal flaw in Coder’s code-marketplace software, versions up to 2.4.1, exposes servers to arbitrary file writes. Attackers with upload access can slip malicious VSIX extension files past extraction safeguards, dumping payloads anywhere the process can write. Coder patched it in v2.4.2 after a responsible disclosure from researcher Kandlaguduru Vamsi.
This Zip Slip vulnerability—CWE-22 in MITRE’s common weaknesses enumeration—hits the ExtractZip function. It feeds raw, attacker-controlled zip entry names directly to a callback that joins them with the target directory using Go’s filepath.Join. No checks block traversal sequences like ../../../etc/cron.d/evil. filepath.Clean normalizes paths but doesn’t enforce boundaries, so filepath.Join("/srv/ext/pub/1.0", "../../../../etc/cron.d/evil") resolves to /etc/cron.d/evil.
Technical Breakdown
The root issue lies in two loops within AddExtension: one for the main zip entries and another for extra files. Here’s the vulnerable pattern:
return false, fn(zf.Name, zr) // zf.Name not sanitized
And the path construction:
path := filepath.Join(dir, name) // zip loop
path := filepath.Join(dir, file.RelativePath) // extra files loop
Zip Slip isn’t new; it surfaced in 2018 across libraries like Apache Commons Compress and Node.js adm-zip. Attackers embed ../ in filenames to escape sandboxes. In Go, libraries like archive/zip parse entries safely but defer path handling to callers. Coder’s marketplace skipped that step, a classic oversight in untrusted archive processing.
Coder builds remote development environments, akin to self-hosted Gitpod or GitHub Codespaces. Their marketplace (github.com/coder/code-marketplace) lets admins distribute VS Code extensions (VSIX files, which are zips) to workspaces. Deployments often run as non-root, but marketplace daemons might elevate for installs. Check your Dockerfile or systemd unit—many setups bind to low ports or write system-wide.
Attack Vectors and Real-World Impact
Any authenticated user with upload permissions triggers this. No special roles needed beyond basic contributor access. Upload a crafted VSIX with traversal entries, and extraction writes to chosen paths. Depending on process user (often coder or root):
- Inject cron jobs:
/etc/cron.d/backdoorfor persistence. - Drop SSH keys:
/home/coder/.ssh/authorized_keys. - Hijack loaders:
/etc/ld.so.preloadfor shared library attacks. - Overwrite binaries if privs allow.
Why this matters: Marketplaces amplify supply-chain risks. A single bad extension compromises all connected workspaces. Coder’s setup integrates tightly with Kubernetes or Docker, so one breach pivots to clusters. In production, this scores high CVSS—base 8.8+ for authenticated remote file write. Skeptically, it’s not zero-day material; scanners like Trivy flag Zip Slip in CI. But overlooked in hotfixes, it lingered until disclosure.
Broader context: VS Code extensions run semi-trusted code in servers. Malicious VSIXes already plague open-vsx.org. Coder’s marketplace, being self-hosted, trades central vetting for control—but demands rigor. Similar slips hit JetBrains Marketplace in 2023 and Eclipse plugins historically.
Fix and Forward Steps
Coder released v2.4.2 on GitHub with path sanitization. Key change: prefix enforcement before writes, likely via filepath-safe joins or resolvePath equivalents. Verify with:
$ git diff v2.4.1..v2.4.2 -- marketplace/extract.go
Upgrade immediately if ≤2.4.1. Audit deployments: run ps aux | grep marketplace for privs, scan with zip-slip-scanner tools. Best practice: use libraries like github.com/sirupsen/logrus no, wait—adopt github.com/mholt/archiver or github.com/klauspost/compress with built-in checks. Always resolve paths against a base via filepath.Abs and prefix match:
resolved := filepath.Clean(filepath.Join(baseDir, zipName))
if !strings.HasPrefix(resolved, baseDir) {
return errors.New("path traversal detected")
}
Coder’s quick fix and bounty policy shine here. Credit Vamsi via LinkedIn for clean disclosure per their policy. Operators, treat marketplaces as hostile: validate uploads, sign extensions, isolate processes. This vuln underscores why archive handling demands paranoia— one slip unzips your server.