Skip to content

[security] Freestyle and Islo stop accept claimless canonical resource names before deletion #714

Description

@coygeek

[security] Freestyle and Islo stop accept claimless canonical resource names before deletion

Summary

The direct Freestyle and Islo providers use the provider-visible crabbox-... name shape as enough recovery evidence when local lease-claim state is missing. Because both providers allow Crabbox to choose the provider resource name at creation time, another resource in the same provider account can also have a canonical-looking name without any retained Crabbox claim or provider-side ownership marker tying that exact object to Crabbox.

That crosses Crabbox's documented provider-resource safety boundary. SECURITY.md lists destructive provider actions against resources Crabbox cannot strongly identify as its own as in scope, and docs/security.md distinguishes missing cleanup coverage from unsafe deletion of resources that are not strongly identified as Crabbox-owned. The issue is not hostile multi-tenancy: the required actor is a local trusted operator or automation process with the relevant direct-provider credential, but Crabbox still performs the destructive action after only a name-shape check.

Affected Components

  • Checked commit: 5001cd1179a42c174da65c8e8a87bf16218aef95
  • Components: direct-provider lifecycle recovery and stop/delete handling
  • Freestyle:
    • internal/providers/freestyle/backend.go:357-370 resolves an operator-supplied id and calls DeleteVM.
    • internal/providers/freestyle/backend.go:492-552 accepts a raw fsb_... VM id, listed VM id/name, or generated slug when the provider VM name passes isCrabboxFreestyleSandboxName.
    • internal/providers/freestyle/backend.go:634-645 defines the canonical-name predicate as normalized name plus crabbox- prefix.
    • internal/providers/freestyle/client.go:42-46 shows Freestyle creation sends the selected name but no Crabbox ownership label or metadata field.
  • Islo:
    • internal/providers/islo/backend.go:544-558 resolves an operator-supplied id and calls DeleteSandbox.
    • internal/providers/islo/backend.go:563-593 uses the same resolver for Pause and Resume.
    • internal/providers/islo/backend.go:703-739 accepts canonical crabbox-... names and isb_<crabbox-name> lease ids without requiring an exact local claim.
    • internal/providers/islo/backend.go:923-934 defines the canonical-name predicate as normalized name plus crabbox- prefix.
    • internal/providers/islo/ssh.go:16-32 uses the same claimless resolver for SSH target resolution.
    • internal/providers/islo/backend.go:604-627 shows Islo creation sends the selected name but no provider-side ownership marker.

Attack Path

Attacker role: local trusted-operator process or automation with the relevant Freestyle or Islo provider credential.

Prerequisites:

  • The provider account contains a Freestyle VM or Islo sandbox whose provider-visible name matches Crabbox's canonical crabbox-... form.
  • The resource is not currently bound to Crabbox by an exact retained local lease claim, or the local claim state has been lost.
  • The actor can invoke Crabbox with the direct provider credential.

Steps:

  1. Select a canonical-looking Freestyle VM identifier or Islo sandbox name in the provider account.
  2. Run a destructive Crabbox operation such as crabbox stop --provider freestyle --id fsb_<vm-id> or crabbox stop --provider islo isb_<crabbox-name>.
  3. Freestyle resolveLeaseID fetches or lists the provider VM, then treats isCrabboxFreestyleSandboxName(vm.Name) as the ownership gate when no local claim is present.
  4. Islo resolveIsloLeaseID treats a canonical crabbox-... name, or an isb_ lease id wrapping such a name, as enough to build a lease id without looking up an exact local claim.
  5. Stop calls DeleteVM or DeleteSandbox and removes any local claim if one happens to exist.

The same Islo resolver also feeds Pause, Resume, and SSH resolution, so claimless canonical names can be reused non-destructively as well. The reportable destructive sink is the stop/delete path.

Impact

Crabbox can delete Freestyle VMs or Islo sandboxes that merely look like Crabbox resources but are not strongly proven to be owned by Crabbox. The impact is provider-resource integrity and availability loss: an operator or automation process can accidentally or intentionally route deletion through Crabbox for a resource whose only Crabbox evidence is a provider-visible prefix.

The severity is limited by the direct-provider prerequisite. The actor already needs local ability to run Crabbox with the provider credential, and the affected resource is in the same provider account. That lowers the issue to Medium, but it does not remove reportability because Crabbox's own policy treats destructive provider actions without strong ownership identification as a supported security boundary.

