A sweep is a plan-then-execute fan-out. Planning and synthesis are side-effect free, so you can inspect the whole thing before any credit is spent. Execution is a separate call with its own scope.

Dependency sweeps

One sandbox per package, results synthesized into a sequenced upgrade path.

Plan (free)

POST /api/v1/sweeps/plan — scope loops:write.

{ "packages": ["lodash@4.17.20", "express@4.17.1"], "budgetMicros": 1000000 }

Returns { "plan": { …assignments… } }. 400 packages_required when the list is empty. Nothing is reserved and no sandbox is created.

Synthesize (free)

POST /api/v1/sweeps/synthesize — scope loops:read.

{ "assignments": [ … ], "results": [ … ] }

Returns { "synthesis": …, "summary": … }. 400 assignments_required when the assignments are missing.

Run (spends)

POST /api/v1/sweeps/run — scope assessments:create.

{ "packages": ["lodash@4.17.20"], "target": "https://staging.example.com",
  "budgetMicros": 1000000, "maxSandboxes": 3 }

Each assignment becomes one ordinary assessment through the same launch path the sandbox page uses, so metering, model routing and the runner protocol are unchanged. Fan-out is bounded by the platform's batch and global limits, and packages past the plan's capacity come back as the next wave rather than disappearing.

Status error Meaning
400 packages_required no packages supplied
400 no_sweepable_packages nothing in the list could be swept; includes the plan
409 target_not_ready no registered target and none passed
402 insufficient_credits balance or per-sandbox budget too low

Why the scopes differ. loops:write can describe work but must not be able to spend. Running a sweep reserves credit and creates sandboxes, so it requires assessments:create, the same boundary as launching one assessment by hand.

Compromise and privilege-escalation sweeps

This answers a different question from a login-form scan: if an attacker already holds a credential, what does it reach? Cloud control planes, the deploy pipeline, production data, secret stores, and other tenants.

The module never asserts reach it did not observe. An unproven path is unknown, not reachable.

Assumed footholds

POST /api/v1/compromise/plan takes a profile:

Profile Assumes
developer-laptop A local shell as the developer, including their SSO session and CLI caches; credentials in shell history, dotfiles or a checked-out .env; network position inside the corporate VPN if one is in use
ci-runner The runner's build-time secrets and its repository token; the ability to modify build output and any artifact it publishes
service-account A long-lived token for one service with whatever scopes it was granted; no interactive user session

An unknown profile returns unknown compromise profile "<name>" with no assignments.

Stages, in attacker order

Every stage is included even when the operator supplies a narrow instruction, because an attacker does not skip a stage that works:

  1. Harvest additional credentials — cloud CLI config, kubectl contexts, database URLs, SSH keys, browser session stores, CI tokens in dotfiles, secrets in shell history.
  2. Reach the cloud control plane — read-only enumeration: list roles, read parameter or secret stores, describe instances, check whether a broader role can be assumed. No modification.
  3. Reach the deploy pipeline — whether the foothold can push to a protected branch, trigger a deploy, alter a build step or write a release artifact.
  4. Reach production data — prove reach with a scoped read against a non-destructive endpoint, never a write.
  5. Move laterally, including across tenants — whether the identity reaches another team's or tenant's resources through shared infrastructure, shared secrets, or an over-broad service account.

Reach tiers

Findings land in one of, ordered by implied damage: production-control, production-data, deploy-pipeline, cloud-control, internal-only.

Routes and scopes

Route Scope Effect
POST /api/v1/compromise/plan loops:write free; returns staged assignments
POST /api/v1/compromise/synthesize loops:read free; summarizes observed reach
POST /api/v1/compromise/run assessments:create spends; dispatches stages in attacker order

Execution runs one stage at a time. A later stage proceeds only on what the earlier stages actually proved, and each dispatched assessment carries a deterministic idempotency key so a retried run does not double-spend.

Related recipes

critical-dependency-remediation is the recipe that wraps the dependency sweep: collect advisories, group fixes into patch/minor/major risk bands, open one branch per group, deploy a preview, launch a focused runtime assessment, verify the finding in a fresh sandbox, then open a pull request with evidence and rollback steps.

An agent-driven recipe is an orchestration contract, not a sandbox. The coding agent edits the repository; Offense supplies disposable runtime validation, evidence and retests.