> ## 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-L3 — Provenance is generated in-job, not isolated

> In-job attestation steps satisfy SLSA Build L2 but not L3 — L3 requires the trusted reusable workflow.

| Field      | Value                                                          |
| ---------- | -------------------------------------------------------------- |
| Rule ID    | `slsa-build-l3-provenance-isolated`                            |
| Severity   | **MEDIUM**                                                     |
| SLSA level | [v1.2 Build L3](https://slsa.dev/spec/v1.2/build-track-basics) |
| Auto-fix   | ✗                                                              |

## What the check does

Fires when **both** of the following are true:

1. The workflow contains a step using `actions/attest-build-provenance` or
   `actions/attest` (in-job signing).
2. The workflow does **not** also call a reusable workflow under
   `slsa-framework/slsa-github-generator/...`.

## Why it matters

SLSA Build L3 requires that the signing context be **isolated** from
user-defined build steps — an attacker who controls a `run:` step must not be
able to influence what's signed. In-job attestation runs in the same job as
the user's build steps, so any compromise of those steps compromises the
attestation. L3 on GitHub is achieved by the
[`slsa-framework/slsa-github-generator`](https://github.com/slsa-framework/slsa-github-generator)
reusable workflows, whose signing job runs in a trusted context the caller
cannot influence.

## L2-but-not-L3 example

```yaml theme={null}
jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      attestations: write
    steps:
      - uses: actions/checkout@<sha>
      - run: ./build.sh
      - uses: actions/attest-build-provenance@<sha>     # in-job → L2 only
        with: { subject-path: dist/myapp }
```

## L3 example

```yaml theme={null}
jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      digests: ${{ steps.hash.outputs.digests }}
    steps:
      - uses: actions/checkout@<sha>
      - run: ./build.sh
      - id: hash
        run: echo "digests=$(sha256sum dist/myapp | base64 -w0)" >> $GITHUB_OUTPUT

  provenance:
    needs: build
    permissions:
      id-token: write
      contents: read
      actions: read
    uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0
    with:
      base64-subjects: ${{ needs.build.outputs.digests }}
```
