From 4ba1bbd805bd9d04e3640592b64b8cda717d7221 Mon Sep 17 00:00:00 2001 From: Moritz Mazetti Date: Thu, 30 Jul 2026 12:25:18 +0200 Subject: [PATCH] chore(security): pin npm exactly and make release tags immutable Two gaps OpenSSF Scorecard flagged on the first run (7/10 overall). Pinned-Dependencies scored 9 rather than 10 because release.yml installed npm@11, a floating major. Pinned to an exact patch; Renovate keeps it current. Added two repository rulesets: - Release integrity: main requires the CI checks to pass, signed commits, and blocks deletion and force-push. - Immutable release tags: refs/tags/v* cannot be deleted, updated, force-pushed or created unsigned. GitHub's immutable-releases setting is not exposed through the REST API, and this covers the half that matters -- a published version tag cannot be repointed at different code. This change deliberately goes through a pull request rather than a direct push. Scorecard scored Code-Review 0 because every commit so far landed straight on main, and the new ruleset now enforces the better path. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01CEdTd43qLEEE5qCsL1A7gW --- .github/workflows/release.yml | 5 +++-- SECURITY.md | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a304620..48d1780 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -29,8 +29,9 @@ permissions: {} env: # Trusted publishing needs npm 11.5.1 or newer. setup-node bundles whatever shipped with the Node - # release, so the version is pinned explicitly rather than left to chance. - NPM_VERSION: '11' + # release, so the version is pinned to an exact patch rather than left to a floating major. Renovate + # keeps it current. + NPM_VERSION: '12.0.2' jobs: verify: diff --git a/SECURITY.md b/SECURITY.md index 19f5f5a..905e844 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -104,8 +104,10 @@ Stated explicitly rather than left for someone to discover: - **Secret scanning is currently disabled** by an organisation-level security configuration, which a repository administrator cannot override. It is free for public repositories and should be enabled org-wide. -- **Immutable releases** are not currently exposed through the REST API, so the setting must be - confirmed in the repository's UI under Settings → General. +- **Immutable releases** are not exposed through the REST API. A repository ruleset covers the + important half: `refs/tags/v*` cannot be deleted, updated, force-pushed, or created unsigned, so a + published version tag cannot be moved to different code. Confirm the GitHub-native setting in + Settings → General as well, if it is available to the organisation. - **No egress filtering on runners.** `step-security/harden-runner` is the usual recommendation and would detect a build step phoning home. It is deliberately absent: adding a third-party action to the publish path widens the trusted set on exactly the job where that matters most. Worth revisiting