Skip to content

fix: require exact claims for direct cloud cleanup#817

Open
steipete wants to merge 7 commits into
mainfrom
codex/issue811-provider-ownership
Open

fix: require exact claims for direct cloud cleanup#817
steipete wants to merge 7 commits into
mainfrom
codex/issue811-provider-ownership

Conversation

@steipete

@steipete steipete commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • require canonical lease IDs before DigitalOcean, Linode, Vultr, or Scaleway resources enter Crabbox inventory
  • require exact provider/account-or-project/resource-bound local claims before reuse, stop, or cleanup
  • keep claimless canonical resources read-only until explicit --reclaim adoption; never synthesize destructive ownership from remote tags
  • preserve interrupted-create recovery while validating the exact stored provider identity, and prevent read-only resolve paths from writing claims
  • document the ownership boundary in provider and stop documentation

Closes #811

Verification

  • go test -race ./internal/providers/digitalocean ./internal/providers/linode ./internal/providers/scaleway ./internal/providers/vultr -count=1 — pass.
  • Focused CLI/provider race tests for exact claims, canonical-ID alias denial, and read-only status resolution — pass.
  • go vet ./internal/cli ./internal/providers/digitalocean ./internal/providers/linode ./internal/providers/scaleway ./internal/providers/vultr — pass.
  • scripts/check-docs.sh — pass; 53 command docs, 71 provider-matrix rows, 207 Markdown files, and the generated docs site verified.
  • Exact-branch autoreview — clean after fixing stale-claim status handling (0.79).
  • All 11 exact-head hosted checks pass, including Go, Release Check, Apple VZ, and CodeQL.

Exact-head live proof

Candidate: 5a2ba9dd6314b638198e6a2928b3914c18865dfd

  • DigitalOcean: authenticated from empty inventory; provisioned a real Droplet and managed SSH key; reached ready; ran echo ok over SSH; listed and stopped the exact claim; verified final inventory [] and no managed-key residue.
  • Linode: authenticated from empty inventory; provisioned a real instance; reached ready; ran echo ok over SSH; listed and stopped the exact claim; verified final inventory [] and no local-key residue.
  • Scaleway: authenticated from empty inventory; provisioned a real project/zone-bound instance and managed SSH key; reached ready; ran echo ok over SSH; listed and stopped the exact claim; verified final inventory [] and no managed-key residue.
  • Vultr: pending because an authenticated API credential is not yet available. Keep this PR unmerged until the same exact-head create/use/stop/empty-inventory proof passes for Vultr, or that provider-specific gate is explicitly waived.

@clawsweeper

clawsweeper Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 4, 2026, 2:13 PM ET / 18:13 UTC.

Summary
The PR hardens DigitalOcean, Linode, Scaleway, and Vultr direct-provider inventory, resolve, status-wait, reclaim, stop, and cleanup paths to require canonical lease IDs plus exact local provider/resource claims before destructive actions.

Reproducibility: yes. The linked security issue and current main source show weak non-canonical lease label acceptance in provider ownership predicates that feed destructive cleanup paths; live destructive cloud reproduction was not run in this read-only review.

Review metrics: 4 noteworthy metrics.

  • Direct providers changed: 4 providers. DigitalOcean, Linode, Scaleway, and Vultr all change ownership checks before destructive lifecycle operations.
  • Diff surface: 28 files, +1010/-264. The branch spans provider adapters, CLI status behavior, docs, and regression tests, so merge review must cover multiple ownership paths.
  • Provider live proof: 3 summarized, 1 pending. The PR body summarizes DigitalOcean, Linode, and Scaleway proof while Vultr remains an explicit merge gate.
  • Release-owned file changed: 1 CHANGELOG.md edit. The branch still touches a release-owned file that normal PRs should leave to the release process.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #811
Summary: This PR is the candidate fix for the direct-provider cleanup security issue.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🦪 silver shellfish
Patch quality: 🐚 platinum hermit
Result: blocked until stronger real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Provide redacted current-head Vultr live proof or obtain an explicit maintainer waiver.
  • Remove the release-owned CHANGELOG.md entry and keep release-note context in the PR body or commit messages.

Proof guidance:

  • [P1] Needs stronger real behavior proof before merge: The PR body summarizes live proof for DigitalOcean, Linode, and Scaleway but names an older proof candidate and explicitly leaves Vultr pending or requiring waiver. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Risk before merge

  • [P1] Vultr current-head live create/use/list/stop/empty-inventory proof or an explicit maintainer waiver is still pending for a changed destructive provider backend.
  • [P1] The stricter exact-claim model intentionally makes claimless or mismatched direct-provider resources read-only until explicit --reclaim, which can break existing stop or cleanup workflows after upgrade.
  • [P1] The PR body's provider-live proof candidate is older than the latest head, so maintainers need current-head proof coverage or a clear waiver before merging this security-sensitive provider change.

