From ca046e61c1a25d6f9c7030a9fcceb8422c7e1106 Mon Sep 17 00:00:00 2001 From: Parfii-bot Date: Wed, 22 Apr 2026 17:12:15 +0800 Subject: [PATCH] =?UTF-8?q?fix(v0.19.1):=20supply-chain=20hardening=20rema?= =?UTF-8?q?inder=20=E2=80=94=20ci.yml=20SHA-pin=20+=20dependabot=20+=20bun?= =?UTF-8?q?.lock=20placeholder?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to c27b626 (release.yml pinning). Finishes H4 + H5. ci.yml: - 11 third-party actions SHA-pinned with # vN.m.k comments - actions/checkout@34e114876b... (v4.3.1) - actions/setup-node@49933ea5288... (v4.4.0) - dtolnay/rust-toolchain@3c5f7ea28... (rust 1.94.1) - Swatinem/rust-cache@c19371144... (v2.9.1) .github/dependabot.yml (NEW): - 3 ecosystems weekly: github-actions, npm, cargo - PR cap 5, labels [dependencies, ] - Auto-opens update PRs for SHA bumps — human reviews, not silent churn _ts_packages/packages/mcp-server/bun.lock (NEW — placeholder): - 13-line comment explaining H4 gate - Instructs: 'cd _ts_packages/packages/mcp-server && bun install' before release - release.yml (since v0.19.1) uses --frozen-lockfile with NO fallback — missing real lockfile fails the build deliberately BUILD.md: - New 'Lockfile' section (19 LOC) documenting the pre-release workflow CHANGELOG.md: - [Unreleased] → Security: 3 bullets covering this + prior supply-chain commit All SHAs E1 (verified via api.github.com or reused from release.yml). NEXT STEP BEFORE TAGGING v0.19.1: Populate real bun.lock locally, commit, then tag. Workflow will fail on missing/stale lockfile — that's the point of H4 defense. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/dependabot.yml | 26 ++++++++++++++++++++ .github/workflows/ci.yml | 29 ++++++++++++++--------- CHANGELOG.md | 5 ++++ _ts_packages/packages/mcp-server/BUILD.md | 19 +++++++++++++++ _ts_packages/packages/mcp-server/bun.lock | 13 ++++++++++ 5 files changed, 81 insertions(+), 11 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 _ts_packages/packages/mcp-server/bun.lock diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..8c88efe --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,26 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + open-pull-requests-limit: 5 + labels: + - dependencies + - github-actions + - package-ecosystem: npm + directory: /_ts_packages + schedule: + interval: weekly + open-pull-requests-limit: 5 + labels: + - dependencies + - npm + - package-ecosystem: cargo + directory: /_primitives/_rust + schedule: + interval: weekly + open-pull-requests-limit: 5 + labels: + - dependencies + - rust diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ededde0..4e285d5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,13 @@ on: branches: [main] pull_request: +# v0.19.1 supply-chain hardening (H5): every third-party action is pinned +# by full commit SHA. A floating tag like @v4 can be re-pointed by a +# compromised maintainer (CVE-2025-30066 class). The `# vN.m.k` comment +# next to each SHA is a human-readable hint only — the SHA is the load- +# bearing identifier. When Dependabot proposes a bump, review the new SHA +# against the release tag before merging. + jobs: rust-assembler: runs-on: ${{ matrix.os }} @@ -12,9 +19,9 @@ jobs: matrix: os: [ubuntu-latest, macos-latest] steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9 # rust 1.94.1 (dtolnay/rust-toolchain master) + - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 with: workspaces: _assembler - run: cd _assembler && cargo test --release @@ -25,9 +32,9 @@ jobs: matrix: os: [ubuntu-latest, macos-latest] steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9 # rust 1.94.1 (dtolnay/rust-toolchain master) + - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 with: workspaces: _primitives/_rust - run: cd _primitives/_rust && cargo test --workspace --release @@ -39,8 +46,8 @@ jobs: os: [ubuntu-latest, macos-latest] node: ['20', '22'] steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: ${{ matrix.node }} - run: cd _ts_packages && npm ci @@ -53,8 +60,8 @@ jobs: matrix: os: [ubuntu-latest, macos-latest] steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9 # rust 1.94.1 (dtolnay/rust-toolchain master) - name: Install hard deps (Ubuntu) if: matrix.os == 'ubuntu-latest' run: sudo apt-get update && sudo apt-get install -y jq pandoc @@ -69,7 +76,7 @@ jobs: shell-lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - run: sudo apt-get update && sudo apt-get install -y shellcheck - name: shellcheck (advisory) run: find hooks _primitives -name '*.sh' -exec shellcheck -S warning {} + diff --git a/CHANGELOG.md b/CHANGELOG.md index 896e50f..6339238 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,11 @@ _primitives/_rust/target/release/kei-changelog \ - Placeholder: hook-bypass edge case follow-up to v0.15.1. - **primitives/keisei (v0.19 audit hardening):** close 3 Security HIGH + 3 Critic HIGH + 2 Critic MEDIUM findings. Path-escape guard on `mcp_server` + `memory/artifacts/manifests` (absolute / `..` / canonical-mismatch → `PathEscape`); brain-name regex `^[a-z][a-z0-9_-]{0,63}$` (`InvalidName`); symlink-rooted brain inputs rejected (`BrainIsSymlink` — closes USB → `$HOME` pivot); MCP-entry collision check across all 4 adapters (`NameConflict` instead of silent clobber); dropped unused `rusqlite` dep (no C toolchain tail); `BrainPaths.{memory,artifacts,manifests}` relaxed to `Option`; `$KEISEI_HOME`/`$HOME` resolver deduped into `paths.rs` SSoT; `fsx::write_atomic` rewritten on `tempfile::NamedTempFile` for Windows + cross-fs correctness; 5 adversarial integration tests added (16 total pass). +### Security +- Pinned all GitHub Actions (`ci.yml`, `release.yml`) by full commit SHA to defend against CVE-2025-30066-class supply-chain attacks via mutable tag re-pointing. +- Removed `|| bun install` fallback from `release.yml` build-mcp-binary job — lockfile is now strictly REQUIRED (H4 audit finding). +- Added `.github/dependabot.yml` for weekly SHA update PRs on github-actions, npm, and cargo ecosystems. + ## [0.15.0] — 2026-04-22 ### Added diff --git a/_ts_packages/packages/mcp-server/BUILD.md b/_ts_packages/packages/mcp-server/BUILD.md index 955164f..8b6972c 100644 --- a/_ts_packages/packages/mcp-server/BUILD.md +++ b/_ts_packages/packages/mcp-server/BUILD.md @@ -50,3 +50,22 @@ GitHub release. Runtime requirement: **none** (static). - **`.js` ESM imports fail** — the mcp-server source imports via `.js` suffix (ESM canonical). Bun resolves these from the sibling `.ts` file automatically; no `tsc` pre-step needed. + +## Lockfile + +Since v0.19.1 this package ships a `bun.lock` committed to the repo. +The release workflow runs `bun install --frozen-lockfile` with NO +fallback — a missing or out-of-date lockfile fails the build on +purpose. This is H4 supply-chain defense: every release builds +against the exact dependency tree recorded in `bun.lock`, not +whatever the npm registry serves that day. + +**Before every release tag:** +1. `cd _ts_packages/packages/mcp-server` +2. `bun install` (regenerates `bun.lock` if `package.json` changed) +3. Commit `bun.lock` if it changed +4. Tag the release + +**If you see the build fail with "lockfile missing" on a tag push:** +you pushed the tag before committing an updated `bun.lock`. Fix: +generate the lockfile locally, commit, re-tag. diff --git a/_ts_packages/packages/mcp-server/bun.lock b/_ts_packages/packages/mcp-server/bun.lock new file mode 100644 index 0000000..2cb2d69 --- /dev/null +++ b/_ts_packages/packages/mcp-server/bun.lock @@ -0,0 +1,13 @@ +# bun.lock placeholder — v0.19.1 +# +# This file MUST be replaced with a real bun lockfile BEFORE any release tag +# is pushed. The release.yml workflow (since v0.19.1) uses +# `bun install --frozen-lockfile` with NO fallback — a missing real lockfile +# will fail the build deliberately (H4 supply-chain defense). +# +# To populate: +# cd _ts_packages/packages/mcp-server && bun install +# Then commit the generated bun.lock (overwrites this placeholder). +# +# Until populated, the release workflow will fail at the bun install step — +# intentional gate to force the lockfile into the repo before first release.