Skip to content

[security] Linux code-server bootstrap executes an unpinned upstream installer as root #816

Description

@coygeek

[security] Linux code-server bootstrap executes an unpinned upstream installer as root

Summary

The documented Linux crabbox code workflow provisions a lease with the code capability and installs code-server during cloud-init. Both bootstrap generators currently do that by piping https://code-server.dev/install.sh directly into sh as root:

retry env HOME=/root sh -c 'curl -fsSL https://code-server.dev/install.sh | sh -s -- --method=standalone --prefix=/usr/local'

There is no pinned version, SHA-256 digest, signature check, or reviewed package repository control before the script is executed. If the upstream installer, its hosting path, or an on-path dependency of that fetch is compromised, the attacker gets root code execution inside every newly provisioned Linux lease that requested code-server.

Scope classification: in scope. SECURITY.md explicitly lists integrity failures in artifacts or images Crabbox downloads and installs as part of a documented default workflow as in scope. This report does not rely on hostile tenants sharing one broker, hostile repository configuration, or a lease owner attacking their own machine; it relies on Crabbox's own bootstrap generator executing an unauthenticated-by-digest upstream installer in a documented workflow. The impact is limited to the leased VM and the Crabbox workflow state exposed to that VM; the per-lease SSH private key remains local to the operator, and only the public key is sent to the coordinator/provider.

Affected Components

  • internal/cli/bootstrap.go:1445-1448: the Go bootstrap generator appends the code-server.dev/install.sh | sh command when cfg.Code is true, then only checks that /usr/local/bin/code-server --version runs. These lines execute remote script bytes before any digest or signature validation.
  • worker/src/bootstrap.ts:1465-1468: the Worker-side bootstrap generator mirrors the same root curl | sh installation path for config.code, so coordinator-created Linux code leases inherit the same supply-chain exposure.
  • internal/cli/bootstrap_test.go:392-410: the Go test asserts that the generated cloud-init contains the upstream installer URL and standalone install flags, and it only checks that code-server is absent when the code capability is not requested. There is no test requiring pinning or verification.
  • worker/test/bootstrap.test.ts:406-415: the Worker test likewise asserts the unpinned https://code-server.dev/install.sh URL in code-capable leases without asserting a digest or signature control.
  • docs/commands/code.md:20-24: the public command documentation describes crabbox warmup --code / crabbox code as a supported coordinator-backed Linux workflow for providers that advertise the code capability.
  • docs/security.md:306-343: the operations guide shows the stronger integrity pattern already used for Windows bootstrap artifacts and Linux APT signing keys: reviewed digests or pinned signing fingerprints, verification before install, and fail-closed behavior on mismatch.
  • docs/features/ssh-keys.md:51-56: counterevidence for impact calibration. In brokered mode the CLI sends only the public SSH key to the coordinator, while the private key never leaves the local machine, so the compromised lease should not be described as directly reading the operator's local per-lease private key.

Attack Path

Attacker role: external supply-chain attacker able to alter the bytes served as https://code-server.dev/install.sh, the hosting account, or a dependency of that fetch.

Prerequisites:

  • The operator creates a coordinator-backed Linux lease with the code capability, for example through crabbox warmup --code followed by crabbox code.
  • The selected provider uses the generated Linux cloud-init bootstrap from the Go or Worker bootstrap generator.
  • The attacker can make the installer URL return malicious script content during lease bootstrap.

Steps:

  1. The attacker compromises or controls the script bytes returned by https://code-server.dev/install.sh.
  2. The operator requests a fresh Linux code lease. Crabbox generates cloud-init with the root curl -fsSL ... | sh command.
  3. During provisioning, cloud-init executes the attacker-controlled installer as root before any code-server binary, package, or script digest is checked.
  4. The attacker installs a trojanized code-server, modifies /usr/local, adds a persistent service, reads the synced workspace, observes later commands executed on that lease, and captures any environment values intentionally forwarded to the lease by Crabbox's allowlist.
  5. The lease is handed to the operator as ready, so the compromised editor/runtime becomes part of the normal Crabbox development workflow until the machine is destroyed or rebuilt.

Impact

A compromise of the upstream code-server installer path becomes root code execution inside Crabbox-managed Linux code leases. From there, the attacker can tamper with the editor, source checkout, generated files, command outputs, and failure bundles for that lease. The attacker can also read any environment variables the operator explicitly forwards to commands running on the lease; the operations guide states that a box may observe forwarded environment values, and that profiles forwarding secrets are higher risk.

