Skip to content

[security] Managed-Linux --code bootstrap executes the remote code-server installer without integrity verification #788

Description

@coygeek

[security] Managed-Linux --code bootstrap executes the remote code-server installer without integrity verification

Summary

Crabbox's managed-Linux --code capability installs code-server by rendering a root cloud-init bootstrap command that fetches https://code-server.dev/install.sh and pipes the response directly to sh:

curl -fsSL https://code-server.dev/install.sh | sh -s -- --method=standalone --prefix=/usr/local

This capability is opt-in and disabled by default, but it is a documented Crabbox-owned lease capability rather than repository-controlled project automation. When an operator requests --code, Crabbox downloads and installs the code-server runtime as part of the supported managed-Linux Code workflow.

The root security boundary is therefore supply-chain integrity for an external artifact Crabbox downloads and executes during a documented runtime bootstrap. This fits the maintainer policy's in-scope class for "integrity failures in artifacts or images that Crabbox downloads and installs as part of a documented default workflow" and is distinct from out-of-scope hostile repository scripts or a trusted operator intentionally running commands on their own lease.

Affected Components

  • Verification target snapshot: ab1c29f3fd40fad7898a6bf109edd0a17678c937
  • Component: managed-Linux cloud-init bootstrap for the Code lease capability
  • Affected files:
    • internal/cli/bootstrap.go:77-107 renders cloud-init runcmd as a root bash -euxo pipefail script and appends optional capability bootstrap commands before marking the lease bootstrapped.
    • internal/cli/bootstrap.go:1445-1448 appends the cfg.Code install branch, including curl -fsSL https://code-server.dev/install.sh | sh ..., with no digest, signature, or pinned-release verification.
    • internal/cli/bootstrap_test.go:392-409 asserts that generated cfg.Code cloud-init contains https://code-server.dev/install.sh, confirming this is the current expected generated bootstrap shape.
    • internal/cli/lease_flags.go:57-60 exposes --code as the lease flag for provisioning or requiring the web code-server capability.
    • docs/features/capabilities.md:149-165 documents the managed-Linux Code capability and states that the bootstrap installs code-server at /usr/local/bin/code-server.
    • docs/features/runner-bootstrap.md:72-90 documents --code as an optional lease capability whose readiness check verifies code-server --version.

Attack Path

Attacker role:

An external supply-chain or delivery-path attacker who can control the response served for https://code-server.dev/install.sh at install time. Examples include compromise of the upstream installer endpoint, its hosting/CDN path, DNS/routing for the endpoint, or a TLS-intercepting environment trusted by the lease.

Prerequisites:

  • The operator creates or warms a managed Linux lease with --code.
  • The attacker controls the installer script body returned to that lease when cloud-init runs.
  • No Crabbox credential, trusted operator account, hostile repository configuration, or access to the operator's local machine is required.

Steps:

  1. The operator requests a managed Linux lease with --code.
  2. Crabbox renders cloud-init for the lease. The generated runcmd runs as root.
  3. The cfg.Code branch installs libatomic1, then runs curl -fsSL https://code-server.dev/install.sh | sh -s -- --method=standalone --prefix=/usr/local with HOME=/root.
  4. The attacker-controlled installer body executes as root inside the freshly provisioned lease.
  5. The resulting /usr/local/bin/code-server runtime is the binary Crabbox later verifies with code-server --version and exposes through the authenticated Code bridge.

Expected result:

Crabbox should either install a reviewed, version-pinned code-server artifact whose digest/signature is verified before execution, or fail closed when the fetched bytes do not match the expected integrity metadata.

Actual result:

The remote installer script is executed as root without a Crabbox-side integrity check. A tampered installer can run arbitrary root commands inside every managed Linux lease provisioned with --code during the attack window.

Impact

A successful attack yields arbitrary root code execution inside the managed Linux lease that requested --code. That code can modify the checked-out project, observe files and command output on the lease, alter the installed code-server runtime, and influence the authenticated Code experience the operator later opens through Crabbox.

The trusted-operator model does not make this expected behavior: the attacker is not a trusted operator, a same-OS-user process, or repository configuration intentionally executed by the operator. The boundary crossed is Crabbox's responsibility for the integrity of external runtime artifacts it downloads and installs in a supported bootstrap path.

The issue is limited to leases that request --code; minimal headless leases and managed Linux leases without the Code capability are unaffected.

Severity Assessment

CVSS Assessment

Metric v3.1 v4.0
Score 7.5 / 10.0 7.7 / 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:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:L/SI:L/SA:L
Calculator CVSS v3.1 Calculator CVSS v4.0 Calculator

The score uses high attack complexity because exploitation requires control of the upstream installer response or its delivery path at the moment a --code lease boots. User interaction is required because an operator must request the Code capability. Privileges required are none for the external attacker, and the impact to the provisioned lease is high for confidentiality, integrity, and availability once the script executes as root.

Recommended Remediation

Replace the remote install-script execution path with a pinned artifact install that fails closed on integrity mismatch.

A minimal fix would:

  • Select an explicit code-server version in internal/cli/bootstrap.go.
  • Download a versioned release artifact for the detected architecture, for example from the official GitHub release path.
  • Embed reviewed SHA-256 digests for each supported architecture beside the URL/version constants.
  • Verify the archive with sha256sum -c - before extraction or execution.
  • Install the verified binary into /usr/local/bin/code-server.
  • Add regression coverage that fails if generated cfg.Code cloud-init contains code-server.dev/install.sh | sh or lacks the digest verification step.

If a short-term compatibility path must keep the upstream installer script, fetch it to a file first, pin its exact digest, verify that digest before execution, and document the temporary trust model and update process in docs/security.md.

Validation

Validation performed:

  • Source review of the current isolated target copy.
  • Focused generated-cloud-init test:
GOCACHE=/tmp/crabbox-go-cache GOTMPDIR=/tmp go test ./internal/cli -run TestCloudInitCodeProfile -count=1

Result:

ok  	github.com/openclaw/crabbox/internal/cli	0.769s

Evidence:

  • internal/cli/bootstrap.go:77-107 shows the managed Linux bootstrap runs root cloud-init commands under bash -euxo pipefail.
  • internal/cli/bootstrap.go:1445-1448 shows the cfg.Code branch pipes the remote code-server installer directly into sh.
  • internal/cli/bootstrap_test.go:392-409 confirms generated cfg.Code cloud-init is expected to contain https://code-server.dev/install.sh and does not install code-server in the base configuration.
  • internal/cli/bootstrap.go:141-148, :215-216, :278-279, :411-415, and :459-461 show the established Windows bootstrap pattern of verifying downloaded artifacts with SHA-256 before extraction or execution.
  • internal/cli/bootstrap.go:1642-1659 shows a comparable managed-Linux pinned-install mode for Tailscale that downloads a versioned archive and verifies it with sha256sum -c -.
  • docs/features/capabilities.md:24-26 states that --code defaults off and must be requested when the lease is created.
  • docs/features/capabilities.md:149-165 documents the supported Code capability and its /usr/local/bin/code-server install shape.
  • SECURITY.md:46-48 lists integrity failures in artifacts or images Crabbox downloads and installs as in scope.

Counterevidence considered:

  • --code is optional and defaults off. This narrows affected leases, but it does not remove the integrity requirement once the operator uses the documented Crabbox-owned capability.
  • The attacker must control the external installer response or delivery path. This raises attack complexity, but the resulting root execution is still a supported-boundary crossing because Crabbox executes unverified external bytes during bootstrap.
  • The behavior is covered by an existing test, so it is not an accidental dead branch. The test currently preserves the vulnerable install shape rather than proving an integrity check.

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