From 3b8af4d341b10e7267c9362cda4c36548b102fba Mon Sep 17 00:00:00 2001 From: Logan Yang Date: Wed, 13 May 2026 17:09:14 -0700 Subject: [PATCH] ci(release): publish artifact attestations for release assets (#2431) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a step that signs main.js, manifest.json, and styles.css with the workflow's OIDC identity and publishes the attestation to Sigstore's public transparency log via actions/attest-build-provenance@v2. Why: Obsidian's plugin review tooling flags release assets without an attestation as a soft warning. Attestations cryptographically prove the asset was built by this workflow on this commit, defending against an attacker who gains release-asset-replace permissions and silently swaps in a compromised main.js. Verification post-release: gh attestation verify main.js --owner logancyang --repo logancyang/obsidian-copilot Placement: the new step runs AFTER the prerelease manifest swap and BEFORE gh release create. That way the attested manifest.json is exactly the bytes that get uploaded — for stable releases that's the committed manifest.json; for prereleases it's the in-runner copy of manifest-beta.json. Permissions: adds attestations: write and id-token: write to the job. The id-token: write permission is what allows the workflow to request an OIDC token from GitHub; the attest action uses that token as proof of identity when signing. No secrets to manage. Free for public repos. Co-authored-by: Claude Opus 4.7 (1M context) --- .github/workflows/release.yml | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1134df6d..37150489 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -24,7 +24,9 @@ jobs: runs-on: ubuntu-latest permissions: - contents: write # required to create GitHub releases and tags + contents: write # required to create GitHub releases and tags + attestations: write # required to publish artifact attestations + id-token: write # required for the workflow's OIDC token (used to sign attestations) env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -169,7 +171,25 @@ jobs: echo "Release-asset manifest.json (prerelease):" cat manifest.json - # ── Step 10: Create GitHub Release ─────────────────────────────────────── + # ── Step 10: Generate build provenance attestation ────────────────────── + # Cryptographically signs main.js / manifest.json / styles.css with the + # workflow's OIDC identity and publishes the attestation to Sigstore's + # public transparency log. Anyone can later verify a downloaded asset + # was actually built by this workflow on this commit with: + # gh attestation verify main.js --owner logancyang --repo logancyang/obsidian-copilot + # + # Runs AFTER the prerelease manifest swap so the attested manifest.json + # exactly matches the file uploaded to the GitHub Release. + - name: Generate artifact attestation + if: steps.semver.outputs.is_release == 'true' && steps.check_existing.outputs.exists != 'true' + uses: actions/attest-build-provenance@v2 + with: + subject-path: | + main.js + manifest.json + styles.css + + # ── Step 11: Create GitHub Release ─────────────────────────────────────── # --target pins the tag to the exact merge commit SHA so concurrent # merges cannot cause the release tag to point at a different commit. # When the PR title is a prerelease semver (X.Y.Z-tag.N), pass --prerelease