> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pipefort.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SLSA-BUILD-L2 — Provenance/signing step is missing id-token: write

> Keyless signing tooling (attest/cosign/slsa-generator) needs the OIDC token permission.

| Field      | Value                                                          |
| ---------- | -------------------------------------------------------------- |
| Rule ID    | `slsa-build-l2-oidc-token-scope`                               |
| Severity   | **MEDIUM**                                                     |
| SLSA level | [v1.2 Build L2](https://slsa.dev/spec/v1.2/build-track-basics) |
| Auto-fix   | ✓ ([what it does](#auto-fix))                                  |

## What the check does

Fires on any job that uses one of:

* `actions/attest-build-provenance@…` / `actions/attest@…`
* `sigstore/cosign-installer@…` (or a `cosign sign` run-line)
* A reusable workflow call under `slsa-framework/slsa-github-generator/...`

…without declaring `permissions: id-token: write` either at the job level or
at the workflow level.

## Why it matters

Sigstore's keyless signing path mints a short-lived signing certificate from
the workflow's OIDC token. GitHub does not issue that token unless the job
(or workflow) explicitly requests `id-token: write`. Without the permission,
the signing step fails — and SLSA Build L2's "signed provenance" requirement
is unmet.

## Vulnerable example

```yaml theme={null}
jobs:
  sign:
    runs-on: ubuntu-latest
    permissions:
      contents: read              # ← no id-token: write
    steps:
      - uses: actions/attest-build-provenance@<sha>
```

## Safe example

```yaml theme={null}
jobs:
  sign:
    runs-on: ubuntu-latest
    permissions:
      id-token: write             # OIDC token
      attestations: write         # upload attestation
      contents: read
    steps:
      - uses: actions/attest-build-provenance@<sha>
```

## Auto-fix

`--fix` locates the job containing the offending signing step and:

* If the job already has a `permissions:` mapping, appends `id-token: write` (or upgrades an existing `id-token: read` entry).
* If the job has a scalar `permissions:` (e.g. `read-all`), replaces it with `{ contents: read, id-token: write }`.
* If the job has no `permissions:` block at all, adds one with `{ contents: read, id-token: write }`.

The fixer does not add `attestations: write` — that's only required for `actions/attest*` flows, and many signing jobs don't need it. Add it manually if your tooling reports a missing-permission error after the fix.
