[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:
- Select a canonical-looking Freestyle VM identifier or Islo sandbox name in the provider account.
- Run a destructive Crabbox operation such as
crabbox stop --provider freestyle --id fsb_<vm-id> or crabbox stop --provider islo isb_<crabbox-name>.
- Freestyle
resolveLeaseID fetches or lists the provider VM, then treats isCrabboxFreestyleSandboxName(vm.Name) as the ownership gate when no local claim is present.
- 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.
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.
[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.mdlists destructive provider actions against resources Crabbox cannot strongly identify as its own as in scope, anddocs/security.mddistinguishes 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
5001cd1179a42c174da65c8e8a87bf16218aef95internal/providers/freestyle/backend.go:357-370resolves an operator-supplied id and callsDeleteVM.internal/providers/freestyle/backend.go:492-552accepts a rawfsb_...VM id, listed VM id/name, or generated slug when the provider VM name passesisCrabboxFreestyleSandboxName.internal/providers/freestyle/backend.go:634-645defines the canonical-name predicate as normalized name pluscrabbox-prefix.internal/providers/freestyle/client.go:42-46shows Freestyle creation sends the selected name but no Crabbox ownership label or metadata field.internal/providers/islo/backend.go:544-558resolves an operator-supplied id and callsDeleteSandbox.internal/providers/islo/backend.go:563-593uses the same resolver forPauseandResume.internal/providers/islo/backend.go:703-739accepts canonicalcrabbox-...names andisb_<crabbox-name>lease ids without requiring an exact local claim.internal/providers/islo/backend.go:923-934defines the canonical-name predicate as normalized name pluscrabbox-prefix.internal/providers/islo/ssh.go:16-32uses the same claimless resolver for SSH target resolution.internal/providers/islo/backend.go:604-627shows 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:
crabbox-...form.Steps:
crabbox stop --provider freestyle --id fsb_<vm-id>orcrabbox stop --provider islo isb_<crabbox-name>.resolveLeaseIDfetches or lists the provider VM, then treatsisCrabboxFreestyleSandboxName(vm.Name)as the ownership gate when no local claim is present.resolveIsloLeaseIDtreats a canonicalcrabbox-...name, or anisb_lease id wrapping such a name, as enough to build a lease id without looking up an exact local claim.StopcallsDeleteVMorDeleteSandboxand 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
Recommended Remediation
Require strong ownership evidence before destructive Freestyle and Islo operations. Suitable controls include:
stop,pause,resume, SSH resolution, or reused-run operations that mutate an existing provider resource.--reclaimflow 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-49places destructive provider actions against resources Crabbox cannot strongly identify as its own in scope.docs/security.md:361-365says deleting a resource Crabbox cannot strongly identify as its own crosses a safety boundary.docs/security.md:378-389says 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-136anddocs/providers/islo.md:157-160intentionally 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-369callsDeleteVMafterresolveLeaseIDreturns an id.internal/providers/freestyle/backend.go:492-552accepts raw and listed Freestyle identifiers when the fetched/listed VM name passesisCrabboxFreestyleSandboxName;internal/providers/freestyle/backend.go:634-645makes that a normalizedcrabbox-prefix check.internal/providers/freestyle/client.go:42-46andinternal/providers/freestyle/backend.go:382-392show the Freestyle create request carriesname,ports, and optional template data, not a provider-side Crabbox ownership marker.internal/providers/freestyle/backend_test.go:177-206rejects non-canonical unclaimed VMs but accepts an unclaimedfsb_vm123when the provider VM name iscrabbox-repo-abc123.internal/providers/islo/backend.go:549-556callsDeleteSandboxafterresolveIsloLeaseIDreturns a name.internal/providers/islo/backend.go:703-739accepts canonicalcrabbox-...names andisb_<canonical-name>ids without requiring an exact retained local claim;internal/providers/islo/backend.go:923-934makes that a normalizedcrabbox-prefix check.internal/providers/islo/backend.go:604-627shows 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-204rejects non-canonical names but acceptscrabbox-repo-abcdefwithout a retained claim.internal/providers/islo/backend_test.go:1714-1739confirmsPauseandResumecall the provider for a canonical name and reject only a non-Crabbox name.Verification commands:
This returned v3.1
6.0/ Medium and v4.06.8/ Medium.GOCACHE=/tmp/crabbox-verify-4000-gocache GOMODCACHE=/tmp/crabbox-verify-4000-gomodcache go test ./internal/providers/freestyle ./internal/providers/isloThe 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.