[security] Manage-share run events can reattribute runs into another lease's audit history
Summary
POST /v1/runs/:id/events correctly requires the caller to own the run before appending an event, but it separately accepts an optional leaseID from the event body. If that supplied lease ID differs from the run's current lease, the coordinator only checks whether the caller can manage the target lease. A user with manage share access to another owner's lease can therefore append an event to one of their own runs that changes the run's lease attribution to the shared lease.
This crosses Crabbox's supported trusted-team boundary because the documented run-history model says lease owners receive read-only audit access to work on their leases, while lease shares do not grant access to runs created by other actors. The affected path lets a share recipient create misleading backing-lease attribution and place an unrelated run into the target lease owner's audit/history views.
Affected Components
worker/src/fleet.ts:10032-10045: The run-event route first checks that the caller can write the run, then accepts input.leaseID; for a different lease ID it performs a raw lease lookup and authorizes the supplied lease with leaseManageableByRequest.
worker/src/fleet.ts:11740-11743: leaseManageableByRequest treats a manage share recipient the same as the lease owner for this check, so the event route accepts a cross-owner lease ID when the caller has manage-share access.
worker/src/fleet.ts:11959-11982: Appending the event calls applyRunEventSummary, persists the event, persists the mutated run, and broadcasts the event after the event body has been allowed to change the run summary.
worker/src/fleet.ts:15495-15506: applyRunEventSummary copies event.leaseID into run.leaseID, turning the event body's lease ID into durable run attribution metadata.
worker/src/fleet.ts:11829-11840: When the run lease ID changes, setRunLeaseAttribution records the target lease ID and the target lease owner's owner/org identity in run.leaseIDs and run.leaseOwners.
worker/src/fleet.ts:10151-10180: Run history listing uses run.leaseIDs, ensureRunLeaseAttribution, and runReadableToRequest, so a reattributed run appears in lease-filtered run history for the target lease owner.
worker/src/fleet.ts:6576-6606: Portal run detail, log, and event routes use runReadableToRequest; once the target lease owner is in the run attribution list, they can read the reattributed run detail, logs, and events as audit data.
docs/features/history-logs.md:68-73: The documented history contract says backing lease owners get read-only audit access to work on their lease, and explicitly says lease shares do not grant access to runs created by other actors.
Attack Path
Attacker role: authenticated non-admin user who has manage share access on a lease owned by another owner or org.
Prerequisites:
- The attacker has a valid Crabbox user token.
- Another operator has shared a lease with the attacker using the
manage role.
- The attacker owns any run record that is writable by their identity.
Steps:
- The attacker creates or selects one of their own runs.
- The attacker sends
POST /v1/runs/<attacker-run-id>/events with an event body containing leaseID for the other operator's shared lease.
- The coordinator validates that the attacker owns the run, then validates only that the attacker has manage access to the supplied lease.
- The event summary updates the run's primary
leaseID and records the supplied lease owner's identity in the run's backing-lease attribution.
- The other lease owner's history, portal, log, event, and live-event audit paths can now show the attacker's unrelated run as work attributed to that lease.
Impact
This is an audit-history integrity issue. A manage-share recipient can cause unrelated runs to appear under another operator's lease history and can make that lease owner receive read-only audit access to run detail, logs, events, telemetry, and live event subscriptions that were not created as work on their lease.
The issue does not grant admin authority, mutate the target lease lifecycle, or allow a user without manage-share access to target the lease. The practical impact is that Crabbox's coordinator-stored run history can no longer be treated as a reliable record of which runs were actually backed by a lease, and lease owners may be shown misleading or attacker-controlled run history under their lease audit surface.
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 is Medium because exploitation requires an authenticated user who already has manage-share access to the target lease, and the effect is limited to coordinator run-history integrity. The attack does not expose Crabbox credentials or provider resources directly, but it does cross the documented audit attribution boundary for lease owners and shared users.
Recommended Remediation Approach
Bind event-supplied lease attribution to the run's existing backing-lease relationship instead of treating manage-share access to an arbitrary lease as sufficient. The event route should only accept a replacement leaseID when it is part of a legitimate run/lease replacement flow or otherwise matches the run's current owner/org and established attribution state. If manage share users need to operate on shared leases, keep that permission scoped to lease management actions and avoid letting it rewrite unrelated run history.
Add regression coverage for a user with manage share access who attempts to append a run event with a different owner's lease ID to their own unrelated run. The expected behavior should be rejection or a non-attributing event that cannot alter run.leaseID, run.leaseIDs, or run.leaseOwners.
Validation
Validation method: source review against current main at cd9ede0bd4611e044d7d60279c8ff35ac9c3db6e.
Confirmed evidence:
- The run-event endpoint allows
input.leaseID to name a lease other than the run's current lease when leaseManageableByRequest passes for that lease.
- A
manage share recipient satisfies leaseManageableByRequest.
- The accepted event mutates durable run attribution through
applyRunEventSummary and setRunLeaseAttribution.
- Run history, portal run pages, logs, events, and live event subscriptions use the resulting attribution to grant read-only audit access to backing lease owners.
- Crabbox's documented history contract says lease owners get audit access to work on their lease and that lease shares do not grant access to runs created by other actors.
Counterevidence and limits:
- Users with only
use share access are already blocked from re-tagging unrelated runs into lease-owner audit views.
- The event body is bounded metadata and does not by itself mutate the target lease lifecycle or provider resources.
- The attacker must already be authenticated and have manage-share access on the target lease.
[security] Manage-share run events can reattribute runs into another lease's audit history
Summary
POST /v1/runs/:id/eventscorrectly requires the caller to own the run before appending an event, but it separately accepts an optionalleaseIDfrom the event body. If that supplied lease ID differs from the run's current lease, the coordinator only checks whether the caller can manage the target lease. A user withmanageshare access to another owner's lease can therefore append an event to one of their own runs that changes the run's lease attribution to the shared lease.This crosses Crabbox's supported trusted-team boundary because the documented run-history model says lease owners receive read-only audit access to work on their leases, while lease shares do not grant access to runs created by other actors. The affected path lets a share recipient create misleading backing-lease attribution and place an unrelated run into the target lease owner's audit/history views.
Affected Components
worker/src/fleet.ts:10032-10045: The run-event route first checks that the caller can write the run, then acceptsinput.leaseID; for a different lease ID it performs a raw lease lookup and authorizes the supplied lease withleaseManageableByRequest.worker/src/fleet.ts:11740-11743:leaseManageableByRequesttreats amanageshare recipient the same as the lease owner for this check, so the event route accepts a cross-owner lease ID when the caller has manage-share access.worker/src/fleet.ts:11959-11982: Appending the event callsapplyRunEventSummary, persists the event, persists the mutated run, and broadcasts the event after the event body has been allowed to change the run summary.worker/src/fleet.ts:15495-15506:applyRunEventSummarycopiesevent.leaseIDintorun.leaseID, turning the event body's lease ID into durable run attribution metadata.worker/src/fleet.ts:11829-11840: When the run lease ID changes,setRunLeaseAttributionrecords the target lease ID and the target lease owner's owner/org identity inrun.leaseIDsandrun.leaseOwners.worker/src/fleet.ts:10151-10180: Run history listing usesrun.leaseIDs,ensureRunLeaseAttribution, andrunReadableToRequest, so a reattributed run appears in lease-filtered run history for the target lease owner.worker/src/fleet.ts:6576-6606: Portal run detail, log, and event routes userunReadableToRequest; once the target lease owner is in the run attribution list, they can read the reattributed run detail, logs, and events as audit data.docs/features/history-logs.md:68-73: The documented history contract says backing lease owners get read-only audit access to work on their lease, and explicitly says lease shares do not grant access to runs created by other actors.Attack Path
Attacker role: authenticated non-admin user who has
manageshare access on a lease owned by another owner or org.Prerequisites:
managerole.Steps:
POST /v1/runs/<attacker-run-id>/eventswith an event body containingleaseIDfor the other operator's shared lease.leaseIDand records the supplied lease owner's identity in the run's backing-lease attribution.Impact
This is an audit-history integrity issue. A manage-share recipient can cause unrelated runs to appear under another operator's lease history and can make that lease owner receive read-only audit access to run detail, logs, events, telemetry, and live event subscriptions that were not created as work on their lease.
The issue does not grant admin authority, mutate the target lease lifecycle, or allow a user without manage-share access to target the lease. The practical impact is that Crabbox's coordinator-stored run history can no longer be treated as a reliable record of which runs were actually backed by a lease, and lease owners may be shown misleading or attacker-controlled run history under their lease audit surface.
Severity Assessment
CVSS Assessment
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:NThe score is Medium because exploitation requires an authenticated user who already has manage-share access to the target lease, and the effect is limited to coordinator run-history integrity. The attack does not expose Crabbox credentials or provider resources directly, but it does cross the documented audit attribution boundary for lease owners and shared users.
Recommended Remediation Approach
Bind event-supplied lease attribution to the run's existing backing-lease relationship instead of treating manage-share access to an arbitrary lease as sufficient. The event route should only accept a replacement
leaseIDwhen it is part of a legitimate run/lease replacement flow or otherwise matches the run's current owner/org and established attribution state. Ifmanageshare users need to operate on shared leases, keep that permission scoped to lease management actions and avoid letting it rewrite unrelated run history.Add regression coverage for a user with
manageshare access who attempts to append a run event with a different owner's lease ID to their own unrelated run. The expected behavior should be rejection or a non-attributing event that cannot alterrun.leaseID,run.leaseIDs, orrun.leaseOwners.Validation
Validation method: source review against current
mainatcd9ede0bd4611e044d7d60279c8ff35ac9c3db6e.Confirmed evidence:
input.leaseIDto name a lease other than the run's current lease whenleaseManageableByRequestpasses for that lease.manageshare recipient satisfiesleaseManageableByRequest.applyRunEventSummaryandsetRunLeaseAttribution.Counterevidence and limits:
useshare access are already blocked from re-tagging unrelated runs into lease-owner audit views.