[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:
- The attacker compromises or controls the script bytes returned by
https://code-server.dev/install.sh.
- The operator requests a fresh Linux code lease. Crabbox generates cloud-init with the root
curl -fsSL ... | sh command.
- During provisioning, cloud-init executes the attacker-controlled installer as root before any
code-server binary, package, or script digest is checked.
- 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.
- 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.
[security] Linux code-server bootstrap executes an unpinned upstream installer as root
Summary
The documented Linux
crabbox codeworkflow provisions a lease with thecodecapability and installscode-serverduring cloud-init. Both bootstrap generators currently do that by pipinghttps://code-server.dev/install.shdirectly intoshas 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.mdexplicitly 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 thecode-server.dev/install.sh | shcommand whencfg.Codeis true, then only checks that/usr/local/bin/code-server --versionruns. 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 rootcurl | shinstallation path forconfig.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 unpinnedhttps://code-server.dev/install.shURL in code-capable leases without asserting a digest or signature control.docs/commands/code.md:20-24: the public command documentation describescrabbox warmup --code/crabbox codeas 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:
codecapability, for example throughcrabbox warmup --codefollowed bycrabbox code.Steps:
https://code-server.dev/install.sh.curl -fsSL ... | shcommand.code-serverbinary, package, or script digest is checked.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.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
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
code-server.dev/install.sh | shbootstrap with a pinned release-artifact path. Download a reviewedcode-serverarchive or package for the target architecture, verify a checked-in SHA-256 digest before extraction or installation, and fail closed on mismatch.CRABBOX_CODE_SERVER_VERSION,CRABBOX_CODE_SERVER_SHA256_AMD64, andCRABBOX_CODE_SERVER_SHA256_ARM64. Treat missing or malformed operator-supplied digests as a provisioning failure, not as permission to fall back tocurl | sh.internal/cli/bootstrap_test.goandworker/test/bootstrap.test.tsto assert that code-capable Linux bootstraps do not containcode-server.dev/install.sh | shand do contain digest verification before install.curl ... | shwithout adjacent digest/signature verification.Validation
Validation method: static source review with targeted source, documentation, and test evidence.
What was checked:
cfg.Codeis true.Exact proof points:
internal/cli/bootstrap.go:1445-1448andworker/src/bootstrap.ts:1465-1468emit the unpinned root installer command.internal/cli/bootstrap_test.go:392-410andworker/test/bootstrap.test.ts:406-415confirm this is expected output today.SECURITY.md:34-49marks integrity failures in Crabbox-downloaded default workflow artifacts/images as in scope.docs/commands/code.md:20-24confirms the code capability is a documented Linux lease workflow.docs/security.md:306-343confirms that other managed bootstrap artifacts and Linux package-signing inputs use reviewed digest/fingerprint controls.docs/features/ssh-keys.md:51-56confirms the private SSH key does not leave the local operator machine in brokered mode.Counterevidence considered:
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.