aflock-ai/cilock-action reference
Source of truth:
cilock-action/action.yml.
The CI/lock GitHub Action wraps a command (or another GitHub Action) and produces signed attestations. It downloads its own variant of the cilock binary at runtime from the cilock-action releases.
- uses: aflock-ai/cilock-action@d39bb9b17e392520f9e7eef17cf355c027a5c283 # v1.0.4
with:
step: build
command: "go build -o myapp ./cmd/myapp"
platform-url: ${{ vars.CILOCK_PLATFORM_URL }} # your administrator-approved originName the destination. With enable-archivista at its default (true), the action signs through the Fulcio derived from platform-url and uploads the evidence to that platform's Archivista. If you omit platform-url, both default to the hosted platform, https://platform.testifysec.com. Set it explicitly to the origin your administrator approved for this repository: the hosted platform, or your private or self-hosted deployment, with the tenant and product already set up there. See the GitHub Actions tutorial for a preflight step that refuses to run without it.
Release pinned in these docs: v1.0.4, commit d39bb9b17e392520f9e7eef17cf355c027a5c283, the release every recipe on this site was checked against. It bundles a CI/lock built from rookery main with govulncheck, inclusion-proof, secretscan, slsa, and the PR #153 atomic-rename trace fix. It is not the newest release: GitHub lists v3.0.8 (2026-06-10, commit f3cf4e0487df980ee6aa3734229b4d2e9fd27a4d), whose platform-url and enable-archivista defaults are the ones described on this page. Read a release's notes before moving a pipeline to it, then pin its commit SHA with the tag in a comment — never a moving tag or major-version ref, which can be re-pointed after you reviewed the workflow.
What v1.0.4 evidence cannot do
v1.0.4 was built from an older rookery, and its evidence does not pass every verification these docs teach:
- It records
command-run/v0.1. The policies in these docs requirehttps://aflock.ai/attestations/command-run/v0.2, and verification refuses a v1.0.4 envelope against them (missing required attestation .../command-run/v0.2). A policy for v1.0.4 evidence has to namecommand-run/v0.1. - Its products and materials carry no file list. They appear only as Merkle
tree:subjects, socilock verify -f <artifact>and anartifactsFromchain cannot pass on its evidence. cilock-argsis mostly dropped. It applies only the--attestor-secretscan-*flags.--attestor-product-include-glob,--trace,--capture-mode,--require-zero-dropsand--material-manifestare silently ignored, and so is theproduct-include-globinput.- An empty
platform-urlmeans the hosted platform.platform-url: ${{ vars.X }}withXunset signs and uploads tohttps://platform.testifysec.com.
For a step that needs artifact (-f) or cross-step (artifactsFrom) verification, run the plain CLI (cilock run) until a release built from current source is published. The action's current source records command-run/v0.2 and inline file lists. It applies the product globs, and it refuses cilock-args, an empty platform-url and the other inputs it would drop. That source is not released yet, so the pin above stays v1.0.4.
Multi-step chain via step names
CI/lock's policy language lets you declare relationships between attested steps. By giving each step a distinct name and declaring artifactsFrom in the verification policy, the verifier enforces that step N's materials match step N-1's products byte-for-byte. This is how CI/lock's own release pipeline chains vendor-cilock-deps → release-build — see Verify the cilock binary.
v1.0.4 evidence cannot pass that check (see above), so run chained steps with the plain CLI in the same workflow. Install cilock on PATH first, outside the checkout, as the release promotion gate does. --material-manifest keeps the file inventory the comparison reads, and the outfiles go under $RUNNER_TEMP so one step's evidence is not an input of the next:
# Step 1 — vendor
- name: vendor-deps
run: |
cilock run --step vendor-deps --material-manifest \
-o "$RUNNER_TEMP/vendor.attestation.json" \
-- go mod vendor
# Step 2 — build; the policy chains app-build to vendor-deps
- name: app-build
run: |
cilock run --step app-build --material-manifest --trace \
-o "$RUNNER_TEMP/build.attestation.json" \
-- go build -mod=vendor -o app ./cmd/app--trace records network egress and file operations for the hermetic Rego gates.
Required permissions
For keyless Sigstore signing (the default), the workflow needs:
permissions:
id-token: write # for OIDC token to Fulcio
contents: read # standard checkoutAdd packages: write if you push container images, etc.
Inputs
Core
One of command or action-ref is required.
| Input | Default | Description |
|---|---|---|
step | (required) | Step name for the attestation. |
command | (none) | Shell command to run. |
action-ref | (none) | GitHub Action to wrap (owner/repo@ref or docker://image). |
action-inputs | (none) | JSON map of inputs to pass to the wrapped action. |
action-env | (none) | Additional env vars for the wrapped action (KEY=VALUE per line). |
Binary
| Input | Default | Description |
|---|---|---|
version | matches action tag | cilock-action release version to download. |
cilock-binary-url | (none) | Custom URL for a pre-built cilock binary. |
cilock-args | (none) | v1.0.4 applies only the --attestor-secretscan-* flags and silently drops the rest. Current source refuses the input. Use the dedicated inputs instead. |
Attestation
| Input | Default | Description |
|---|---|---|
attestations | environment git github | Space-separated attestor list (the shim translates to the comma-separated form the cilock CLI expects). v1.0.4 reads environment,git as one unknown attestor; current source also accepts commas. |
outfile | (none) | Output file for signed envelope. |
workingdir | (none) | Working directory. |
trace | false | Enable command tracing. |
hashes | sha256 | Hash algorithms. |
TestifySec platform
| Input | Default | Description |
|---|---|---|
platform-url | https://platform.testifysec.com | All service URLs are derived from this, including where evidence is uploaded. Set it explicitly to your administrator-approved origin; the default sends evidence to the hosted platform. |
Archivista
Derived from platform-url if not explicitly set.
| Input | Default | Description |
|---|---|---|
enable-archivista | true | Store attestations in Archivista. |
archivista-server | derived from platform-url | Archivista server URL. |
Sigstore / Fulcio
Derived from platform-url if not explicitly set.
| Input | Default | Description |
|---|---|---|
enable-sigstore | true | Enable Sigstore/Fulcio signing. |
fulcio-url | derived from platform-url | Fulcio server URL. |
fulcio-oidc-client-id | sigstore | Fulcio OIDC client ID. |
fulcio-oidc-issuer | https://token.actions.githubusercontent.com | Fulcio OIDC issuer URL. |
fulcio-use-http | true | Use HTTP/REST API for Fulcio (works behind any reverse proxy). |
File signer
| Input | Default | Description |
|---|---|---|
key | (none) | Path to signing key. |
certificate | (none) | Path to signing certificate. |
intermediates | (none) | Comma-separated paths to intermediate certificates. |
KMS
| Input | Default | Description |
|---|---|---|
kms-aws-profile | (none) | AWS profile for KMS signing. |
kms-gcp-credentials-file | (none) | GCP credentials file for KMS signing. |
kms-ref | (none) | KMS key reference URI (awskms://..., gcpkms://..., azurekms://..., hashivault://...). |
Vault
| Input | Default | Description |
|---|---|---|
vault-url | (none) | HashiCorp Vault URL. |
vault-token | (none) | HashiCorp Vault token. |
Timestamps
| Input | Default | Description |
|---|---|---|
timestamp-servers | derived from platform-url | Space-separated TSA URLs. |
Environment filtering
| Input | Default | Description |
|---|---|---|
env-add-sensitive-key | (none) | Comma-separated additional sensitive env var keys. |
env-filter-sensitive-vars | false | Filter (remove) sensitive vars instead of obfuscating. |
Material / Product
| Input | Default | Description |
|---|---|---|
product-include-glob | * | Glob for product file inclusion. |
product-exclude-glob | (none) | Glob for product file exclusion. |
Attestor exports
| Input | Default | Description |
|---|---|---|
attestor-sbom-export | false | Export SBOM as a separate attestation. |
attestor-slsa-export | false | Export SLSA provenance as a separate attestation. |
Builder
| Input | Default | Description |
|---|---|---|
builder-manifest | (none) | Path to a rookery-builder manifest for a custom binary. |
builder-preset | (none) | Builder preset: minimal, cicd, all. |
Outputs
| Output | Description |
|---|---|
git_oid | GitOID of the stored attestation. |
attestation_file | Path to the attestation output. |
Runtime
runs:
using: "node20"
main: "shim/index.js"The shim/index.js Node entry point downloads the variant binary from https://github.com/aflock-ai/cilock-action/releases/{latest/download | download/<tag>} and invokes it with the constructed args.
SLSA Build L3: the provenance workflow
The verifier half ships: cilock verify --slsa-level is in cilock v4.6.0 and later. The builder half ships too: provenance.yml is in cilock-action release v4.6.2, byte for byte the file on main, so pin a commit that contains it. Even so, the standards guidance and the support matrix still list SLSA Build L3 as planned, because the matrix does not yet count this mode as available. Treat this section as early access, not a supported level.
When cilock runs inside your build job, the provenance it signs can reach SLSA Build L2 at most. The job's own steps could forge it. For L3, add a second job. It calls the reusable provenance.yml workflow, runs none of your code, and signs SLSA v1 provenance with its own Fulcio identity:
provenance:
needs: build
permissions: { id-token: write }
uses: aflock-ai/cilock-action/.github/workflows/provenance.yml@<40-hex commit>
with: { subjects: "${{ needs.build.outputs.subjects }}" }- Pin by commit, never by tag. The verifier requires the certificate's Build Signer URI to name the pinned commit, so a tag pin is refused.
subjectsis one<name>=sha256:<hex>per line. Your build job outputs it, for example withecho "subjects=app=sha256:$(sha256sum dist/app | cut -d' ' -f1)" >> "$GITHUB_OUTPUT". The build job must also run cilock in the same workflow run: a subject is accepted only if that run's build collection carries it.- Triggers: the workflow signs only for
push,releaseandworkflow_dispatch. Any other event, fork pull requests andpull_request_targetincluded, fails the job. - Signer: the platform's Fulcio and timestamp authority by default (
platform-url). Setpublic-sigstore: trueto use public Sigstore instead.
Verify with the built-in L3 policy. There is no -p:
cilock verify ./dist/app --slsa-level 3 \
--slsa-builder-digest <the same commit> --slsa-source-repo <owner>/<repo> \
-a provenance.json -a build.json --vsa-outfile vsa.json--slsa-level 3 exits 0 only if all of these hold:
- the provenance's signing certificate names
provenance.ymlat that commit, a GitHub-hosted runner, a writer-only trigger, and your repository; - builder.id, repository, commit and run in the statement equal that certificate's extensions;
buildTypeandexternalParametersare whatprovenance.ymlwrites;- the artifact is among the subjects, and a build collection from the same run, repository and commit carries it.
--format json lists each requirement that failed. The VSA states SLSA_BUILD_LEVEL_3 only on a pass. Add --slsa-roots public-sigstore with --slsa-public-sigstore-ca-roots and --slsa-public-sigstore-timestamp-servers to accept public Sigstore signatures.
Worked examples
The action ships example workflows in examples/github/:
- Wrapping another GitHub Action (e.g.
docker/build-push-action) - Wrapping a shell command
- Multi-step pipeline with downstream verification
The full end-to-end walkthrough lives in the GitHub Actions tutorial.
Reference generated from the product documentation. Match commands and support details to your installed release.