Maintainer options:

  1. Require Vultr proof or waiver (recommended)
    Ask for redacted current-head Vultr live create/use/list/stop/empty-inventory proof, or an explicit maintainer waiver that names why that provider gate can be skipped.
  2. Accept fail-closed upgrade behavior
    Maintainers can choose to land the stricter reclaim policy knowing claimless or mismatched resources become read-only until explicit adoption.
  3. Pause until proof catches up
    If Vultr proof or waiver is not available, keep the PR paused rather than merging partial live coverage for a destructive provider boundary.

Next step before merge

  • [P1] Human follow-up is needed because automation cannot provide Vultr live cloud proof or accept the fail-closed compatibility/security policy for maintainers.

Security
Cleared: No introduced code-level security regression was found in the inspected latest-head ownership checks; the remaining security-sensitive merge gate is Vultr live proof or waiver.

Review findings

  • [P3] Remove the release-owned changelog entry — CHANGELOG.md:12
Review details

Best possible solution:

Land the exact-claim hardening after current-head Vultr proof or waiver, explicit maintainer acceptance of the fail-closed reclaim policy, routine checks on the final head, and removal of release-owned changelog edits.

Do we have a high-confidence way to reproduce the issue?

Yes. The linked security issue and current main source show weak non-canonical lease label acceptance in provider ownership predicates that feed destructive cleanup paths; live destructive cloud reproduction was not run in this read-only review.

Is this the best way to solve the issue?

Yes, pending merge gates. Exact local provider/resource claims are the narrow maintainable safety boundary, but Vultr live proof or waiver and explicit upgrade-policy acceptance remain necessary before merge.

Full review comments:

  • [P3] Remove the release-owned changelog entry — CHANGELOG.md:12
    CHANGELOG.md is release-owned for normal PRs, and this branch still adds the direct-provider claim-hardening release note under 0.35.1. This repeats the prior ClawSweeper finding; keep the release-note context in the PR body or commit messages so the release process owns the changelog.
    Confidence: 0.95

Overall correctness: patch is correct
Overall confidence: 0.84

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against e1732002dad3.

Label changes

Label justifications:

  • P0: The PR addresses a security/data-loss boundary where weak ownership evidence can lead to destructive direct-provider deletion.
  • merge-risk: 🚨 compatibility: Existing direct-provider resources without exact local claims may stop resolving for cleanup or stop after upgrade.
  • merge-risk: 🚨 security-boundary: The diff modifies the provider ownership checks that gate destructive cloud API calls.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🐚 platinum hermit.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The PR body summarizes live proof for DigitalOcean, Linode, and Scaleway but names an older proof candidate and explicitly leaves Vultr pending or requiring waiver. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

Acceptance criteria:

  • [P1] go test -race ./internal/cli ./internal/providers/digitalocean ./internal/providers/linode ./internal/providers/vultr ./internal/providers/scaleway.
  • [P1] go vet ./internal/cli ./internal/providers/digitalocean ./internal/providers/linode ./internal/providers/vultr ./internal/providers/scaleway.
  • [P1] scripts/check-docs.sh.

What I checked:

  • Repository policy read: AGENTS.md was read fully; its provider-adapter boundary, security/configuration guidance, and release-owned/generated-output cautions are relevant to this provider cleanup hardening review. (AGENTS.md:1, e1732002dad3)
  • Security boundary: The repository security policy treats destructive provider actions against resources Crabbox cannot strongly identify as its own as an in-scope boundary. (SECURITY.md:44, e1732002dad3)
  • Current-main source reproduction: Current main accepts any non-empty lease label in the DigitalOcean, Linode, and Vultr ownership validators instead of requiring core.IsCanonicalLeaseID, matching the reported weak-label cleanup class. (internal/providers/digitalocean/tags.go:314, e1732002dad3)
  • PR canonical ownership checks: The PR head changes the affected ownership predicates to require core.IsCanonicalLeaseID before provider inventory is treated as Crabbox-owned. (internal/providers/digitalocean/tags.go:314, 9d074c707f39)
  • Exact-claim release guard: The PR head rejects DigitalOcean release when no exact local claim exists and requires matching account and resource identity before non-read-only claim use. (internal/providers/digitalocean/backend.go:701, 9d074c707f39)
  • Read-only status guard: The PR head resolves SSH status with NoLocalStateMutations and calls provider-specific StatusTouchClaimMatches before status --wait touches a lease. (internal/cli/status.go:67, 9d074c707f39)

