Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Attestation predicate

cicd-sensor generates a predicate intended to be attached to an attestation for CI/CD runtime verification.

Note: There is no settled industry standard for preserving CI/CD runtime evidence in attestations. This predicate format is expected to change — including breaking changes — as the ecosystem converges and based on feedback from real users.

The current format is based on the in-toto runtime-trace v0.1 predicate.

On GitHub-hosted runners, cicd-sensor/cicd-sensor-action uploads this predicate as the cicd-sensor-attestation artifact by default. The file inside the artifact is predicate.json.

The action generates the predicate body only. It does not sign the predicate and does not create a complete in-toto statement by itself. For GitHub Actions, use GitHub Artifact Attestations with actions/attest in a downstream job. The cicd-sensor action creates predicate.json in its post step, so a later step in the same job cannot normally sign it.

What it represents

The predicate is intended to make CI/CD runtime behavior reviewable after the job finishes. It summarizes the runtime evidence that is useful for build, release, and deploy verification.

The wire schema is defined in proto/cicd_sensor/attestation/v1alpha1/runtime_trace_predicate.proto — that file is the source of truth. The v1alpha1 package marks it as pre-stable; breaking changes are expected before it graduates to v1.

Example predicate

This is a shortened example of the predicate generated by cicd-sensor. The actual predicate may contain more network addresses, domains, and rule hits.

{
  "monitorLog": {
    "network": [
      "104.16.11.34",
      "140.82.112.3",
      "151.101.0.223"
    ],
    "https://cicd-sensor.github.io/runtime_trace/detections/v1alpha1": [
      {
        "ruleset_id": "cicd-sensor/baseline",
        "rule_id": "block_curl_to_unknown_host",
        "ruleset_revision": "v0.0.27",
        "action": "terminate",
        "count": 3
      },
      {
        "ruleset_id": "cicd-sensor/testevent",
        "rule_id": "domain_lookup",
        "ruleset_revision": "f1c2a3b",
        "action": "detect",
        "count": 12
      }
    ],
    "https://cicd-sensor.github.io/runtime_trace/domains/v1alpha1": [
      "github.com",
      "registry.npmjs.org",
      "testevent.cicd-sensor.com"
    ],
    "https://cicd-sensor.github.io/runtime_trace/result/v1alpha1": "terminated",
    "https://cicd-sensor.github.io/runtime_trace/job/v1alpha1": {
      "provider": "github",
      "provider_host": "github.com",
      "project_path": "rung/cicd-sensor-demo",
      "commit_sha": "fbc9d31d8cc43000ef3dbe356c74ccc6a88f1aca",
      "ref_name": "main",
      "trigger": "push",
      "actor_name": "octocat",
      "github_run_id": "26220308941",
      "github_job": "build",
      "github_run_attempt": "1",
      "github_runner_tracking_id": "github_75639fba-cf1e-412d-a71d-0b08d01bb13a",
      "github_workflow": "cicd-sensor Demo"
    }
  },
  "metadata": {
    "buildStartedOn": "2026-04-30T12:00:00Z",
    "buildFinishedOn": "2026-04-30T12:05:00Z"
  }
}

The important parts are:

  • network: unique remote IP addresses observed during the job.
  • https://cicd-sensor.github.io/runtime_trace/domains/v1alpha1: unique domain names resolved during the job.
  • https://cicd-sensor.github.io/runtime_trace/detections/v1alpha1: rule hits aggregated per rule. Each entry carries ruleset_id, rule_id, ruleset_revision, action, and count. Includes both detect and terminate actions; collect is excluded. For per-event detail (process tree, argv, payload) see the detection log.
  • https://cicd-sensor.github.io/runtime_trace/result/v1alpha1: final job result (passed / detected / terminated).
  • https://cicd-sensor.github.io/runtime_trace/job/v1alpha1: provider, repository / project, commit, trigger, actor, and provider-specific run / job / workflow identifiers (in-toto runtime-trace standard extension shape, shared with the log envelope’s job).
  • metadata.buildStartedOn / metadata.buildFinishedOn: RFC 3339 timestamps for the monitored window. buildStartedOn is when the agent began observing the job; buildFinishedOn is when the report document was finalized (end of monitoring window).

The runtime_trace/ segment namespaces these extensions to the in-toto runtime-trace predicate, leaving room for cicd-sensor extensions to other predicate types (e.g. a future test_result/...) without colliding. The trailing /v1alpha1 tracks each extension’s schema version independently, so a breaking change to one key bumps only that key and leaves the others stable.

The URI keys are cicd-sensor extension fields. Generic in-toto consumers can ignore unknown extension fields while preserving the evidence for cicd-sensor-aware consumers.

What is not included

collect hits are not included in the predicate. They are runtime event / correlation inputs and are available through the logs, not through the attestation predicate.

Per-event detail (timestamp, rule name, rule condition, process tree, argv, payload, event type) is not embedded in detection entries. Each entry is one aggregated rule hit with count.

File access is not emitted as a dedicated runtime-trace fileAccess field today. cicd-sensor does not yet expose file evidence at the granularity expected by attestation consumers, and an always-empty field would be misleading.

Sign on GitHub Actions

On GitHub Actions, actions/attest is the recommended way to attach this predicate to a signed GitHub Artifact Attestation. The cicd-sensor action only uploads predicate.json as the cicd-sensor-attestation artifact — signing runs in a later step or job that downloads the artifact and feeds it into actions/attest.

- name: Download cicd-sensor runtime-trace predicate
  uses: actions/download-artifact@<latest commit SHA>
  with:
    name: cicd-sensor-attestation
    path: trace

- name: Attest runtime-trace
  uses: actions/attest@<latest commit SHA>
  with:
    subject-checksums: dist/checksums.txt
    predicate-type: https://in-toto.io/attestation/runtime-trace/v0.1
    predicate-path: trace/predicate.json

For container images, swap subject-checksums for subject-name + subject-digest, and set push-to-registry: true when the attestation should also be pushed to the registry.