Standards guidance
A ceiling is the highest level this evidence could support. It is not a verified level: a SLSA Build level needs an assessment of the build platform, and an ALPS level needs an independent verifier.
cilock run and cilock verify print a standards block and, under --json / --format json, a typed standards object (schema cilock.standards-guidance/v1) with slsa_build.ceiling, alps.ceiling, verified_level: null and an ordered next_steps[]. When a coding agent drives cilock, the steps are phrased as imperative actions for the agent.
SLSA Build
Specification: SLSA v1.2 Build track
| Level | Status | Requires | How cilock observes it |
|---|---|---|---|
| L1 | available | Provenance exists for the build. | The run selected the slsa attestor (-a slsa) and signed the collection. |
| L2 | available | Provenance is generated and signed by a hosted build platform and timestamped. | The signing leaf is a keyless CI workload identity (GitHub Actions, gitlab.com, Buildkite, CircleCI or a Kubernetes service account, recognized by its OIDC issuer) and its runner-environment names a provider-hosted runner, and the envelope carries an RFC 3161 timestamp. On a self-hosted runner, CircleCI or Kubernetes the level depends on whether you treat your runner operator as the build platform (formal/slsa-tracks interpretation I2), so cilock reports those as not provider-hosted. |
| L3 | planned | Provenance is unforgeable by the tenant's build steps: it is signed under a builder identity no build step can obtain, on an isolated, ephemeral runner. | The signing leaf's Build Signer URI names the isolated provenance workflow (builder_identity on the slsa-provenance-workflow step), not the tenant workflow. GitHub Actions only: other CI signer identities are pipeline-wide. |
Not reachable on some CI platforms
- L3 on gitlab, buildkite, circleci, kubernetes: not reachable on this CI today: its signer identity is pipeline-wide, so a build step can mint it. The only paths are the GitHub Actions provenance workflow (coming) and cilockd on a runner you operate (not yet available).
Next steps
slsa-provenance-attestor (to L1, available)
SLSA Build L1 needs provenance, and this run produced none.
Action: Add the slsa attestor to the cilock run invocation.
cilock run --step build -a slsa -- <your build command>
slsa-hosted-runner (to L2, available)
SLSA Build L2 needs a hosted build platform. A laptop is never one. On a self-hosted runner, CircleCI or Kubernetes it depends on whether you treat your runner operator as the build platform; a provider-hosted runner (GitHub-hosted, gitlab.com SaaS, Buildkite hosted) removes that question.
Action: Run the build on a provider-hosted runner (GitHub-hosted, gitlab.com SaaS, or Buildkite hosted), or decide that your runner operator counts as the build platform and record why.
jobs:
build:
runs-on: ubuntu-latest
slsa-workflow-identity (to L2, available)
SLSA Build L2 needs provenance signed by the platform's workload identity, not a key or a person's session.
Action: Sign keyless with your CI's workload OIDC identity. GitHub Actions works with the platform Fulcio or public Sigstore (grant id-token: write and use cilock-action). gitlab.com, Buildkite hosted and CircleCI cloud work with the platform Fulcio from the CI/lock release after 4.5.0, which fetches their job token itself (on gitlab.com declare an id_tokens entry with audience sigstore); with CI/lock 4.5.0 or earlier, and on Kubernetes, sign through public Sigstore Fulcio.
permissions:
id-token: write
contents: read
steps:
with:
step: build
command: "<your build command>"
attestations: environment git github slsa
Docs: https://cilock.dev/getting-started/quickstart-ci
slsa-timestamp (to L2, available)
The envelope carries no trusted timestamp, so a short-lived keyless leaf cannot be verified later.
Action: Sign with a timestamp authority.
cilock run --step build -a slsa --timestamp-servers <tsa-url> -- <your build command>
slsa-provenance-workflow (to L3, planned)
Inline provenance is signed by the same workflow identity the build steps can mint, so a build step can forge it (issue #9822). L3 needs a separate builder identity, which only GitHub Actions' reusable-workflow identity provides.
Action: Coming: the isolated cilock provenance workflow. When it ships, add a provenance job that needs the build job and signs the build's subjects under its own identity.
Not yet published. Run and verify output withhold this snippet until it ships:
provenance:
needs: build
permissions:
id-token: write
uses: aflock-ai/cilock-action/.github/workflows/provenance.yml@{{pin}}
with:
subjects: ${{ needs.build.outputs.subjects }}
ALPS
Specification: ALPS 0.1
| Level | Status | Requires | How cilock observes it |
|---|---|---|---|
| ALPS-0 | available | The statement is signed and bound to the commit. | The run signed the collection. |
| ALPS-1 | available | The signing leaf chains to the platform root and names a non-human agent or workload principal, and the envelope is timestamped. | Not reported by cilock yet. A leaf that names an agent or a CI workflow does not show the platform issued it (the same name appears under public Sigstore or a BYO CA), and authenticating the platform root is a separate design, so run and verify report ALPS-0 at most. A verifier policy that pins the platform root can still require it. |
| ALPS-2 | planned | The run happened inside an enforced sandbox, and a non-agent observer signed the boundary it ran in. | Nothing yet: the alps-evidence predicate has no boundary field. See docs/design/alps-2-boundary-attestation.md. |
| ALPS-3 | future | requires cilockd (not yet available) | Nothing yet. |
Next steps
alps-agent-identity (to ALPS-1, available)
ALPS 1 needs a non-human principal the platform issued. This run signed with a local key or a human session, so the evidence cannot say an agent signed it.
Action: Enroll an agent identity for this machine and approve it in the browser.
cilock enroll agent
alps-workflow-identity (to ALPS-1, available)
ALPS 1 needs a non-human principal the platform issued. In CI that is the job's workload OIDC identity, which this job did not sign with.
Action: Sign with the job's workload identity against the platform Fulcio. On GitHub Actions grant the job id-token: write. On gitlab.com, Buildkite or CircleCI use a CI/lock newer than 4.5.0, which fetches the job token itself (on gitlab.com declare an id_tokens entry with audience sigstore). Other CI has no platform-issued identity yet.
alps-timestamp (to ALPS-1, available)
The envelope carries no trusted timestamp, so a short-lived identity cannot be verified later.
Action: Sign with a timestamp authority.
cilock run --step <step> --timestamp-servers <tsa-url> -- <command>
alps-boundary-attestation (to ALPS-2, planned)
ALPS 2 needs an enforced sandbox and a non-agent observer that signs the boundary. cilock records no boundary today, so no run can present ALPS 2 evidence yet.
Action: Coming: boundary attestation in alps-evidence. Until it ships, run the agent inside the recommended sandbox so the run already has the boundary the attestation will record.