Severity Assessment

CVSS Assessment

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

Recommended Remediation

Require strong ownership evidence before destructive Freestyle and Islo operations. Suitable controls include:

  • Require an exact retained local lease claim before stop, pause, resume, SSH resolution, or reused-run operations that mutate an existing provider resource.
  • If the provider API supports it, write immutable Crabbox ownership metadata at creation time and require that marker before delete or reuse.
  • Keep canonical-name recovery non-destructive by default. For example, list matching orphan candidates and require an explicit --reclaim flow that recreates a local claim before any delete, pause, resume, or SSH action.

Regression coverage should prove that canonical-looking provider resources without an exact claim or provider-side ownership marker are refused before DeleteVM, DeleteSandbox, PauseSandbox, ResumeSandbox, or SSH resume/wait behavior.

Validation

Validation method: source review, unit-test inspection, CVSS calculator check, and targeted test attempt.

Evidence:

  • SECURITY.md:34-49 places destructive provider actions against resources Crabbox cannot strongly identify as its own in scope.
  • docs/security.md:361-365 says deleting a resource Crabbox cannot strongly identify as its own crosses a safety boundary.
  • docs/security.md:378-389 says direct cleanup uses provider labels and brokered sweeps require exact retained bindings for destructive action. This is stronger than the Freestyle/Islo stop fallback, which uses only canonical provider names.
  • docs/providers/freestyle.md:134-136 and docs/providers/islo.md:157-160 intentionally document recovery by canonical names after local claim loss. That is useful recovery behavior, but it is also the counterevidence: the current destructive path treats that recovery name as ownership proof.
  • internal/providers/freestyle/backend.go:362-369 calls DeleteVM after resolveLeaseID returns an id.
  • internal/providers/freestyle/backend.go:492-552 accepts raw and listed Freestyle identifiers when the fetched/listed VM name passes isCrabboxFreestyleSandboxName; internal/providers/freestyle/backend.go:634-645 makes that a normalized crabbox- prefix check.
  • internal/providers/freestyle/client.go:42-46 and internal/providers/freestyle/backend.go:382-392 show the Freestyle create request carries name, ports, and optional template data, not a provider-side Crabbox ownership marker.
  • internal/providers/freestyle/backend_test.go:177-206 rejects non-canonical unclaimed VMs but accepts an unclaimed fsb_vm123 when the provider VM name is crabbox-repo-abc123.
  • internal/providers/islo/backend.go:549-556 calls DeleteSandbox after resolveIsloLeaseID returns a name.
  • internal/providers/islo/backend.go:703-739 accepts canonical crabbox-... names and isb_<canonical-name> ids without requiring an exact retained local claim; internal/providers/islo/backend.go:923-934 makes that a normalized crabbox- prefix check.
  • internal/providers/islo/backend.go:604-627 shows the Islo create request carries the selected name and runtime options, not a provider-side Crabbox ownership marker.
  • internal/providers/islo/backend_test.go:181-204 rejects non-canonical names but accepts crabbox-repo-abcdef without a retained claim. internal/providers/islo/backend_test.go:1714-1739 confirms Pause and Resume call the provider for a canonical name and reject only a non-Crabbox name.

Verification commands:

python3 - <<'PY'
from cvss import CVSS3, CVSS4
print(CVSS3("CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:N/I:H/A:H").scores())
print(CVSS4("CVSS:4.0/AV:L/AC:L/AT:N/PR:H/UI:N/VC:N/VI:H/VA:H/SC:N/SI:N/SA:N").scores())
PY

This returned v3.1 6.0 / Medium and v4.0 6.8 / Medium.

GOCACHE=/tmp/crabbox-verify-4000-gocache GOMODCACHE=/tmp/crabbox-verify-4000-gomodcache go test ./internal/providers/freestyle ./internal/providers/islo

The targeted Go test command was attempted from the isolated target copy, but dependency setup was environment-blocked because the sandbox cannot resolve proxy.golang.org. No live provider proof was attempted; the accepted verdict is based on current source, existing tests that encode the behavior, and the maintainer-authored security boundary.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1Urgent regression or broken agent/channel workflow affecting real users now.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:data-lossThis issue is about lost, corrupted, or silently dropped user/session/config data.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