diff --git a/.circleci/config.yml b/.circleci/config.yml index edcb3edfc2e..51c4625c8af 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -11,10 +11,10 @@ parameters: type: string default: cimg/base:2026.03 # Pinned ci-base-clang image (cimg/base + clang/llvm-dev/libclang-dev) for Rust jobs. - # Provenance is verified by .github/workflows/verify-ci-base-clang-attestation.yml. + # Provenance is verified by .github/workflows/security.yml. rust_base_image: type: string - default: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-base-clang@sha256:852cb2dcd64eb5c039abf857a2217f341351eb7e4ef1a989ba9eefb86f158105 + default: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-base-clang@sha256:00f641689576d7393d83f6fd49fe1592006148305999f1ba2fc4f1f9d2e8a342 base_image: type: string default: default diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml new file mode 100644 index 00000000000..869f761b967 --- /dev/null +++ b/.github/workflows/security.yml @@ -0,0 +1,54 @@ +name: security + +on: + push: + branches: + - 'develop' + paths: + - '.circleci/config.yml' + - '.github/workflows/security.yml' + pull_request: + branches: + - 'develop' + paths: + - '.circleci/config.yml' + - '.github/workflows/security.yml' + workflow_dispatch: + +jobs: + verify: + name: verify provenance ci-base-clang + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Harden the runner + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2 + with: + egress-policy: audit + - name: Checkout + uses: actions/checkout@71cf2267d89c5cb81562390fa70a37fa40b1305e # v6 + - name: Extract pinned image reference + id: extract + run: | + set -euo pipefail + IMAGE_REF=$(grep -A2 '^ rust_base_image:' .circleci/config.yml \ + | grep -oE 'us-docker\.pkg\.dev/oplabs-tools-artifacts/images/ci-base-clang@sha256:[0-9a-f]{64}' \ + | head -n1) + if [[ -z "${IMAGE_REF}" ]]; then + echo "Could not extract ci-base-clang image reference from .circleci/config.yml" >&2 + exit 1 + fi + echo "image=${IMAGE_REF}" >> "$GITHUB_OUTPUT" + echo "Pinned image: ${IMAGE_REF}" + - name: Verify provenance attestation + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + IMAGE_REF: ${{ steps.extract.outputs.image }} + run: | + set -euo pipefail + gh attestation verify "oci://${IMAGE_REF}" \ + --bundle-from-oci \ + --owner ethereum-optimism \ + --signer-repo ethereum-optimism/factory \ + --source-ref refs/heads/develop