Likely related people:

  • coygeek: Targeted symbol history traces the DigitalOcean, Linode, and Vultr ownership validators to direct-provider implementation commits by Coy Geek. (role: direct provider introducer; confidence: high; commits: aff04c9f19a3, d6be66ec65cf, f36b6a9ef3fc; files: internal/providers/digitalocean/tags.go, internal/providers/linode/tags.go, internal/providers/vultr/tags.go)
  • steipete: Targeted symbol history traces the Scaleway ownership validator to Peter Steinberger's Scaleway direct-provider commit, and current path history includes release preparation touching provider files. (role: direct provider and recent release-area contributor; confidence: medium; commits: 5fe673c90673, 192e382e9044; files: internal/providers/scaleway/provider.go, CHANGELOG.md)
  • vincentkoc: Recent current-main history includes provider cleanup and ownership hardening work by Vincent Koc, and PR discussion shows a follow-up for the Vultr rebinding concern. (role: recent adjacent cleanup contributor and reviewer; confidence: medium; commits: 8002e15e3089, 9970a5ea5154, 7fd07050f275; files: internal/providers/vultr/backend.go, internal/providers/hetzner/backend.go, internal/cli/hcloud.go)
  • aki-luxor: The merged status-wait PR established the read-only SSH status resolution contract that this PR preserves while adding exact-claim touch gating. (role: adjacent status behavior contributor; confidence: medium; commits: 12d32c9e294f; files: internal/cli/status.go, internal/cli/provider_backend.go)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (6 earlier review cycles)
  • reviewed 2026-07-04T05:52:23.341Z sha 25d50a9 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-04T09:54:29.242Z sha 5a2ba9d :: needs real behavior proof before merge. :: [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-04T10:01:07.210Z sha 5a2ba9d :: needs real behavior proof before merge. :: [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-04T10:10:08.631Z sha 5a2ba9d :: needs real behavior proof before merge. :: [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-04T11:30:48.615Z sha 5a2ba9d :: needs real behavior proof before merge. :: [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-04T13:03:57.837Z sha 17c55cf :: needs real behavior proof before merge. :: [P3] Remove the release-owned changelog section

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a332ab6b8d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

preserveDigitalOceanKeyIdentity(server.Labels, claim.Labels)
} else if req.ReleaseOnly {
return core.LeaseTarget{}, core.Exit(2, "digitalocean lease=%s has no exact local claim; refusing release", leaseID)
} else if !req.NoLocalStateMutations {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Allow status-only resolves to remain read-only

When crabbox status resolves a live but claimless DigitalOcean lease, it calls ResolveRequest{StatusOnly: true} from internal/cli/status.go without Repo, Reclaim, or NoLocalStateMutations; this new guard therefore returns the use --reclaim error even though status is a read-only inspection path and the status command has no --reclaim flag. That leaves canonical claimless resources visible in list but impossible to inspect with status; treat non-waiting StatusOnly resolves as read-only here or have the caller set NoLocalStateMutations.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P0 Emergency: data loss, security bypass, crash loop, or unusable core runtime. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. labels Jul 3, 2026
@vincentkoc vincentkoc force-pushed the codex/issue811-provider-ownership branch from a332ab6 to ee49c68 Compare July 4, 2026 03:42
@vincentkoc

Copy link
Copy Markdown
Member

Updated this PR to keep SSH-provider status resolves read-only on current head ee49c68b6bed9592623457c8859561c0b85650ef.

Validation now green on this head:

  • local: go test -race ./internal/cli ./internal/providers/digitalocean ./internal/providers/linode ./internal/providers/vultr ./internal/providers/scaleway
  • local: go vet ./...
  • local: scripts/check-docs.sh
  • hosted: CI and CodeQL all green

Remaining proof gate is still provider-live: Vultr current-head create/use/stop/empty-inventory proof is unavailable here because no VULTR_API_KEY / CRABBOX_VULTR_API_KEY is present. The PR body now marks older DigitalOcean/Linode/Scaleway live proof as stale after the head update.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Jul 4, 2026
@steipete steipete force-pushed the codex/issue811-provider-ownership branch from ee49c68 to 7d58d5c Compare July 4, 2026 05:06

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7d58d5c6d5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +420 to 421
if req.Repo.Root != "" && !req.NoLocalStateMutations {
if _, err := core.ClaimLeaseTargetForRepoConfigIfUnchanged(leaseID, server.Labels["slug"], b.Cfg, server, ssh, req.Repo.Root, b.Cfg.IdleTimeout, req.Reclaim, claim, claimExists); err != nil {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject cloudless Vultr claims before rebinding

When an exact Vultr claim exists but has an empty CloudID and no valid recovery marker, this non-read-only resolve path still falls through and rewrites the claim with the live instance's ID. That lets a legacy or corrupt local claim become resource-bound without --reclaim, so a later stop can delete the instance based only on matching remote tags; the other direct-cloud providers now reject cloudless claims unless they are explicit recovery states. Please add the same claim.CloudID == "" recovery-state validation before this write.

Useful? React with 👍 / 👎.

@steipete

steipete commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

Updated the PR body with redacted exact-head proof for 7d58d5c6d53e7a71247faa7c9b872d6ae05af57b.

  • DigitalOcean, Linode, and Scaleway each passed authenticated create/use/list/exact-stop/empty-inventory proof on this head, with managed key cleanup verified.
  • The fail-closed reclaim migration is intentional maintainer policy: claimless or mismatched resources remain read-only until explicit, conflict-safe --reclaim adoption binds the exact provider scope and resource.
  • Vultr remains an explicit merge gate; no provider-specific waiver is being claimed.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Jul 4, 2026
@vincentkoc

Copy link
Copy Markdown
Member

Pushed a maintainer follow-up for the Vultr finding on current head 25d50a9e34466d90331005267323c8a608278c52.

What changed:

  • Reject a Vultr local claim with empty CloudID before mutating resolve can bind it to a live instance, unless it is the existing ambiguous-create recovery state.
  • Added TestResolveRejectsCloudlessClaimBeforeRebinding to prove the cloudless claim stays cloudless and resolution fails instead of rewriting local ownership.

Local validation on this head:

go test -race ./internal/providers/vultr -run 'TestResolveRejectsCloudlessClaimBeforeRebinding|TestResolveReadOnlyDoesNotClaimVisibleInstance|TestReleaseOnlyResolveFallsBackToLocalClaimBySlug|TestAmbiguousCreateRecoveryDeletesAfterLiveInstanceIsFound' -count=1
# ok github.com/openclaw/crabbox/internal/providers/vultr 1.600s

go test -race ./internal/cli ./internal/providers/digitalocean ./internal/providers/linode ./internal/providers/vultr ./internal/providers/scaleway
# ok github.com/openclaw/crabbox/internal/cli 141.891s
# ok github.com/openclaw/crabbox/internal/providers/digitalocean 3.950s
# ok github.com/openclaw/crabbox/internal/providers/linode 5.401s
# ok github.com/openclaw/crabbox/internal/providers/vultr 4.204s
# ok github.com/openclaw/crabbox/internal/providers/scaleway 4.772s

go vet ./...
# clean

scripts/check-docs.sh
# checked 52 command docs: command surface ok
# checked provider matrix: 71 providers
# checked 205 markdown files: internal links ok
# built docs site: dist/docs-site

This removes the code blocker from the prior review. The remaining merge gate is still exact-head Vultr live proof or an explicit maintainer waiver; no Vultr token is present in this shell, so I am not claiming provider-live proof.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@steipete steipete force-pushed the codex/issue811-provider-ownership branch from 25d50a9 to 5a2ba9d Compare July 4, 2026 09:48
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels Jul 4, 2026
@steipete steipete force-pushed the codex/issue811-provider-ownership branch from 5a2ba9d to 17c55cf Compare July 4, 2026 12:57

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 17c55cfe49

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/cli/status.go Outdated
Comment on lines +149 to +151
return claimed && exact &&
claim.ProviderScope == providerScope &&
resourceID != "" && claim.CloudID == resourceID, nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require provider identity before touching status leases

When crabbox status --wait resolves a direct-cloud lease it now uses NoLocalStateMutations, so the provider-side resolve intentionally skips the exact-claim account/project checks; this helper then decides whether to call Touch, but it only verifies provider scope and CloudID. An exact legacy or corrupt DigitalOcean/Linode/Vultr/Scaleway claim with the same resource ID but missing or mismatched account/project labels would still return true, causing status --wait to mutate remote TTL/last-touched tags even though normal resolve/stop paths would reject that claim as not account/project-bound. Include the provider identity labels in this predicate or avoid touching when the claim has not passed the same ownership checks.

Useful? React with 👍 / 👎.

@steipete steipete force-pushed the codex/issue811-provider-ownership branch from 17c55cf to 9d074c7 Compare July 4, 2026 18:07

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9d074c707f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}
} else {
switch claim.Labels["recovery"] {
case "ambiguous-create", "ambiguous-create-response", "ambiguous-key-create", "rollback-cleanup", "rollback-key-cleanup":

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject key-only Scaleway recoveries for live servers

When a live Scaleway server is resolved, targetFromServer and deleteServer use this helper to decide whether an exact claim proves ownership. Allowing empty-CloudID ambiguous-key-create or rollback-key-cleanup claims here treats recovery states that were recorded before any server identity existed, or only for SSH-key cleanup, as proof of server ownership. If a tagged server with the same lease/slug/project exists, it can then be rebound or deleted without an exact server-bound claim; only server-create ambiguous states should be accepted when server.CloudID is non-empty.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. P0 Emergency: data loss, security bypass, crash loop, or unusable core runtime. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[security] Direct-provider cleanup trusts non-canonical lease labels before destructive deletes

2 participants