Harden the repository and npm releases against Shai-Hulud - #16
Harden the repository and npm releases against Shai-Hulud#16natanelia wants to merge 34 commits into
Conversation
📝 WalkthroughWalkthroughThe PR adds repository-wide supply-chain controls and replaces automatic releases with manually triggered version preparation, verified artifact staging, and release finalization workflows. ChangesRelease and supply-chain hardening
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant Maintainer
participant VersionWorkflow
participant StageWorkflow
participant NpmRegistry
participant FinalizeWorkflow
participant GitHubRelease
Maintainer->>VersionWorkflow: prepare and validate version patch
VersionWorkflow-->>Maintainer: upload checksummed patch artifact
Maintainer->>StageWorkflow: provide release version
StageWorkflow->>NpmRegistry: stage verified package tarballs
Maintainer->>FinalizeWorkflow: provide version and commit
FinalizeWorkflow->>NpmRegistry: verify published package versions
FinalizeWorkflow->>GitHubRelease: create or reuse release tag
Possibly related issues
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Final validation is complete: CI run #190 passed all ten jobs, including the supply-chain policy, dependency review, audit, semantic version-patch validation, package builds/consumers, and Chromium/Firefox/WebKit real-worker tests. The repository-side hardening is complete on this branch. Administrative controls that code cannot self-grant are tracked in #17 and must be completed before the new release path is treated as protected. Joezer's independent review remains requested. |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
scripts/prepare-release-artifacts.mjs (1)
164-183: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winAssert built output and publishable dependency ranges.
ALLOWED_PACKAGE_FILESpermitspackage.json/README-only packages, so a missing or staledist/build can pass the metadata check. Also validate that packeddependenciesdo not retainworkspace:ranges, because publishing a package withpackages/comlink-worker-pool-react/package.jsoncontainingworkspace:*forcomlink-worker-poolmakes consumers fail to resolve the dependency.Add both checks after
assertPackageContents(packageInfo.name, packResult.files).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/prepare-release-artifacts.mjs` around lines 164 - 183, After assertPackageContents in the packing flow, validate that the packed files include the expected built dist/ output and reject packages missing or containing stale build artifacts. Also inspect packed package metadata and reject any dependency range using the workspace: protocol, including dependencies such as comlink-worker-pool; keep both validations before constructing the packedPackages entry.scripts/validate-version-changes.mjs (1)
69-83: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winStrip Changesets-updated dependency fields.
stripAllowedChangesignorespeerDependencies,devDependencies, andoptionalDependencies, but Changesets versioning can update ranges in those fields too. Make this stripping use the Changesets schema/order so it remains valid ifpackages/comlink-worker-pool-react/package.jsondeclarescomlink-worker-pooloutsidedependencies; a hard-codedindex === 1check ties the allowlist toPACKAGE_PATHSorder.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/validate-version-changes.mjs` around lines 69 - 83, Update stripAllowedChanges to remove comlink-worker-pool from every dependency field Changesets can update—dependencies, peerDependencies, devDependencies, and optionalDependencies—using the Changesets schema/order rather than assuming dependencies only. Replace the index === 1 package check in the PACKAGE_PATHS mapping with a package-identity or path-based determination so the allowlist remains correct if PACKAGE_PATHS order changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/stage-release.yml:
- Around line 86-91: Update the release setup around “Set up release-compatible
Node.js” to install/pin npm 11.15.0 or newer before staging. Adjust the staging
flow so npm stage publish runs from a temporary checkout or working directory
containing the package, rather than passing a tarball path, and preserve the
existing release behavior.
In `@scripts/validate-version-changes.mjs`:
- Around line 27-34: Update scripts/validate-version-changes.mjs at lines 27-34
to stage all files with intent-to-add before enumerating changes, then use git
diff HEAD --name-status --no-renames and allow status A for changelog paths.
Update .github/workflows/release.yml at lines 44-46 to run git add --all before
generating the version patch and use git diff --cached --binary --full-index,
ensuring validation and patch generation inspect the same staged set.
- Line 29: Update the git diff argument list containing “--find-renames=0” to
use “--no-renames” instead, ensuring rename detection is disabled and renamed
files are reported as separate additions and deletions.
---
Nitpick comments:
In `@scripts/prepare-release-artifacts.mjs`:
- Around line 164-183: After assertPackageContents in the packing flow, validate
that the packed files include the expected built dist/ output and reject
packages missing or containing stale build artifacts. Also inspect packed
package metadata and reject any dependency range using the workspace: protocol,
including dependencies such as comlink-worker-pool; keep both validations before
constructing the packedPackages entry.
In `@scripts/validate-version-changes.mjs`:
- Around line 69-83: Update stripAllowedChanges to remove comlink-worker-pool
from every dependency field Changesets can update—dependencies,
peerDependencies, devDependencies, and optionalDependencies—using the Changesets
schema/order rather than assuming dependencies only. Replace the index === 1
package check in the PACKAGE_PATHS mapping with a package-identity or path-based
determination so the allowlist remains correct if PACKAGE_PATHS order changes.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: ccb83922-e22e-4188-92c3-336059a9b0da
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (17)
.github/CODEOWNERS.github/dependabot.yml.github/workflows/ci.yml.github/workflows/deploy-playground.yml.github/workflows/finalize-release.yml.github/workflows/release.yml.github/workflows/stage-release.yml.gitignore.npmrcREADME.mdSECURITY.mdbunfig.tomlpackage.jsonscripts/check-supply-chain-security.mjsscripts/prepare-release-artifacts.mjsscripts/release.mjsscripts/validate-version-changes.mjs
💤 Files with no reviewable changes (1)
- scripts/release.mjs
| - name: Set up release-compatible Node.js | ||
| uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 | ||
| with: | ||
| node-version: 24 | ||
| package-manager-cache: false | ||
| registry-url: https://registry.npmjs.org/ |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🌐 Web query:
npm stage publish tarball path argument supported npm docs
💡 Result:
The npm publish command natively supports providing a tarball path as an argument [1][2]. The command follows the syntax: npm publish [1][3]. A package-spec can be interpreted as a gzipped tarball, or a folder containing a package.json file [1][3]. If you are providing a local path (either to a folder or a tarball), the documentation notes that if it is a relative path, it should begin with an explicit./ prefix [1]. In summary, you can publish a package directly from a tarball file by passing its path to the npm publish command [1][2].
Citations:
- 1: https://docs.npmjs.com/cli/v11/commands/npm-publish/
- 2: https://docs.npmjs.com/cli/v6/commands/npm-publish/
- 3: https://docs.npmjs.com/cli/v10/commands/npm-publish/
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workflow excerpt =="
sed -n '70,175p' .github/workflows/stage-release.yml
echo
echo "== checkout references in workflow =="
rg -n "checkout|setup-node|npm stage|npm install|artifact|tarball|package" .github/workflows/stage-release.yml
echo
echo "== repository files =="
git ls-files | sed -n '1,120p'
echo
echo "== package manifests =="
for f in $(git ls-files | rg '(^|/)package\.json$'); do
echo "--- $f"
python3 - <<'PY' "$f"
import json, sys
p=sys.argv[1]
with open(p) as fh:
data=json.load(fh)
for k in ("name","private","publishConfig","packageManager","scripts"):
if k in data:
print(f"{k}={data[k]!r}")
PY
doneRepository: natanelia/comlink-worker-pool
Length of output: 13756
🌐 Web query:
npm stage command added npm 11.15.0
💡 Result:
The npm stage command was officially added in npm version 11.15.0, which was released on May 20, 2026 [1][2]. This command introduced staged publishing, a workflow that allows package maintainers to decouple the act of publishing from the requirement of two-factor authentication (2FA) [3][4]. With npm stage publish, an automated CI/CD workflow can stage a package version without a 2FA prompt [5][6]. The package is held in a pending state and is not publicly available until a maintainer explicitly approves it, a step that does require 2FA [7][4][8]. The npm stage command includes several subcommands for managing this process [5][6]: npm stage publish: Stages a package for publishing (no 2FA required). npm stage list: Lists all staged package versions. npm stage view: Views details of a specific staged package. npm stage approve: Approves and publishes a staged package (requires 2FA). npm stage reject: Rejects and removes a staged package (requires 2FA). npm stage download: Downloads the staged tarball for local inspection.
Citations:
- 1: https://github.com/npm/cli/releases/tag/v11.15.0
- 2: https://github.com/npm/cli/blob/v11.15.0/CHANGELOG.md
- 3: npm/cli@254809e
- 4: https://docs.npmjs.com/staged-publishing/
- 5: https://docs.npmjs.com/cli/v11/commands/npm-stage/
- 6: feat: npm stage npm/cli#9201
- 7: https://github.blog/changelog/2026-05-22-staged-publishing-and-new-install-time-controls-for-npm/
- 8: https://docs.npmjs.com/cli/v12/commands/npm-stage/
🌐 Web query:
Node.js 24 bundled npm version
💡 Result:
Node.js 24 ships with npm version 11 [1][2]. Specifically, the initial release of Node.js 24 (v24.0.0) included npm 11.0.0 [1][2]. Throughout the lifecycle of the Node.js 24 release line, the bundled npm version may be updated in subsequent releases [2].
Citations:
- 1: https://nodejs.org/en/blog/release/v24.0.0
- 2: https://github.com/nodejs/node/releases/tag/v24.0.0
🌐 Web query:
npm stage stage:publish help --stage staging tarball argument
💡 Result:
The command npm stage publish is part of npm's staged publishing feature, which allows maintainers to upload a package to a staging area for later approval, rather than publishing it directly [1][2]. This workflow is designed to improve security by allowing automated CI/CD systems to stage a package without requiring 2FA, while deferring the 2FA requirement to the manual approval step [3][4]. There is no specific tarball argument for the npm stage publish command [1][5]. The command automatically packs the current working directory as a tarball and uploads it to the npm registry [1][4]. Key details regarding this command and process: * Purpose: npm stage publish creates a pending version of your package that is not yet publicly available [1][2]. * 2FA Requirement: The staging step does not require 2FA [1][6]. 2FA is only required during the subsequent npm stage approve step [2][6]. * Inspection: If you need to inspect the contents of a staged package, you can use the npm stage download <stage-id> command to download the tarball for local review [1][3]. * System Requirements: Staged publishing is available in npm CLI version 11.15.0 or later [2][4]. If you are working programmatically with libnpmpublish, the underlying library uses an opts.stage option (set to true) to perform this action, handling the manifest and tarball data as inputs [7]. For standard CLI usage, you simply navigate to your package directory and run npm stage publish [2][6].
Citations:
- 1: https://docs.npmjs.com/cli/v11/commands/npm-stage/
- 2: https://docs.npmjs.com/staged-publishing/
- 3: feat: npm stage npm/cli#9201
- 4: https://github.blog/changelog/2026-05-22-staged-publishing-and-new-install-time-controls-for-npm/
- 5: https://docs.npmjs.com/cli/v12/commands/npm-stage/
- 6: https://docs.npmjs.com/creating-and-publishing-scoped-public-packages/
- 7: https://cdn.jsdelivr.net/npm/npm@11.16.0/node_modules/libnpmpublish/README.md
🌐 Web query:
Node.js 24 current npm version in August 2026
💡 Result:
As of August 5, 2026, the current npm version included with Node.js 24.19.0 is npm 11.17.0 [1][2]. Node.js 24.19.0 was released on August 3, 2026 [3][1].
Citations:
- 1: https://nodejs.org/en/blog/release/v24.19.0
- 2: https://github.com/nodejs/nodejs.org/blob/main/apps/site/pages/en/blog/release/v24.19.0.md
- 3: https://github.com/nodejs/node/releases
Upgrade npm before staging and stage from the package directory.
npm stage is unavailable in the older Node 24 npm versions, and npm stage publish stages the current package directory rather than accepting a tarball path. Pin/install npm 11.15.0 or newer and create a temp checkout pointing at the package dir, or otherwise stage from the correct package directory before calling npm stage publish.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/stage-release.yml around lines 86 - 91, Update the release
setup around “Set up release-compatible Node.js” to install/pin npm 11.15.0 or
newer before staging. Adjust the staging flow so npm stage publish runs from a
temporary checkout or working directory containing the package, rather than
passing a tarball path, and preserve the existing release behavior.
| const changedLines = execFileSync( | ||
| "git", | ||
| ["diff", "--name-status", "--find-renames=0"], | ||
| { encoding: "utf8" }, | ||
| ) | ||
| .trim() | ||
| .split(/\r?\n/) | ||
| .filter(Boolean); |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
The version-patch flow uses a diff basis that excludes untracked and staged changes. Both the validator and the patch generator read git diff without a commit argument. Files that bun run version creates are untracked, so the allowlist never inspects them and the patch never contains them. A reviewer can therefore apply a version patch that is missing a generated changelog while every checksum verifies.
scripts/validate-version-changes.mjs#L27-L34: enumerate changes withgit diff HEAD --name-status --no-renamesaftergit add --all --intent-to-add, and accept statusAfor the changelog paths only..github/workflows/release.yml#L44-L46: rungit add --allbefore the patch step and build the patch withgit diff --cached --binary --full-index, so the validated set and the patched set are identical.
📍 Affects 2 files
scripts/validate-version-changes.mjs#L27-L34(this comment).github/workflows/release.yml#L44-L46
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/validate-version-changes.mjs` around lines 27 - 34, Update
scripts/validate-version-changes.mjs at lines 27-34 to stage all files with
intent-to-add before enumerating changes, then use git diff HEAD --name-status
--no-renames and allow status A for changelog paths. Update
.github/workflows/release.yml at lines 44-46 to run git add --all before
generating the version patch and use git diff --cached --binary --full-index,
ensuring validation and patch generation inspect the same staged set.
|
|
||
| const changedLines = execFileSync( | ||
| "git", | ||
| ["diff", "--name-status", "--find-renames=0"], |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
git diff --find-renames=0 versus --no-renames documentation
💡 Result:
In Git, --no-renames and --find-renames=0 are effectively equivalent in practice, as both disable rename detection, though they function slightly differently at the command-line level [1][2][3]. --no-renames This is the explicit flag to turn off rename detection [1][2]. It overrides any configuration (such as diff.renames=true) that might otherwise enable rename detection by default [1][3]. --find-renames=0 This uses the --find-renames (or -M) option with a similarity threshold of 0 [1][2][4]. In Git, rename detection calculates a similarity index between added and deleted files [1][2]. Setting this threshold to 0% means that Git requires 0% similarity between files to consider them a rename [1][2][4]. Because any file comparison will satisfy a 0% threshold, this effectively results in no files being identified as renames, acting as a functional disablement of the feature [1][2]. Summary of differences: --no-renames is the documented, idiomatic way to disable the feature [1][3]. --find-renames=0 is a side effect of how the similarity threshold parameter is parsed, which achieves the same result [1][4]. In summary, you should use --no-renames for clarity and intent [1][3].
Citations:
- 1: https://git-scm.com/docs/diff-options
- 2: https://git-scm.com/docs/git-diff
- 3: https://git-scm.com/docs/git-diff/2.48.0
- 4: https://www.man7.org/linux/man-pages/man1/git-diff.1.html
🌐 Web query:
git diff find-renames=0 rename output git-diff docs
💡 Result:
There is no standard git diff command option formatted as find-renames=0. The correct way to disable rename detection in git diff is to use the --no-renames flag [1][2][3]. If you are looking to control rename detection behavior, the standard options are as follows: --no-renames: Disables rename detection entirely [1][3]. This causes files that have been moved or renamed to be displayed as a deleted file and an added file in the diff output [4]. -M[] or --find-renames[=]: Enables rename detection [1][2]. The optional is a threshold representing the similarity index (as a percentage or a fraction) [1][3]. For example, -M50% (the default) requires at least 50% similarity for a file pair to be considered a rename [1][3]. Using -M100% limits detection to exact renames only [1][2]. Regarding your specific search for find-renames=0, it is possible you encountered this in a configuration context or as a misunderstood variant of the -M option. In git configuration, you can set diff.renames = false to disable rename detection globally or for specific repositories [2][5]. Note that the option syntax --find-renames=0 is generally not recognized by the command line interface in the same way as --no-renames; passing incorrect or non-standard options can sometimes result in them being ignored, causing the default rename detection behavior to remain active [6][7].
Citations:
- 1: https://git-scm.com/docs/diff-options
- 2: https://git-scm.com/docs/git-diff.html
- 3: https://git-scm.com/docs/git-diff
- 4: https://stackoverflow.com/questions/67738831/disable-rename-detection-during-the-git-commit-to-preserve-history
- 5: https://git-scm.com/docs/diff-config
- 6: http://public-inbox.org/git/20240122230051.GB814674@coredump.intra.peff.net/t/
- 7: https://public-inbox.org/git/20240120011800.GF117170@coredump.intra.peff.net/
🏁 Script executed:
#!/bin/bash
set -u
printf 'Repository files matching script name:\n'
git ls-files | grep -F 'scripts/validate-version-changes.mjs' || true
printf '\nRelevant lines from scripts/validate-version-changes.mjs:\n'
sed -n '1,90p' scripts/validate-version-changes.mjs
printf '\nCheck local git availability and parse option behavior via git --help/exit if possible (no repository code execution):\n'
if command -v git >/dev/null 2>&1; then
printf 'git version: '
git --version | sed -n '1p'
git diff --help | grep -A3 -E '^\s+--find-renames|^\s+\-M|^\s+--no-renames' || true
else
echo 'git not found'
fiRepository: natanelia/comlink-worker-pool
Length of output: 3369
🌐 Web query:
git diff --no-renames --find-renames=0 official documentation -M threshold
💡 Result:
In Git, the command line options --no-renames and --find-renames operate as follows: --no-renames: This flag explicitly disables rename detection, overriding any configuration settings (such as diff.renames) that might otherwise enable it [1][2]. --find-renames[=]: This option enables rename detection. The optional parameter defines a threshold on the similarity index, which represents the amount of addition and deletion compared to the file's size [1][2]. Key details regarding the threshold : - Range: The threshold is expressed as a percentage or a fraction. For example, -M90% requires 90% similarity, while -M5 (interpreted as 0.5) is equivalent to 50% [1][3]. - Default: When -M or --find-renames is used without a specific value, the default similarity threshold is 50% [1][2]. - Behavior of 0: Setting the threshold to 0 (e.g., --find-renames=0) effectively sets the similarity requirement to 0%, meaning Git will consider any added/deleted pair as a rename, regardless of how much the file content has changed [1][2]. Note: Using both flags in the same command results in the last flag taking precedence. If you run git diff --no-renames --find-renames=0, Git will enable rename detection with a 0% threshold [1][2].
Citations:
- 1: https://git-scm.com/docs/git-diff
- 2: https://git-scm.com/docs/diff-options
- 3: https://man.freebsd.org/cgi/man.cgi?query=git-diff&sektion=
🌐 Web query:
git source diff-lib.c rename_threshold zero find_renames false
💡 Result:
In the Git source code, rename detection logic is not primarily housed in diff-lib.c, which focuses on comparing the work tree with the index [1][2]. Rename detection is handled in diffcore-rename.c [3][4]. The parameters you mentioned, rename_threshold and find_renames, correspond to internal configuration settings within Git's diff machinery [3][4][5]. When Git's rename detection is disabled (find_renames = false), the system skips the expensive process of comparing file contents to detect similarities, significantly optimizing performance for diff operations [6][3]. Specifically, in the C implementation (such as in diffcore-rename.c): - find_renames is a function (or flag-based logic) that iterates through potential rename candidates [3][7][5]. - rename_threshold (often represented as minimum_score) determines the similarity percentage required for a file to be considered a rename [6][3][4]. - If rename detection is turned off, the diff output will only show additions and deletions rather than identifying moved or renamed files [6]. While diff-lib.c manages the high-level diff process by gathering file metadata and changes, it relies on functions defined in diffcore.h and implemented in files like diffcore-rename.c to perform the heavy lifting of rename detection [1][2][3].
Citations:
- 1: https://code.googlesource.com/git/+/HEAD/diff-lib.c
- 2: https://github.com/git/git/blob/master/diff-lib.c
- 3: https://code.googlesource.com/git/+/refs/tags/v2.31.7/diffcore-rename.c
- 4: https://code.googlesource.com/git/+/refs/tags/v2.29.0-rc0/diffcore-rename.c
- 5: https://fuchsia.googlesource.com/third_party/git/+/refs/heads/main/diffcore-rename.c
- 6: https://git-scm.com/docs/git-diff/2.12.5
- 7: https://code.googlesource.com/git/+/refs/tags/v2.22.2/diffcore-rename.c
🌐 Web query:
"git diff" "--find-renames=0" "status R"
💡 Result:
The command git diff --find-renames=0 status R is likely a misunderstanding of how Git flags interact. This command does not perform a single operation, but rather interprets the flags as follows: 1. --find-renames=0: This option (equivalent to -M0) tells Git to detect renames with a similarity threshold of 0%. In practice, this forces Git to consider even very different files as potential renames [1][2][3]. 2. status: In the context of git diff, "status" is not a standard flag. Git will likely interpret this as a positional argument (a path or a commit reference), which will likely result in an error if no such file or commit exists [1][4]. 3. R: The -R flag (not to be confused with the status letter R) is a valid Git option that swaps the two inputs of the diff, showing differences from the index/on-disk file to the tree contents rather than the other way around [5][6][7]. If your goal was to show only renamed files, you should use the --name-status and --diff-filter options instead [5][6]. For example: git diff --name-status --diff-filter=R This command displays only the files that have been renamed [5][8][7]. If you specifically need to adjust rename detection sensitivity, you can add -M: git diff --name-status --diff-filter=R -M50% In this example, -M50% is the default behavior; you can adjust the percentage as needed to control how aggressively Git detects renames [1][3].
Citations:
- 1: https://git-scm.com/docs/git-diff
- 2: https://git-scm.com/docs/diff-options
- 3: https://www.man7.org/linux/man-pages/man1/git-diff.1.html
- 4: https://git-scm.com/docs/git-diff/2.25.1
- 5: https://git-scm.com/docs/diff-options/2.25.1
- 6: https://code.googlesource.com/git/+/HEAD/Documentation/diff-options.adoc
- 7: https://man.archlinux.org/man/git-diff.1.en
- 8: https://stackoverflow.com/questions/61491666/git-diff-status-flags
🌐 Web query:
"git diff --name-status --no-renames" "R copy from"
💡 Result:
The command git diff --name-status --no-renames is used to list changed files along with their status, while explicitly disabling Git's rename detection mechanism [1][2][3]. Breakdown of the components: --name-status: This option instructs Git to output only the name of each changed file and a status letter indicating the type of change (e.g., A for Added, M for Modified, D for Deleted) [1][4][3]. It suppresses the detailed patch/diff content [5][4]. --no-renames: This option forces Git to turn off its rename detection logic [1][6][3]. Without this flag, Git might identify a file deletion and a file creation as a single "rename" (R) or "copy" (C) if the file contents are sufficiently similar [4][3]. By using --no-renames, you ensure that Git treats these as separate deletion (D) and addition (A) events [1][6]. This command is particularly useful when you need to see the raw file-level changes without Git attempting to infer relationships between renamed or copied files [1][3].
Citations:
- 1: https://git-scm.com/docs/diff-options
- 2: https://git-scm.com/docs/git-diff/2.25.1
- 3: https://git-scm.com/docs/git-diff
- 4: https://man.archlinux.org/man/git-diff.1
- 5: https://git-scm.com/docs/git-diff/2.12.5
- 6: https://www.man7.org/linux/man-pages/man1/git-diff.1.html
🌐 Web query:
git 2.48 --find-renames=0 change rename detection zero threshold documentation
💡 Result:
In Git 2.48, as in other modern versions of Git, there is a distinction between rename detection threshold (controlled by -M or --find-renames) and the rename detection limit (controlled by -l or diff.renameLimit). 1. Rename Detection Threshold (--find-renames): The --find-renames option (or -M) controls the similarity index required to consider a file pair as a rename [1][2]. The value is a percentage or fraction (e.g., -M50% or -M0.5). If you set this to 0 (e.g., --find-renames=0), it effectively sets the required similarity threshold to 0%, meaning any deleted file and any added file would be considered a potential rename regardless of content similarity [1][2]. Note that this is different from disabling rename detection, which is done via --no-renames or git config diff.renames false [1][3]. 2. Rename Detection Limit (-l / diff.renameLimit): The -l option (or the diff.renameLimit configuration) controls the maximum number of files considered during the expensive, exhaustive O(N^2) portion of rename detection [1][2]. Contrary to the similarity threshold, setting this limit to 0 has a specific, well-documented behavior: it is treated as unlimited [1][2]. This allows Git to attempt exhaustive rename detection regardless of the number of files involved, which can be computationally expensive [1][4]. Summary: - --find-renames=0: Sets the similarity threshold to 0%. - -l0 or diff.renameLimit=0: Sets the exhaustive rename detection limit to unlimited [1][2].
Citations:
- 1: https://git-scm.com/docs/git-diff/2.48.0
- 2: https://git-scm.com/docs/diff-options/2.48.0
- 3: https://git-scm.com/docs/git-diff/2.43.1
- 4: https://www.kernel.org/pub/software/scm/git/docs/git-diff.html
🌐 Web query:
"git diff --find-renames=0" "R" output
💡 Result:
The command git diff --find-renames=0 (or -M0) sets the rename detection threshold to 0% [1][2]. In Git's rename detection logic, the similarity index represents how much of a file's content remains unchanged between a deletion and an addition [1][3]. By setting this value to 0, you are instructing Git to consider any deleted file and any added file as a potential rename candidate, regardless of how different their contents are [4]. Essentially, this forces Git to perform the most aggressive rename detection possible, effectively treating any added/deleted file pair as a rename, even if they share almost no content [4]. This is in contrast to the default behavior (typically 50%), where Git only flags a rename if at least 50% of the content is identical [1][4]. While this can be useful for forcing detection in cases where files have changed significantly, it also increases the risk of false positives, where Git incorrectly identifies unrelated files as renames [4].
Citations:
- 1: https://git-scm.com/docs/diff-options
- 2: https://git-scm.com/docs/git-diff
- 3: https://www.man7.org/linux/man-pages/man1/git-diff.1.html
- 4: https://stackoverflow.com/questions/73529530/behavior-of-git-diff-name-status-when-searching-from-commit-1-up-to-head
🌐 Web query:
git diff --name-status --find-renames=0 changed files same status
💡 Result:
The command git diff --name-status --find-renames=0 is technically malformed because the --find-renames (or -M) option requires a similarity index threshold value [1][2]. Providing 0 as an argument to --find-renames is not a valid configuration for detecting renames [1][3]. Rename Detection Mechanics: 1. --find-renames[=]: This option is used to detect renames [1][4]. The parameter represents the similarity index threshold (as a percentage or fraction) [1][5]. 2. If the option is omitted or used without a value, the default similarity index is 50% [1][2]. 3. If you want to disable rename detection, you should use the --no-renames option instead [4][2]. If you run git diff --name-status, Git uses its default configuration (or the value set in the diff.renames git config) [1][6]. When rename detection is enabled, Git identifies a file as renamed (status R) if the similarity between a deleted file and an added file exceeds the defined threshold [1][7]. If rename detection is disabled, these changes will appear as two separate entries: a deletion (D) and an addition (A) [7]. To effectively control rename detection: - To disable: Use git diff --name-status --no-renames. - To use default threshold: Use git diff --name-status. - To set a specific threshold: Use git diff --name-status -M (e.g., -M60% or -M0.6) [1][5].
Citations:
- 1: https://git-scm.com/docs/git-diff
- 2: https://git-scm.com/docs/diff-options
- 3: https://git-scm.com/docs/diff-options/2.52.0
- 4: https://code.googlesource.com/git/+/HEAD/Documentation/diff-options.adoc
- 5: https://github.com/git/git/blob/1eaabe34fc6f486367a176207420378f587d3b48/Documentation/diff-options.txt
- 6: https://git-scm.com/docs/diff-config
- 7: https://stackoverflow.com/questions/55835638/how-to-run-git-diff-and-show-new-location-of-moved-file-instead-of-old-location
🌐 Web query:
"git-diff" "--no-renames" documentation
💡 Result:
The --no-renames option in git-diff is a command-line flag used to disable Git's automatic rename detection [1][2][3]. When this flag is used, Git will not attempt to identify if a file has been renamed, even if the repository's configuration settings are set to enable it by default [1][3]. By default, Git may detect renames based on similarity thresholds between files [1][2]. Enabling --no-renames forces Git to treat such changes as a simple deletion of one file and the creation of another, bypassing the rename detection logic [1][2]. This option is particularly useful for overriding the diff.renames configuration variable in situations where you want to see the literal file additions and removals rather than a detected rename [1][3].
Citations:
- 1: https://git-scm.com/docs/git-diff
- 2: https://git-scm.com/docs/diff-options
- 3: https://www.man7.org/linux/man-pages/man1/git-diff.1.html
🌐 Web query:
"git diff --name-status --find-renames=0"
💡 Result:
The command git diff --name-status --find-renames=0 is not a valid way to disable rename detection in Git [1][2]. In Git, the --find-renames (or -M) option expects a threshold value representing the similarity index (the percentage of the file that must remain unchanged to be considered a rename) [1][3]. Providing a value of 0 is not documented as a valid way to disable rename detection; rather, the default similarity index is 50%, and values are typically specified as percentages (e.g., -M50%) or fractions [1][4]. To explicitly disable rename detection in Git, you should use the --no-renames option instead [5]. Summary of components: --name-status: Displays only the status (e.g., Added, Modified, Deleted) and the filename of changed files [1][2]. --find-renames[=]: Used to control rename detection thresholds [1][3]. If you want to disable renames, use --no-renames [5].
Citations:
- 1: https://git-scm.com/docs/diff-options
- 2: https://git-scm.com/docs/git-diff
- 3: https://www.man7.org/linux/man-pages/man1/git-diff.1.html
- 4: https://cdn.kernel.org/pub/software/scm/git/docs/git-diff.html
- 5: https://git-scm.com/docs/git-diff-files/2.54.0
🌐 Web query:
Git 2.49 --find-renames=100 --find-renames=0 behavior
💡 Result:
In Git 2.49, as in previous versions, the --find-renames[=] option controls rename detection behavior using a similarity threshold [1][2]. --find-renames=100% This command forces Git to detect only exact renames [1][2]. A pair of files (a deletion and an addition) will be considered a rename only if the content is identical (100% similarity) [1][2]. --find-renames=0 Setting the threshold to 0 is technically equivalent to a very low similarity requirement [1][2]. According to Git documentation, if the number is provided without a percentage sign, it is treated as a fraction where -M5 equals 0.5 (50%) [1][2]. While a threshold of 0 technically asks for 0% similarity, Git's rename detection logic inherently requires some level of content overlap to identify a valid rename. In practice, this setting effectively disables the typical similarity filtering, potentially causing Git to report renames even for files with minimal shared content, or it may be treated as a request for basic rename detection depending on the specific implementation of the diffcore-rename engine [1][2]. There were no changes to the fundamental behavior of --find-renames in Git 2.49 [3][4]. The release focused on internal clean-ups, documentation format changes, and specific fixes rather than modifications to the rename detection algorithm or option parsing [3][4]. The default similarity index remains 50% [1][2].
Citations:
- 1: https://git-scm.com/docs/git-diff/2.12.5
- 2: https://git-scm.com/docs/diff-options
- 3: https://github.com/git/git/blob/v2.49.0/Documentation/RelNotes/2.49.0.adoc
- 4: https://public-inbox.org/git/xmqq34fffihq.fsf@gitster.g/T/
Use --no-renames to disable rename detection.
--find-renames=0 enables rename detection with a threshold instead of disabling it. Use git diff --name-status --no-renames so renamed files are emitted as A .../D rather than R.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/validate-version-changes.mjs` at line 29, Update the git diff
argument list containing “--find-renames=0” to use “--no-renames” instead,
ensuring rename detection is disabled and renamed files are reported as separate
additions and deletions.
What changed
This adds defense in depth against self-propagating npm supply-chain attacks such as Shai-Hulud.
Dependency execution
package.jsonandbun.lock.bun.lockfiles and GitHub Actions, with a seven-day cooldown for ordinary version updates while security updates remain immediate.GitHub Actions
pages: writeand OIDC.@nataneliaand@Joezer-Ivan.Versioning without write credentials
version-packages.patchartifact that a maintainer must inspect, apply to a branch, and submit as a normal reviewed pull request.npm release integrity
NPM_TOKENpath and direct token-based release script.npm stage publishonly.main, which createsv<version>only after both npm packages are public and their source manifests match the exact staged commit.Operations
SECURITY.mdwith required GitHub rulesets, protected environments, security features, npm trusted-publisher settings, the release-review procedure, and incident response.@nataneliaand@Joezer-Ivan.Why
Shai-Hulud propagated through package lifecycle scripts, stole long-lived npm and GitHub credentials, modified repositories and workflows, and published further compromised package versions. The previous repository still retained dependency script trust, used a reusable npm credential, persisted checkout credentials, followed moving Action tags, granted a third-party Pages action repository-write access, and left
mainunprotected.The new design assumes even a build dependency can execute malicious code. Such code receives neither repository-write nor npm-publishing authority. CI can submit only an immutable staged tarball, and npm requires a separate maintainer inspection plus 2FA before public release.
Validation
The final GitHub Actions run passes all ten jobs:
The release artifact packer was additionally exercised against representative package builds and produced two tarballs, a complete file manifest, npm integrity values, and valid SHA-256 checksums.
Required post-merge configuration
Repository code cannot self-grant administrative controls. Complete issue #17 before treating releases as protected:
mainwith PR-only merges, independent Code Owner review, stale-review dismissal, resolved conversations, all CI checks, no force pushes/deletion, and enforcement for administrators.v*tags.npm-releaseandgithub-releaseenvironments.stage-release.yml+npm-release, allow staged publishing only, require WebAuthn 2FA and disallow tokens, then revokeNPM_TOKENand every other package-write token.Summary by CodeRabbit
Security
Release Management
Documentation