# Running CSO scanners `gstack-cso scan RUN SCANNER [REQUEST.json]` collects candidate evidence through the trusted helper when a matching qualified scanner catalog profile exists. Recognized IDs are `gitleaks`, `osv`, `semgrep`, `zizmor`, `trivy`, and `schemathesis`. Without a qualified profile, the command records a specific prerequisite; static assessment and importing existing CodeQL or other SARIF with `gstack-cso import-sarif RUN REPORT.sarif` remain available. The returned immutable artifact can be read later with `gstack-cso scanner-outcome RUN ARTIFACT_ID`; callers never need to open private state files directly. The source-controlled catalog in [`scanner-images/catalog.json`](../lib/cso/scanner-images/catalog.json) is empty until every release gate produces real evidence. Without a reviewed profile, the command records a specific `not_assessed` prerequisite. Installing a scanner on the host does not enable execution. Each profile binds a Linux platform, immutable image digest, fixed entrypoint, absolute scanner executable, version-probe hash, required adapter capabilities, helper ABI, and the exact isolation-policy hash. The helper validates that catalog when it starts and has no executable fallback. Setup preloads the current platform's qualified scanner digests through the trusted installation helper using anonymous public-registry access. A failed preload or a bounded per-image/setup deadline is a nonfatal prerequisite and never causes an audit to pull. The default is 30 seconds per declared image; `GSTACK_CSO_IMAGE_PULL_TIMEOUT_SECONDS=120` selects a longer allowance (accepted range: 5–300 seconds) while the complete preload remains capped at one hour. Doctor is read-only and reports each scanner unavailable unless its exact catalog digest is already present locally. All scanner processes use Docker containment with a watchdog, shared admission limits, read-only source, bounded output, and an isolated network namespace. Static scanners have no network access, including when the audit omits `--offline`. Semgrep rules and OSV/Trivy databases must be baked into the reviewed image. Their content hashes, scope, and freshness accompany the result. Database refresh is a separately reviewed image acquisition/release operation; scans never download missing assets or switch to unrestricted registry networking. `REQUEST.json` can select an exact scanner `profile`. Schemathesis additionally requires comprehensive mode and an `api` object; `gstack-cso schema` describes its fields. The API harness supplies a bounded OpenAPI 3.0/3.1 JSON document, 1–20 unique path operation IDs, a qualified application runtime, an absolute start command, a numeric loopback port, a legitimate HTTP control, and the source files defining the security boundary. Internal schema references are allowed. Server overrides, remote references/examples, hooks, callbacks, and webhooks are rejected. The application must boot and pass the control before the scanner starts. Application and scanner share only the admitted loopback namespace. An API failure is a candidate, never a reproduced vulnerability or certified repair. Sources needing dependency preparation report that prerequisite until a prepared offline closure is available to the API runner. Each execution probes the scanner version before scanning and validates the retained source both before and after collection. Unknown output, failed diagnostics, a timeout, changed source, or incomplete cleanup cannot become an empty clean result. The helper retains valid partial candidates when the adapter can distinguish them from failed coverage. Scanner output is redacted in place: each located sensitive span becomes a `` marker, so an advisory URL or version string that resembles a phone number or IP address does not discard the whole report. Output that cannot be redacted, including a span split across stdout and stderr, is withheld. Scanner and SARIF collection hold the run's mutation lock and reject finished or interrupted reports. Every outcome is written exclusively under a unique `scanner-outcomes/` name before its coverage record enters the report. The returned `artifact` path is relative to the run directory. Model submissions cannot replace `scanner:*` coverage or certify the imported candidates. The free scanner tests use injected runners and catalogs to verify dispatch and failure handling; they do not claim real image qualification. The opt-in Docker qualification test runs the production adapter, image, watchdog, and isolation policy. It emits the version-output hash only after a representative scan completes without a coverage gap. The reviewed release inputs in [`build-inputs.json`](../lib/cso/scanner-images/build-inputs.json) cover all six scanners on both native platforms. The inputs require immutable base and SBOM-generator image digests, exact source commits and versions, signer workflow identities and digests, and reviewed canonical SLSA/SPDX statement-set digests. The workflow cryptographically re-verifies each image with those repository, source, signer, and predicate constraints before use. Semgrep additionally requires a reviewed local rules bundle. OSV and Trivy require complete offline database bundles with recorded content hashes, freshness, and ecosystem coverage. The release workflow does not invent or silently replace them. None of the upstream scanner images publish GitHub artifact attestations, so the reviewed bases come from [`garrytan/gstack-cso-scanner-bases`](https://github.com/garrytan/gstack-cso-scanner-bases). That repository re-publishes each pinned upstream digest with the offline assets added and signs provenance and an SPDX SBOM with its own workflow. Each tagged release attaches a `pending` `build-inputs.json` candidate; a reviewer independently re-verifies the identities and hashes before the state here changes to `reviewed`. [`cso-scanner-images.yml`](../.github/workflows/cso-scanner-images.yml) lets a dispatched branch run read-only input and contract validation. Image publishing, native amd64/arm64 qualification, attestation verification, embedded-asset hash checks, containment, real-adapter execution, and catalog-proposal generation run only from protected `main` through the `cso-scanner-release` environment. Before enabling qualification or promotion, configure the repository's `cso-scanner-release` GitHub environment with required maintainer reviewers and deployments restricted to protected `main`. GitHub otherwise creates a referenced missing environment without protection rules. Promotion requires an explicit dispatch from `main` and approval through that configured environment. It opens a pull request containing only the proposed source catalog, so code review remains the final authorization step. Pushes and pull requests made with the workflow's `GITHUB_TOKEN` start no workflows, so after pushing the promotion branch the job dispatches [`free-tests.yml`](../.github/workflows/free-tests.yml) on it (`actions: write`); that run reports the required `free-tests` check on the branch head. Opening the PR also requires the repository setting **Allow GitHub Actions to create and approve pull requests** (Settings → Actions → General → Workflow permissions); without it `gh pr create` fails after the push and the dispatch, and a maintainer opens the PR from the pushed branch. `previousRevision` records the prior compatible catalog for rollback and must still equal the current `main` catalog when promotion runs. Scanner flags follow the primary documentation linked in [`scanners.ts`](../lib/cso/scanners.ts). Offline qualification must exercise the exact chosen version: OSV's maintainers documented a cache-location regression in 2.5.0, which demonstrates why a version string alone is insufficient. [OSV issue #2983](https://github.com/google/osv-scanner/issues/2983). Trivy uses an explicit memory scan cache alongside read-only baked databases and a baked misconfiguration checks bundle. Schemathesis 4.26 and later repeat fuzzing until `--max-time` is spent, so the adapter sets that budget to three quarters of the scanner deadline and treats a `max_time` stop as complete only when every selected operation was exercised. [Trivy filesystem reference](https://trivy.dev/docs/v0.68/guide/references/configuration/cli/trivy_filesystem/).