The blast radius is not the operator's whole local machine by default. Crabbox's SSH-key documentation says brokered mode sends only the public key to the coordinator/provider and keeps the private key local, so a compromised VM does not directly read the local per-lease private key from this path. The reportable boundary is instead the documented workflow integrity guarantee: Crabbox is downloading and installing an executable bootstrap artifact as part of a supported workflow without the fail-closed pinning pattern it already uses for other bootstrap artifacts.

Severity Assessment

CVSS Assessment

Metric v3.1 v4.0
Score 7.5 / 10.0 7.5 / 10.0
Severity High High
Vector CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Calculator CVSS v3.1 Calculator CVSS v4.0 Calculator

The score reflects a network-reachable supply-chain precondition with high attack complexity and required operator workflow interaction: the attacker must control the installer bytes, and a victim must provision a Linux code lease. Once those prerequisites hold, execution is root inside the vulnerable lease with high confidentiality, integrity, and availability impact for that lease's workspace, runtime, and forwarded command environment. Scope remains unchanged because the directly impacted system is the Crabbox-managed lease created by the vulnerable bootstrap path.

Recommended Remediation

  • Replace the code-server.dev/install.sh | sh bootstrap with a pinned release-artifact path. Download a reviewed code-server archive or package for the target architecture, verify a checked-in SHA-256 digest before extraction or installation, and fail closed on mismatch.
  • Keep the Go and Worker bootstrap generators behaviorally identical so direct CLI leases and coordinator-created leases receive the same verification controls.
  • Add configuration knobs only if needed for upgrades, for example CRABBOX_CODE_SERVER_VERSION, CRABBOX_CODE_SERVER_SHA256_AMD64, and CRABBOX_CODE_SERVER_SHA256_ARM64. Treat missing or malformed operator-supplied digests as a provisioning failure, not as permission to fall back to curl | sh.
  • Update internal/cli/bootstrap_test.go and worker/test/bootstrap.test.ts to assert that code-capable Linux bootstraps do not contain code-server.dev/install.sh | sh and do contain digest verification before install.
  • Add or extend a bootstrap-integrity lint that fails CI when a bootstrap path introduces curl ... | sh without adjacent digest/signature verification.
  • Consider aligning the default Tailscale installer mode with the same fail-closed pattern. Tailscale already has a pinned mode, but the default package mode still uses an unpinned installer script.

Validation

Validation method: static source review with targeted source, documentation, and test evidence.

What was checked:

  • The Go code path for Linux cloud-init generation includes the unpinned code-server installer only when cfg.Code is true.
  • The Worker code path mirrors that behavior for coordinator-created leases.
  • Existing bootstrap tests assert the installer URL and code capability gating, but do not require digest or signature verification.
  • Maintainer-authored policy places default workflow artifact/image integrity failures in scope.
  • Maintainer-authored operations guidance documents stronger fail-closed integrity controls for Windows bootstrap artifacts and Linux APT trust.
  • SSH-key documentation limits the impact claim: the compromised lease can observe lease-local state and forwarded values, but the brokered per-lease private key remains local to the operator.

Exact proof points:

  • internal/cli/bootstrap.go:1445-1448 and worker/src/bootstrap.ts:1465-1468 emit the unpinned root installer command.
  • internal/cli/bootstrap_test.go:392-410 and worker/test/bootstrap.test.ts:406-415 confirm this is expected output today.
  • SECURITY.md:34-49 marks integrity failures in Crabbox-downloaded default workflow artifacts/images as in scope.
  • docs/commands/code.md:20-24 confirms the code capability is a documented Linux lease workflow.
  • docs/security.md:306-343 confirms that other managed bootstrap artifacts and Linux package-signing inputs use reviewed digest/fingerprint controls.
  • docs/features/ssh-keys.md:51-56 confirms the private SSH key does not leave the local operator machine in brokered mode.

Counterevidence considered:

  • Crabbox is not a hostile multi-tenant sandbox, but this finding does not depend on hostile tenants; it depends on an external installer supply-chain compromise in a supported workflow.
  • Repository configuration and explicitly configured commands are trusted automation, but this installer URL is emitted by Crabbox's own bootstrap generator, not supplied by an untrusted repository.
  • TLS protects transport against ordinary network tampering, but it does not bind the installer to a reviewed version or digest and does not protect against upstream account, hosting, CDN, or future-content compromise.

The issue is accepted with high confidence because the vulnerable command is exact, reachable through a documented code lease, policy-supported as an in-scope artifact-integrity boundary, and not defeated by the local SSH-key counterevidence once the impact is scoped to the leased VM and forwarded workflow state.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions