Skip to content

Make audit:prod cross-platform so the release gate works on Windows - #20

Merged
unbraind merged 3 commits into
mainfrom
fix/cross-platform-audit-prod
Jul 28, 2026
Merged

unbraind merged 3 commits into
mainfrom
fix/cross-platform-audit-prod

Conversation

@unbraind

@unbraind unbraind commented Jul 28, 2026 •

Copy link
Copy Markdown
Owner

What

audit:prod used the POSIX-only env -u npm_config_allow_scripts prefix. env is not a command under Windows cmd.exe, so release:check and prepublishOnly fail there with a shell error rather than an audit result.

CI is ubuntu-latest only, so this never surfaced in the pipeline. It breaks a Windows contributor running the gate locally, and npm publish via prepublishOnly.

Why the env -u form existed

The script before it was a bare npm audit --omit=dev, which aborts with EALLOWSCRIPTS whenever npm_config_allow_scripts is present in the environment:

npm error --allow-scripts is not allowed in project-scoped installs

So the gate failed for a reason unrelated to vulnerabilities. env -u fixed that and traded it for the Windows problem. Each form fixed one platform and broke the other.

The fix

Adopt the Node helper now used across the fleet: strip npm_config_allow_scripts from the environment, pin npm_config_userconfig to the platform null device, and spawn npm through a shell on win32 only.

The shell flag is required rather than cosmetic. Node's CVE-2024-27980 hardening (18.20.2 / 20.12.2 / 21.7.3+) refuses to execute .cmd files through spawn unless the shell option is set, so a helper spawning npm.cmd without it fails on Windows for a second, subtler reason. The argument vector is two constants (audit, --omit=dev) with nothing interpolated, so enabling the shell introduces no injection surface.

form POSIX Windows
npm audit --omit=dev breaks on EALLOWSCRIPTS fine
env -u … npm audit … correct env is not a command
Node helper, no shell correct Node refuses to exec .cmd
Node helper, shell on win32 correct correct

Verification

release:check passes end to end — typecheck, build, tests, production audit, pack dry-run, changelog check.

Not empirically verified on Windows — there is no Windows host available here. This follows Node's documented .cmd handling; POSIX behaviour is unchanged and is verified.

Found by Greptile on the 2026.7.28 adoption PRs for the starter templates, then swept across the fleet.


Summary by cubic

Make audit:prod cross-platform so release:check and prepublishOnly work on Windows. Replace POSIX-only env -u with a Node helper that strips npm_config_allow_scripts, sets npm_config_userconfig to the null device, spawns npm via a shell on Windows, and keeps --ignore-scripts; also align manifest.json pm_min_version to 2026.7.28.

Written for commit 004e876. Summary will update on new commits.

Review in cubic

audit:prod used the POSIX-only "env -u npm_config_allow_scripts" prefix, which
is not a command under Windows cmd.exe, so release:check and prepublishOnly
fail there. CI is ubuntu-only so it never surfaced in the pipeline; it breaks
a Windows contributor running the gate locally, and npm publish via
prepublishOnly.

Adopt the same Node helper the rest of the fleet now uses: it strips
npm_config_allow_scripts from the environment, pins npm_config_userconfig to
the platform null device, and spawns npm through a shell on win32 only.

The shell flag is required rather than cosmetic: Node CVE-2024-27980 hardening
refuses to execute .cmd files through spawn unless the shell option is set, so
a helper spawning npm.cmd without it fails on Windows for a second, subtler
reason. The argument vector is two constants with nothing interpolated, so
enabling the shell introduces no injection surface.

Not empirically verified on Windows - there is no Windows host here. POSIX
behaviour is unchanged and verified: release:check passes end to end.
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @unbraind, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented Jul 28, 2026 •

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The audit:prod npm script now uses a Node.js spawnSync invocation to run npm audit --omit=dev, sanitize npm configuration variables, and propagate the child process exit status.

Changes

Production audit execution

Layer / File(s) Summary
Audit command execution
package.json
The audit:prod script replaces the shell-based command with a Node.js implementation that removes npm_config_allow_scripts from relevant configuration variables and returns the spawned audit process status.

Estimated code review effort: 2 (Simple) | ~5 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title accurately summarizes the main change: making audit:prod cross-platform for Windows.
Description check ✅ Passed The description directly matches the changeset and explains the cross-platform audit fix in detail.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/cross-platform-audit-prod

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 28, 2026 •

Copy link
Copy Markdown

Greptile Summary

This PR replaces the POSIX-only env -u npm_config_allow_scripts prefix in the audit:prod script with a cross-platform Node.js inline helper, and bumps manifest.json's pm_min_version to match the current package version.

  • package.json: Rewrites audit:prod as a Node ESM one-liner that strips npm_config_allow_scripts from the environment via a case-insensitive key scan, pins npm_config_userconfig to the OS null device (so user .npmrc files are ignored), and spawns npm audit --omit=dev --ignore-scripts with shell: true on Windows only — satisfying the post-CVE-2024-27980 restriction on executing .cmd files via spawn without the shell flag.
  • manifest.json: pm_min_version updated from 2026.7.20 to 2026.7.28, aligning with the package version and the @unbrained/pm-cli >=2026.7.28 peer dependency declared in package.json.

Confidence Score: 5/5

Safe to merge — the inline Node helper is a narrow, well-contained change that correctly addresses all three known failure modes (EALLOWSCRIPTS, missing env on Windows, Node's .cmd execution restriction post-CVE-2024-27980).

The rewrite of audit:prod is logically correct: env vars are stripped via a case-insensitive scan, the null-device userconfig pin is idiomatic, the two hardcoded argument constants introduce no injection surface, and the fallback exit code of 1 on a null status is appropriate. The manifest version bump is consistent with package.json and the declared peer dependency range.

Files Needing Attention: No files require special attention.

Important Files Changed

Filename Overview
package.json audit:prod script replaced with a cross-platform Node.js inline helper; all design choices (case-insensitive env scrubbing, devNull userconfig pin, conditional shell flag) are correct and well-justified
manifest.json pm_min_version bumped from 2026.7.20 to 2026.7.28, correctly aligned with the package version and peerDependencies declared in package.json

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[npm run audit:prod] --> B[Node ESM inline script starts]
    B --> C[Spread process.env into new env object]
    C --> D[Pin npm_config_userconfig to devNull]
    D --> E[Case-insensitive scan: remove npm_config_allow_scripts]
    E --> F{Windows?}
    F -- Yes --> G[spawnSync npm.cmd with shell:true]
    F -- No --> H[spawnSync npm with shell:false]
    G --> I{r.status null?}
    H --> I
    I -- No --> J[process.exit with r.status]
    I -- Yes --> K[process.exit with 1]
Loading

Reviews (4): Last reviewed commit: "fix(release): restore --ignore-scripts o..." | Re-trigger Greptile

unbraind added 2 commits July 28, 2026 07:10
manifest.json declared a pm_min_version older than the >=2026.7.28 peer
requirement in package.json. The two disagreed about the floor, and the
manifest promised support for a pm version this extension is neither built nor
tested against - the activation tests run through the 2026.7.28 SDK harness.

Set the manifest floor to 2026.7.28 so both declarations agree.

Found by CodeRabbit on pm-presets; the same mismatch was present here.
The cross-platform helper was adopted from pm-ops, whose argv was
["audit", "--omit=dev"] -- so switching to it silently dropped the
--ignore-scripts flag the previous env -u form passed. That is a reduction in
the gate relative to what it replaced, not an intended change.

Restore it, so the only difference from the previous form is the platform
handling.
@unbraind

Copy link
Copy Markdown
Owner Author

@greptileai Confirmed and fixed — upvoted, and you were right that this was a real reduction rather than a cosmetic difference.

I adopted the cross-platform helper from pm-ops, whose argv was ["audit", "--omit=dev"], so switching to it silently dropped the --ignore-scripts that the previous env -u form passed. Nothing about the platform work required dropping it; I inherited the omission along with the helper and did not notice, because both forms exit 0 on a clean tree and the diff I was reading was a one-line script swap.

That is a good illustration of why "adopt the known-good form from a sibling repo" is not automatically safe: the reference implementation itself carried two defects — the missing --ignore-scripts, and the spawnSync of npm.cmd without shell that you flagged earlier. Both were copied into every package that adopted it.

Restored, so the only remaining difference from the previous form is platform handling:

spawnSync(win ? "npm.cmd" : "npm", ["audit", "--omit=dev", "--ignore-scripts"], { stdio: "inherit", env, shell: win })

Swept across all 17 packages carrying the helper, including pm-ops itself. audit:prod and the full release:check gate pass everywhere.

@greptile-apps

greptile-apps Bot commented Jul 28, 2026

Copy link
Copy Markdown

Good catch on tracing the omission back to the reference implementation itself — that's the riskier failure mode, since adopters have no reason to audit a "known-good" helper for correctness.

The restored argv is now the right canonical form:

["audit", "--omit=dev", "--ignore-scripts"]
  • --omit=dev — scopes the audit to the production dependency surface
  • --ignore-scripts — prevents lifecycle hooks from running during the audit scan itself
  • shell: win — satisfies the post-CVE-2024-27980 .cmd restriction on Windows

Sweeping pm-ops as the source of truth before any more packages adopt from it was the right call. Everything looks good here.

@unbraind
unbraind merged commit d5cba66 into main Jul 28, 2026
6 checks passed
@unbraind
unbraind deleted the fix/cross-platform-audit-prod branch July 28, 2026 05:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant