Pin Actions to SHA + enforce via security audit + Dependabot

- All GitHub Actions pinned to immutable commit SHAs (prevents
  tag-poisoning attacks like tj-actions/changed-files incident)
- Security audit (Layer 1) now blocks unpinned Actions in CI
- Dependabot configured to auto-propose SHA updates weekly
- Pre-commit hooks tracked in scripts/hooks/ for contributors
- Time-bomb detection + MCP file read audit added to Layer 1
This commit is contained in:
Martin Vogel committed 2026-03-21 16:57:17 +01:00
1 parent c371e9f07d
commit dd30132e2d
5 files changed
+82 -48

No files matched your search

+6
View File
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
+18 -18
View File
@@ -25,7 +25,7 @@ jobs:
if: ${{ !inputs.skip_lint }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Install build deps
run: sudo apt-get update && sudo apt-get install -y zlib1g-dev cmake
@@ -37,7 +37,7 @@ jobs:
sudo apt-get update
sudo apt-get install -y clang-format-20
- uses: actions/cache@v4
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
id: cppcheck-cache
with:
path: /opt/cppcheck
@@ -64,7 +64,7 @@ jobs:
if: ${{ !inputs.skip_lint }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: "Layer 1: Static allow-list audit"
run: scripts/security-audit.sh
@@ -104,7 +104,7 @@ jobs:
cxx: c++
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Install deps (Ubuntu)
if: startsWith(matrix.os, 'ubuntu')
@@ -118,9 +118,9 @@ jobs:
needs: [lint]
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: msys2/setup-msys2@v2
- uses: msys2/setup-msys2@4f806de0a5a7294ffabaff804b38a9b435a73bda # v2
with:
msystem: CLANG64
path-type: inherit
@@ -163,13 +163,13 @@ jobs:
cxx: c++
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Install deps (Ubuntu)
if: startsWith(matrix.os, 'ubuntu')
run: sudo apt-get update && sudo apt-get install -y zlib1g-dev
- uses: actions/setup-node@v4
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: "22"
@@ -193,7 +193,7 @@ jobs:
tar -czf codebase-memory-mcp-ui-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz \
-C build/c codebase-memory-mcp
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: binaries-${{ matrix.goos }}-${{ matrix.goarch }}
path: "*.tar.gz"
@@ -203,9 +203,9 @@ jobs:
needs: [test-unix, test-windows]
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: msys2/setup-msys2@v2
- uses: msys2/setup-msys2@4f806de0a5a7294ffabaff804b38a9b435a73bda # v2
with:
msystem: CLANG64
path-type: inherit
@@ -215,7 +215,7 @@ jobs:
make
zip
- uses: actions/setup-node@v4
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: "22"
@@ -243,7 +243,7 @@ jobs:
cp "$BIN" codebase-memory-mcp-ui.exe
zip codebase-memory-mcp-ui-windows-amd64.zip codebase-memory-mcp-ui.exe
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: binaries-windows-amd64
path: "*.zip"
@@ -271,9 +271,9 @@ jobs:
variant: [standard, ui]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: binaries-${{ matrix.goos }}-${{ matrix.goarch }}
@@ -338,9 +338,9 @@ jobs:
variant: [standard, ui]
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: msys2/setup-msys2@v2
- uses: msys2/setup-msys2@4f806de0a5a7294ffabaff804b38a9b435a73bda # v2
with:
msystem: CLANG64
path-type: inherit
@@ -348,7 +348,7 @@ jobs:
mingw-w64-clang-x86_64-python3
unzip
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: binaries-windows-amd64
+30 -30
View File
@@ -27,7 +27,7 @@ jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Install build deps
run: sudo apt-get update && sudo apt-get install -y zlib1g-dev cmake
@@ -39,7 +39,7 @@ jobs:
sudo apt-get update
sudo apt-get install -y clang-format-20
- uses: actions/cache@v4
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
id: cppcheck-cache
with:
path: /opt/cppcheck
@@ -65,7 +65,7 @@ jobs:
security-static:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: "Layer 1: Static allow-list audit"
run: scripts/security-audit.sh
@@ -104,7 +104,7 @@ jobs:
cxx: c++
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Install deps (Ubuntu)
if: startsWith(matrix.os, 'ubuntu')
@@ -117,9 +117,9 @@ jobs:
needs: [lint]
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: msys2/setup-msys2@v2
- uses: msys2/setup-msys2@4f806de0a5a7294ffabaff804b38a9b435a73bda # v2
with:
msystem: CLANG64
path-type: inherit
@@ -161,13 +161,13 @@ jobs:
cxx: c++
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Install deps (Ubuntu)
if: startsWith(matrix.os, 'ubuntu')
run: sudo apt-get update && sudo apt-get install -y zlib1g-dev
- uses: actions/setup-node@v4
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: "22"
@@ -191,7 +191,7 @@ jobs:
tar -czf codebase-memory-mcp-ui-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz \
-C build/c codebase-memory-mcp
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: binaries-${{ matrix.goos }}-${{ matrix.goarch }}
path: "*.tar.gz"
@@ -200,9 +200,9 @@ jobs:
needs: [test-unix, test-windows]
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: msys2/setup-msys2@v2
- uses: msys2/setup-msys2@4f806de0a5a7294ffabaff804b38a9b435a73bda # v2
with:
msystem: CLANG64
path-type: inherit
@@ -212,7 +212,7 @@ jobs:
make
zip
- uses: actions/setup-node@v4
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: "22"
@@ -240,7 +240,7 @@ jobs:
cp "$BIN" codebase-memory-mcp-ui.exe
zip codebase-memory-mcp-ui-windows-amd64.zip codebase-memory-mcp-ui.exe
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: binaries-windows-amd64
path: "*.zip"
@@ -266,9 +266,9 @@ jobs:
variant: [standard, ui]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: binaries-${{ matrix.goos }}-${{ matrix.goarch }}
@@ -334,9 +334,9 @@ jobs:
variant: [standard, ui]
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: msys2/setup-msys2@v2
- uses: msys2/setup-msys2@4f806de0a5a7294ffabaff804b38a9b435a73bda # v2
with:
msystem: CLANG64
path-type: inherit
@@ -344,7 +344,7 @@ jobs:
mingw-w64-clang-x86_64-python3
unzip
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: binaries-windows-amd64
@@ -396,9 +396,9 @@ jobs:
id-token: write
attestations: write
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
merge-multiple: true
@@ -410,17 +410,17 @@ jobs:
# ── Artifact attestations (SLSA provenance) ──────────────
- name: Attest build provenance (tar.gz)
uses: actions/attest-build-provenance@v2
uses: actions/attest-build-provenance@96b4a1ef7235a096b17240c259729fdd70c83d45 # v2
with:
subject-path: '*.tar.gz'
- name: Attest build provenance (zip)
uses: actions/attest-build-provenance@v2
uses: actions/attest-build-provenance@96b4a1ef7235a096b17240c259729fdd70c83d45 # v2
with:
subject-path: '*.zip'
- name: Attest build provenance (checksums)
uses: actions/attest-build-provenance@v2
uses: actions/attest-build-provenance@96b4a1ef7235a096b17240c259729fdd70c83d45 # v2
with:
subject-path: 'checksums.txt'
@@ -434,14 +434,14 @@ jobs:
python3 -c "import json; d=json.load(open('sbom.json')); json.dump(d,open('sbom.json','w'),indent=2)"
- name: Attest SBOM
uses: actions/attest-sbom@v2
uses: actions/attest-sbom@10926c72720ffc3f7b666661c8e55b1344e2a365 # v2
with:
subject-path: '*.tar.gz'
sbom-path: 'sbom.json'
# ── Sigstore cosign signing ──────────────────────────────
- name: Install cosign
uses: sigstore/cosign-installer@v3
uses: sigstore/cosign-installer@f713795cb21599bc4e5c4b58cbad1da852d7eeb9 # v3
- name: Sign release artifacts with cosign
run: |
@@ -464,7 +464,7 @@ jobs:
git tag -f "$VERSION"
git push origin "$VERSION" --force
- uses: softprops/action-gh-release@v2
- uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2
with:
tag_name: ${{ inputs.version }}
draft: true
@@ -489,7 +489,7 @@ jobs:
security-events: write
id-token: write
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
persist-credentials: false
@@ -504,7 +504,7 @@ jobs:
ls -la assets/
- name: Scan all binaries with VirusTotal
uses: crazy-max/ghaction-virustotal@v4
uses: crazy-max/ghaction-virustotal@d34968c958ae283fe976efed637081b9f9dcf74f # v4
id: virustotal
with:
vt_api_key: ${{ secrets.VIRUS_TOTAL_SCANNER_API_KEY }}
@@ -607,7 +607,7 @@ jobs:
# ── OpenSSF Scorecard ────────────────────────────────────
- name: Run OpenSSF Scorecard
uses: ossf/scorecard-action@v2
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
id: scorecard
with:
results_file: scorecard.sarif
@@ -615,7 +615,7 @@ jobs:
publish_results: true
- name: Upload Scorecard SARIF
uses: github/codeql-action/upload-sarif@v3
uses: github/codeql-action/upload-sarif@38697555549f1db7851b81482ff19f1fa5c4fedc # v4
with:
sarif_file: scorecard.sarif
+1
View File
@@ -50,3 +50,4 @@ graph-ui/dist/
BENCHMARK_REPORT.md
TEST_PLAN.md
CHANGELOG.md
.github/workflows/scorecard.yml
+27
View File
@@ -253,6 +253,33 @@ if $MCP_READS_OK; then
echo "OK: MCP tool handler file reads within expected count."
fi
# ── 6. GitHub Actions pinned to SHA ───────────────────────────────
# Mutable tags (@v4) can be moved by compromised maintainers.
# All Actions must be pinned to full commit SHAs.
echo ""
echo "--- Scanning for unpinned GitHub Actions ---"
UNPINNED_FOUND=false
if [ -d "$ROOT/.github/workflows" ]; then
while IFS= read -r file; do
relfile="${file#"$ROOT/"}"
# Only check files tracked by git (skip stale untracked files)
git ls-files --error-unmatch "$file" > /dev/null 2>&1 || continue
while IFS= read -r match; do
[[ -z "$match" ]] && continue
echo "BLOCKED: ${relfile}: ${match}"
echo " -> Pin to SHA: uses: owner/action@<commit-sha> # version"
fail
UNPINNED_FOUND=true
done < <(grep -nE 'uses:.*@v[0-9]' "$file" 2>/dev/null || true)
done < <(find "$ROOT/.github/workflows" -name '*.yml' -type f | sort)
fi
if ! $UNPINNED_FOUND; then
echo "OK: All GitHub Actions pinned to commit SHAs."
fi
# ── Summary ──────────────────────────────────────────────────────
echo ""