From 2304a4b5e90b1c9f6f96147b49c310c0bfbe81b1 Mon Sep 17 00:00:00 2001 From: Martin Vogel Date: Wed, 8 Jul 2026 23:34:10 +0200 Subject: [PATCH 1/2] chore(ci): attest release artifacts in build workflow Signed-off-by: Martin Vogel --- .github/workflows/_build.yml | 54 +++++++++++++++++++++++++++++++++++ .github/workflows/dry-run.yml | 6 ++++ .github/workflows/release.yml | 9 ++++-- README.md | 2 +- SECURITY.md | 12 ++++---- 5 files changed, 75 insertions(+), 8 deletions(-) diff --git a/.github/workflows/_build.yml b/.github/workflows/_build.yml index c7b0f6da4..44189c938 100644 --- a/.github/workflows/_build.yml +++ b/.github/workflows/_build.yml @@ -8,9 +8,15 @@ on: description: 'Version string (e.g. v0.8.0)' type: string default: '' + attest: + description: 'Generate build provenance attestations for release artifacts' + type: boolean + default: false permissions: contents: read + id-token: write + attestations: write jobs: build-unix: @@ -83,6 +89,12 @@ jobs: tar -czf "codebase-memory-mcp-${GOOS}-${GOARCH}.tar.gz" \ -C build/c codebase-memory-mcp LICENSE install.sh THIRD_PARTY_NOTICES.md + - name: Attest standard binary provenance + if: ${{ inputs.attest }} + uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1 + with: + subject-path: codebase-memory-mcp-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz + - name: Build UI binary env: VERSION: ${{ inputs.version }} @@ -113,6 +125,12 @@ jobs: tar -czf "codebase-memory-mcp-ui-${GOOS}-${GOARCH}.tar.gz" \ -C build/c codebase-memory-mcp LICENSE install.sh THIRD_PARTY_NOTICES.md + - name: Attest UI binary provenance + if: ${{ inputs.attest }} + uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1 + with: + subject-path: codebase-memory-mcp-ui-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: binaries-${{ matrix.goos }}-${{ matrix.goarch }} @@ -158,6 +176,12 @@ jobs: scripts/gen-third-party-notices.sh THIRD_PARTY_NOTICES.md zip codebase-memory-mcp-windows-amd64.zip codebase-memory-mcp.exe LICENSE install.ps1 THIRD_PARTY_NOTICES.md + - name: Attest standard binary provenance + if: ${{ inputs.attest }} + uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1 + with: + subject-path: codebase-memory-mcp-windows-amd64.zip + - name: Build UI binary shell: msys2 {0} env: @@ -178,6 +202,12 @@ jobs: scripts/gen-third-party-notices.sh THIRD_PARTY_NOTICES.md zip codebase-memory-mcp-ui-windows-amd64.zip codebase-memory-mcp.exe LICENSE install.ps1 THIRD_PARTY_NOTICES.md + - name: Attest UI binary provenance + if: ${{ inputs.attest }} + uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1 + with: + subject-path: codebase-memory-mcp-ui-windows-amd64.zip + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: binaries-windows-amd64 @@ -227,6 +257,12 @@ jobs: scripts/gen-third-party-notices.sh THIRD_PARTY_NOTICES.md zip codebase-memory-mcp-windows-arm64.zip codebase-memory-mcp.exe LICENSE install.ps1 THIRD_PARTY_NOTICES.md + - name: Attest standard binary provenance + if: ${{ inputs.attest }} + uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1 + with: + subject-path: codebase-memory-mcp-windows-arm64.zip + - name: Build UI binary shell: msys2 {0} env: @@ -247,6 +283,12 @@ jobs: scripts/gen-third-party-notices.sh THIRD_PARTY_NOTICES.md zip codebase-memory-mcp-ui-windows-arm64.zip codebase-memory-mcp.exe LICENSE install.ps1 THIRD_PARTY_NOTICES.md + - name: Attest UI binary provenance + if: ${{ inputs.attest }} + uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1 + with: + subject-path: codebase-memory-mcp-ui-windows-arm64.zip + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: binaries-windows-arm64 @@ -299,6 +341,12 @@ jobs: tar -czf "codebase-memory-mcp-linux-${ARCH}-portable.tar.gz" \ -C build/c codebase-memory-mcp LICENSE install.sh THIRD_PARTY_NOTICES.md + - name: Attest standard binary provenance + if: ${{ inputs.attest }} + uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1 + with: + subject-path: codebase-memory-mcp-linux-${{ matrix.arch }}-portable.tar.gz + - name: Build UI binary (static) env: VERSION: ${{ inputs.version }} @@ -318,6 +366,12 @@ jobs: tar -czf "codebase-memory-mcp-ui-linux-${ARCH}-portable.tar.gz" \ -C build/c codebase-memory-mcp LICENSE install.sh THIRD_PARTY_NOTICES.md + - name: Attest UI binary provenance + if: ${{ inputs.attest }} + uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1 + with: + subject-path: codebase-memory-mcp-ui-linux-${{ matrix.arch }}-portable.tar.gz + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: binaries-linux-${{ matrix.arch }}-portable diff --git a/.github/workflows/dry-run.yml b/.github/workflows/dry-run.yml index 8e6c21504..b71b92f5c 100644 --- a/.github/workflows/dry-run.yml +++ b/.github/workflows/dry-run.yml @@ -56,7 +56,13 @@ jobs: build: if: ${{ inputs.skip_builds != true && !cancelled() && (needs.test.result == 'success' || needs.test.result == 'skipped') }} needs: [test] + permissions: + contents: read + id-token: write + attestations: write uses: ./.github/workflows/_build.yml + with: + attest: false # ── Smoke test every binary ──────────────────────────────────── # Run unless builds were skipped or a build leg FAILED. Every build leg diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a885e8c6c..36c071a16 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -56,9 +56,14 @@ jobs: # ── 3. Build all platforms ────────────────────────────────────── build: needs: [test] + permissions: + contents: read + id-token: write + attestations: write uses: ./.github/workflows/_build.yml with: version: ${{ inputs.version }} + attest: true # ── 4. Smoke test every binary ────────────────────────────────── smoke: @@ -99,10 +104,10 @@ jobs: - name: Generate checksums run: sha256sum *.tar.gz *.zip > checksums.txt - - name: Attest build provenance + - name: Attest checksum provenance uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1 with: - subject-path: '*.tar.gz,*.zip,checksums.txt' + subject-path: checksums.txt - name: Generate SBOM run: | diff --git a/README.md b/README.md index db130526d..3811b5b66 100644 --- a/README.md +++ b/README.md @@ -599,7 +599,7 @@ internal/cbm/ Vendored tree-sitter grammars (158 languages) + AST extrac Every release binary is verified through a multi-layer pipeline before publication: - **VirusTotal** — all binaries scanned by 70+ antivirus engines (zero detections required to publish) -- **SLSA Level 3** — cryptographic build provenance generated by GitHub Actions; verify with `gh attestation verify --repo DeusData/codebase-memory-mcp` +- **SLSA Level 3** — cryptographic build provenance generated by the trusted GitHub Actions build workflow; verify with `gh attestation verify --repo DeusData/codebase-memory-mcp --signer-workflow DeusData/codebase-memory-mcp/.github/workflows/_build.yml` - **Sigstore cosign** — keyless signatures on all artifacts; bundles included in every release - **SHA-256 checksums** — `checksums.txt` published with every release; verified by both install scripts before extraction - **CodeQL SAST** — blocks release pipeline if any open alerts remain diff --git a/SECURITY.md b/SECURITY.md index 8514d504b..aa8da2693 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,7 +4,7 @@ codebase-memory-mcp interacts deeply with your filesystem. It reads source files across your entire codebase, writes to agent configuration files, and spawns background processes. This is inherent to what it does — not a bug. -**If you are uncomfortable with these access patterns**, please audit the source code before running. The full source is available in this repository. Every release binary is reproducibly built from this source and can be independently verified via SLSA provenance, Sigstore signatures, and SHA-256 checksums (see [Verification](#verification) below). +**If you are uncomfortable with these access patterns**, please audit the source code before running. The full source is available in this repository. Every release binary is verifiably built from this source and can be independently verified via SLSA provenance, Sigstore signatures, and SHA-256 checksums (see [Verification](#verification) below). We are humans and can make mistakes. We take security seriously — it is Priority #1 for this project — but we cannot guarantee perfection. By using this software you accept responsibility for evaluating whether it meets your own security requirements. @@ -122,9 +122,9 @@ This project implements multiple layers of security verification. Every release Releases are created as **drafts** (invisible to users) and only published after all verification passes: -1. **SLSA build provenance** — cryptographic attestation proving each binary was built by GitHub Actions from this repository +1. **SLSA build provenance** — cryptographic attestation proving each binary was built by the trusted GitHub Actions build workflow from this repository 2. **Sigstore cosign signing** — keyless digital signatures verifiable by anyone -3. **SBOM** — Software Bill of Materials (CycloneDX) listing all vendored dependencies +3. **SBOM** — Software Bill of Materials (SPDX) listing all vendored dependencies 4. **SHA-256 checksums** — published with every release 5. **VirusTotal scanning** — all binaries scanned by 70+ antivirus engines (zero-tolerance: any detection blocks the release) 6. **OpenSSF Scorecard** — repository security health score @@ -145,8 +145,10 @@ If ANY antivirus engine flags ANY binary, the release stays as a draft and is no Users can independently verify any release binary: ```bash -# SLSA provenance (proves binary came from this repo's CI) -gh attestation verify --repo DeusData/codebase-memory-mcp +# SLSA provenance (proves binary came from the trusted build workflow) +gh attestation verify \ + --repo DeusData/codebase-memory-mcp \ + --signer-workflow DeusData/codebase-memory-mcp/.github/workflows/_build.yml # Sigstore cosign (keyless signature) cosign verify-blob --bundle .bundle From 8a370b2209504b990435d17390af67d74c02ba38 Mon Sep 17 00:00:00 2001 From: Martin Vogel Date: Thu, 9 Jul 2026 00:14:15 +0200 Subject: [PATCH 2/2] docs(security): clarify SLSA provenance scope Signed-off-by: Martin Vogel --- SECURITY.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index aa8da2693..d5153f62e 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,7 +4,7 @@ codebase-memory-mcp interacts deeply with your filesystem. It reads source files across your entire codebase, writes to agent configuration files, and spawns background processes. This is inherent to what it does — not a bug. -**If you are uncomfortable with these access patterns**, please audit the source code before running. The full source is available in this repository. Every release binary is verifiably built from this source and can be independently verified via SLSA provenance, Sigstore signatures, and SHA-256 checksums (see [Verification](#verification) below). +**If you are uncomfortable with these access patterns**, please audit the source code before running. The full source is available in this repository. Release binaries produced by the current release pipeline are verifiably built from this source and can be independently verified via SLSA Build Level 3 provenance, Sigstore signatures, and SHA-256 checksums (see [Verification](#verification) below). We are humans and can make mistakes. We take security seriously — it is Priority #1 for this project — but we cannot guarantee perfection. By using this software you accept responsibility for evaluating whether it meets your own security requirements. @@ -122,13 +122,21 @@ This project implements multiple layers of security verification. Every release Releases are created as **drafts** (invisible to users) and only published after all verification passes: -1. **SLSA build provenance** — cryptographic attestation proving each binary was built by the trusted GitHub Actions build workflow from this repository +1. **SLSA Build Level 3 provenance for release binaries** — cryptographic attestation generated inside the trusted GitHub Actions build workflow immediately after each release archive is produced 2. **Sigstore cosign signing** — keyless digital signatures verifiable by anyone 3. **SBOM** — Software Bill of Materials (SPDX) listing all vendored dependencies 4. **SHA-256 checksums** — published with every release 5. **VirusTotal scanning** — all binaries scanned by 70+ antivirus engines (zero-tolerance: any detection blocks the release) 6. **OpenSSF Scorecard** — repository security health score +Scope of the SLSA claim: this is a build provenance claim for release +artifacts. It proves the attested archive was produced by the repository's +trusted GitHub-hosted build workflow from repository source. It is not +third-party certification, it is not retroactive to older releases, and it does +not mean the source code is vulnerability-free or that maintainers cannot change +source. Consumers should verify the signer workflow, not only repository +ownership. + If ANY antivirus engine flags ANY binary, the release stays as a draft and is not published until the issue is investigated and resolved. ### Code-Level Defenses @@ -145,7 +153,7 @@ If ANY antivirus engine flags ANY binary, the release stays as a draft and is no Users can independently verify any release binary: ```bash -# SLSA provenance (proves binary came from the trusted build workflow) +# SLSA Build Level 3 provenance for release binaries gh attestation verify \ --repo DeusData/codebase-memory-mcp \ --signer-workflow DeusData/codebase-memory-mcp/.github/workflows/_build.yml