Skip to content

[security] Use-only lease shares can attach forged runs to the lease owner's history #710

Description

@coygeek

[security] Use-only lease shares can attach forged runs to the lease owner's history

Summary

Crabbox's coordinator lets a user with only use access to another owner's lease create a run record that is attributed to that victim-owned lease. POST /v1/runs accepts a supplied leaseID when the lease is merely visible to the requester, and visibility includes use shares. The same creation path then records the victim owner in run.leaseOwners, while the attacker remains the run owner and can write events and retained logs to that run.

This crosses a supported Crabbox boundary because the maintainer-authored security policy treats access to another owner's resources contrary to documented authorization as in scope. The finding does not depend on hostile tenants sharing one broker as a generic isolation claim; it depends on a lower-privileged, authenticated share recipient mutating coordinator-managed run history that becomes readable as part of the lease owner's resource state.

Affected Components

  • Verified target commit: fca333101f70f3bb14f3368af74b787f83e7aa17
  • Component: coordinator run creation, run attribution, run readability, and portal run history
  • Relevant files:
    • worker/src/fleet.ts
    • worker/src/portal.ts

Attack Path

Attacker role:

An authenticated user token whose principal has use access, but not manage or owner access, to a victim-owned lease.

Prerequisites:

  • The victim owner or org shares a lease with the attacker using role use.
  • The attacker can call the coordinator run API with their own authenticated user token.
  • The victim later views the lease page, run detail page, raw logs, or run event JSON.

Steps:

  1. The attacker sends POST /v1/runs with the victim lease id in leaseID and attacker-chosen run metadata such as label and command.
  2. createRun loads the lease and rejects only if leaseVisibleToRequest is false. leaseVisibleToRequest is backed by leaseAccessRole, and leaseAccessRoleForPrincipal returns use for user or org use shares.
  3. createRun stores the new run under the attacker's owner and org, then calls setRunLeaseAttribution, which adds the victim lease owner to run.leaseOwners.
  4. Because the attacker owns the run, runWritableByRequest permits them to post run events and finish the run with attacker-controlled retained log content.
  5. Because the victim owner is listed in run.leaseOwners, runReadableToRequest permits the victim to read the attacker-owned run.
  6. The victim's lease detail page filters all runs for those that reference the lease and are readable to the victim, so the forged run appears in the lease's recent-run table. The victim can then open the run detail page, raw logs, and event JSON for attacker-controlled content.

Expected behavior:

Use-only access can intentionally permit operating a shared lease, but it should not let the use-share recipient bind arbitrary coordinator run records, events, and retained logs into the lease owner's trusted run history. Run-to-lease attribution should require owner or manage access, or use-share-created runs should remain readable only to the run owner unless an owner/manage principal creates or approves the attribution.

Impact

A lower-privileged share recipient can inject arbitrary run records into another owner's lease history. The injected run can contain attacker-controlled command strings, run labels, events, finish metadata, and retained raw logs, and the victim owner is authorized to retrieve those records through normal coordinator and portal paths.

The reviewed portal rendering escapes HTML, so this is not an XSS finding. The impact is cross-owner integrity of coordinator-managed operational evidence: a use-share principal can pollute another owner's run ledger and make forged execution evidence appear attached to the victim lease. That can mislead debugging, release evidence, incident review, billing review, or other workflows that treat the lease run history as owner-associated state.

Severity Assessment

CVSS Assessment

Metric v3.1 v4.0
Score 4.3 / 10.0 5.3 / 10.0
Severity Medium Medium
Vector CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N
Calculator CVSS v3.1 Calculator CVSS v4.0 Calculator

The score reflects a network-reachable authenticated attacker with low privileges and no victim interaction needed to create and populate the forged run. The direct demonstrated impact is limited integrity loss in the victim owner's coordinator run history. Confidentiality and availability are not scored because the attacker is supplying the log/event data rather than reading victim secret data or disrupting service.

Recommended Remediation

Use the same authorization boundary for run-to-lease attribution that Crabbox uses for lease management. A small fix is to require leaseManageableByRequest when createRun receives a leaseID, and to apply the same owner/manage check before POST /v1/runs/:id/events accepts an event leaseID that changes or expands run attribution.

If use-share users must be able to start commands against shared leases, keep those run records scoped to the run owner unless an owner or manage principal explicitly creates or approves lease-owner attribution. Add regression coverage for both creation-time attribution and event-time attribution.

Validation

Validation method:

Source review of the isolated target copy at commit fca333101f70f3bb14f3368af74b787f83e7aa17.

Positive evidence:

  • worker/src/fleet.ts:852-853 routes POST /v1/runs to createRun.
  • worker/src/fleet.ts:8840-8850 parses leaseID, loads the lease, and rejects only when leaseVisibleToRequest is false.
  • worker/src/fleet.ts:10455-10457 defines visibility as any non-empty leaseAccessRole.
  • worker/src/fleet.ts:10496-10512 returns use when the principal has a user or org use share.
  • worker/src/fleet.ts:8853-8859 creates the run owned by the attacker principal from the request, with an initially empty leaseOwners list.
  • worker/src/fleet.ts:8873-8875 calls setRunLeaseAttribution for the visible lease.
  • worker/src/fleet.ts:10554-10564 records the lease id and the lease owner's { owner, org } in the run attribution.
  • worker/src/fleet.ts:10515-10519 makes the attacker-owned run writable by the attacker.
  • worker/src/fleet.ts:8935-8948 lets a writable run owner append events, and worker/src/fleet.ts:8974-9022 lets a writable run owner finish the run and write retained log content.
  • worker/src/fleet.ts:10522-10533 grants read access to principals listed in run.leaseOwners.
  • worker/src/fleet.ts:5088-5108 builds a lease detail page from runs that reference the lease and pass runReadableToRequest.
  • worker/src/fleet.ts:5666-5696 serves portal run detail, raw logs, and event JSON to readable principals.
  • worker/src/portal.ts:498-615, worker/src/portal.ts:887-1008, and worker/src/portal.ts:2481-2502 render the recent-run table, run detail, log tail, and events.

Counterevidence reviewed:

  • worker/src/portal.ts escapes run labels, commands, logs, and event fields before HTML rendering, so the validated issue is not browser script execution.
  • runWritableByRequest still restricts event and finish writes to the run owner or admin. The issue is the earlier authorization mismatch that lets a use-share user become the run owner while attributing the run to the victim's lease.
  • Crabbox's security policy explicitly excludes mutually adversarial tenants as a general isolation model, but this specific path is in scope because the coordinator has documented owner/share roles and the lower-privileged use role can write state into another owner's resource history.

Suggested regression coverage:

  • Add a coordinator route test that creates a victim-owned lease shared to an attacker with role use, authenticates as the attacker, and asserts POST /v1/runs with the victim lease id is rejected or does not add the victim to run.leaseOwners.
  • Add a second test where an attacker-owned run attempts to append an event with a visible victim lease id and assert that owner/manage access is required for new lease attribution.
  • Verify that legitimate owner or manage principals can still create or attribute runs to the lease.

Suggested verification command:

npm test --prefix worker

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal priority bug or improvement with limited blast radius.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:needs-security-reviewClawSweeper marked this issue as needing security-sensitive review.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:securityThis issue is about security boundaries, credentials, authz, sandboxing, or sensitive data.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    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