Skip to content

## Summary#192

Open
JoachimLK wants to merge 1 commit into
mainfrom
fix/npm-audit-alias-override
Open

## Summary#192
JoachimLK wants to merge 1 commit into
mainfrom
fix/npm-audit-alias-override

Conversation

@JoachimLK
Copy link
Copy Markdown
Contributor

@JoachimLK JoachimLK commented May 29, 2026

  • This PR updates the CI configuration to run npm audit with npm 11, addressing issues with aliased overrides that caused failures in the audit step.

  • This change is necessary to ensure that the audit process can handle aliased packages without crashing, allowing for proper evaluation of vulnerabilities.

PR title must follow Conventional Commits — e.g. feat(jobs): add bulk import or fix: handle null salary. The squash-merged title is what release-please uses to generate the changelog and pick the next version. PRs with non-conventional titles are blocked by CI.

Type of change

  • Bug fix

  • Feature

  • Refactor

  • Docs

  • Chore

Validation

  • I tested locally

  • I added/updated relevant documentation

  • I verified multi-tenant scoping and auth behavior for affected API paths

DCO

  • All commits in this PR are signed off (Signed-off-by) via git commit -s

Summary by CodeRabbit

  • Chores
    • Enhanced dependency audit validation in continuous integration with improved vulnerability detection and configurable allowlisting for known issues.

Review Change Stack

The PR Validation "Build, typecheck, and test" check fails on every
dependency PR at the audit step. npm 10 (bundled with Node 20) crashes
on the aliased "@posthog/cli": "npm:empty-npm-package@1.0.0" override
with "Invalid comparator", so `npm audit` exits non-zero before
evaluating any advisory and `set -o pipefail` fails the job. This is
independent of what each PR bumps, which is why even trivial patch PRs
go red.

- Run audit with npm 11 (handles aliased overrides) via npx.
- Evaluate results with .github/scripts/check-audit.mjs, which fails on
  high/critical advisories except a documented allowlist, and fails
  loudly if audit itself cannot run (never silently skips the gate).
- Allowlist the samlify advisory (GHSA-34r5-q4jw-r36m): it surfaces
  transitively via @better-auth/sso, which pins samlify ~2.10.2, so the
  patched samlify >=2.13.0 would risk breaking SAML/SSO. No safe upstream
  fix exists yet; re-evaluate when @better-auth/sso bumps samlify.

No production dependencies change; package.json/package-lock.json are
untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

📝 Walkthrough

Walkthrough

This PR adds an npm audit allowlist gate to the CI pipeline. A new Node.js script validates npm audit JSON output and enforces that high/critical security advisories either do not exist or are explicitly allowlisted by advisory URL, exiting with distinct codes for success, blocked advisories, or audit errors. The PR validation workflow is updated to invoke this script instead of using npm audit's built-in level flag.

Changes

Audit allowlist enforcement

Layer / File(s) Summary
Audit allowlist enforcement script
\.github/scripts/check-audit.mjs
Script reads npm audit JSON output, extracts high/critical advisories from vulnerability via chains, filters against an allowlist keyed by advisory URL, logs results with audit error handling (exit 2), and exits with code 0 on success or code 1 if blocking advisories remain.
PR validation audit step
\.github/workflows/pr-validation.yml
Workflow invokes npm@11 audit --json, captures output to separate files, pipes combined results through check-audit.mjs, and allows the step to continue with `

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A rabbit hops through audit trails,
Checking advisories, file by file with zeal,
Allowlists grant safe passage through,
While blockers fail with exit codes true—
Security gates now guard the way! 🔐

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The PR title "## Summary" is vague and generic, providing no meaningful information about the changeset or the primary technical change being made. Use a conventional commit format with a specific description, e.g., 'fix(ci): update npm audit to use npm 11 for alias override handling' or 'fix: resolve npm audit failures with aliased package overrides'.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description covers the what and why with sufficient detail, includes type of change selection, and acknowledges the Conventional Commits requirement; however, the PR title itself is non-compliant with Conventional Commits, and validation/DCO checkboxes are unchecked.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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/npm-audit-alias-override

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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 and usage tips.

@railway-app
Copy link
Copy Markdown

railway-app Bot commented May 29, 2026

🚅 Deployed to the reqcore-pr-192 environment in applirank

Service Status Web Updated (UTC)
applirank ✅ Success (View Logs) May 29, 2026 at 2:06 pm

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
.github/workflows/pr-validation.yml (1)

55-55: ⚡ Quick win

audit-error.txt is captured but never surfaced.

npm's stderr is redirected to audit-error.txt, but nothing reads it (the summary only cats audit-output.txt). If npm 11 audit fails to emit valid JSON, check-audit.mjs exits 2 with a generic "Could not read/parse" message while the real npm error stays hidden — losing diagnostics for the exact crash class this PR addresses. Consider echoing it on non-zero parse, or including it in the step summary.

🔭 Surface npm stderr when the audit JSON can't be evaluated
           npx -y npm@11 audit --json > audit-output.json 2> audit-error.txt || true
-          node .github/scripts/check-audit.mjs audit-output.json 2>&1 | tee audit-output.txt
+          node .github/scripts/check-audit.mjs audit-output.json 2>&1 | tee audit-output.txt
+          rc=${PIPESTATUS[0]}
+          if [ "$rc" -eq 2 ] && [ -s audit-error.txt ]; then
+            echo "--- npm audit stderr ---" | tee -a audit-output.txt
+            cat audit-error.txt | tee -a audit-output.txt
+          fi
+          exit "$rc"
🤖 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/pr-validation.yml at line 55, The workflow redirects npm
stderr to audit-error.txt but never surfaces it; update the step and/or the
check-audit.mjs error path to include that stderr when JSON parsing fails: keep
the existing command (npx -y npm@11 audit --json > audit-output.json 2>
audit-error.txt || true) but modify the failure handling in check-audit.mjs (or
the workflow step that calls it) so that on non-zero/parse errors it reads
audit-error.txt and prints or adds its contents to the step summary/console
output (include the filename audit-error.txt and a clear message), ensuring the
parse failure path logs the exact npm stderr for debugging.
🤖 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/scripts/check-audit.mjs:
- Around line 61-67: The loop currently ignores high/critical advisories that
lack via.url; change it so all high/critical via entries are recorded into the
advisories Map even when via.url is falsy: in the block iterating vuln.via
(symbols: advisories, via, vuln, vuln.via) remove the guard that skips when
via.url is falsy and instead compute a stable key (e.g. via.url ||
`${vuln.name||vuln.title||'advisory'}:${via.severity}:${via.id||i}`) and call
advisories.set(key, { url: via.url || null, title: via.title, severity:
via.severity, id: via.id || null }) so entries without a url are captured (with
url null) and will block by default and can be matched by an allowlist
separately.

In @.github/workflows/pr-validation.yml:
- Around line 55-56: Pin the floating npm invocation and surface the stderr file
so audit failures are reproducible and visible: change the npx call (currently
"npx -y npm@11 audit ...") to a pinned release such as "npx -y npm@11.16.0 audit
--json > audit-output.json 2> audit-error.txt || true" and update the downstream
invocation of the audit checker (node .github/scripts/check-audit.mjs) to also
consume or print audit-error.txt (for example pass audit-error.txt as an
additional argument to check-audit.mjs or cat audit-error.txt into the piped
output) so the contents of audit-error.txt are included in audit-output.txt and
the PR summary; ensure references to "npx -y npm@11", "audit-error.txt", and
"node .github/scripts/check-audit.mjs" are updated accordingly.

---

Nitpick comments:
In @.github/workflows/pr-validation.yml:
- Line 55: The workflow redirects npm stderr to audit-error.txt but never
surfaces it; update the step and/or the check-audit.mjs error path to include
that stderr when JSON parsing fails: keep the existing command (npx -y npm@11
audit --json > audit-output.json 2> audit-error.txt || true) but modify the
failure handling in check-audit.mjs (or the workflow step that calls it) so that
on non-zero/parse errors it reads audit-error.txt and prints or adds its
contents to the step summary/console output (include the filename
audit-error.txt and a clear message), ensuring the parse failure path logs the
exact npm stderr for debugging.
🪄 Autofix (Beta)

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

Run ID: e09b360c-47e3-4576-af56-3d410c62968f

📥 Commits

Reviewing files that changed from the base of the PR and between ee89062 and b3b4c9f.

📒 Files selected for processing (2)
  • .github/scripts/check-audit.mjs
  • .github/workflows/pr-validation.yml

Comment on lines +61 to +67
for (const vuln of Object.values(vulns)) {
for (const via of vuln.via || []) {
if (typeof via !== "object") continue;
if (via.severity !== "high" && via.severity !== "critical") continue;
if (via.url) advisories.set(via.url, { url: via.url, title: via.title, severity: via.severity });
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

High/critical advisories without a url are silently dropped from the gate.

A via advisory object is only recorded when via.url is truthy (Line 65). Any high/critical advisory object lacking a url is skipped entirely, so it neither blocks nor gets reported. It also can't be allowlisted (the allowlist keys on url), so the safe default for such an entry is to block. In practice npm/GHSA advisories carry a url, hence the low priority, but for a security gate it's worth failing closed.

🛡️ Fail closed when a high/critical advisory has no url
 for (const vuln of Object.values(vulns)) {
   for (const via of vuln.via || []) {
     if (typeof via !== "object") continue;
     if (via.severity !== "high" && via.severity !== "critical") continue;
-    if (via.url) advisories.set(via.url, { url: via.url, title: via.title, severity: via.severity });
+    // Use the url as the dedup/allowlist key; fall back to a synthetic key so
+    // an advisory without a url still surfaces and blocks (it can't be allowlisted).
+    const key = via.url || `${via.source ?? via.title ?? "unknown"}`;
+    advisories.set(key, { url: via.url || "(no url)", title: via.title, severity: via.severity });
   }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for (const vuln of Object.values(vulns)) {
for (const via of vuln.via || []) {
if (typeof via !== "object") continue;
if (via.severity !== "high" && via.severity !== "critical") continue;
if (via.url) advisories.set(via.url, { url: via.url, title: via.title, severity: via.severity });
}
}
for (const vuln of Object.values(vulns)) {
for (const via of vuln.via || []) {
if (typeof via !== "object") continue;
if (via.severity !== "high" && via.severity !== "critical") continue;
// Use the url as the dedup/allowlist key; fall back to a synthetic key so
// an advisory without a url still surfaces and blocks (it can't be allowlisted).
const key = via.url || `${via.source ?? via.title ?? "unknown"}`;
advisories.set(key, { url: via.url || "(no url)", title: via.title, severity: via.severity });
}
}
🤖 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/scripts/check-audit.mjs around lines 61 - 67, The loop currently
ignores high/critical advisories that lack via.url; change it so all
high/critical via entries are recorded into the advisories Map even when via.url
is falsy: in the block iterating vuln.via (symbols: advisories, via, vuln,
vuln.via) remove the guard that skips when via.url is falsy and instead compute
a stable key (e.g. via.url ||
`${vuln.name||vuln.title||'advisory'}:${via.severity}:${via.id||i}`) and call
advisories.set(key, { url: via.url || null, title: via.title, severity:
via.severity, id: via.id || null }) so entries without a url are captured (with
url null) and will block by default and can be matched by an allowlist
separately.

Comment on lines +55 to +56
npx -y npm@11 audit --json > audit-output.json 2> audit-error.txt || true
node .github/scripts/check-audit.mjs audit-output.json 2>&1 | tee audit-output.txt
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

What is the latest npm 11 version and its required Node.js engines range?

💡 Result:

As of May 29, 2026, the latest version of npm 11 is 11.16.0 [1]. The required Node.js engines range for npm 11 is defined as ^20.17.0 || >=22.9.0 [2]. This range was established to support newer Node.js releases while ensuring compatibility with supported LTS versions [2].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# Show the workflow section around the referenced lines and any setup-node config nearby.
FILE=".github/workflows/pr-validation.yml"
if [ -f "$FILE" ]; then
  echo "== $FILE =="
  nl -ba "$FILE" | sed -n '1,140p'
else
  echo "Missing $FILE" >&2
  exit 1
fi

# Also show the check-audit script for context on what error outputs it consumes.
SCRIPT=".github/scripts/check-audit.mjs"
if [ -f "$SCRIPT" ]; then
  echo "== $SCRIPT =="
  nl -ba "$SCRIPT" | sed -n '1,200p'
else
  echo "Missing $SCRIPT" >&2
  exit 1
fi

Repository: reqcore-inc/reqcore

Length of output: 166


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE=".github/workflows/pr-validation.yml"
if [ -f "$FILE" ]; then
  echo "== $FILE =="
  awk 'NR>=1 && NR<=160 {printf "%d:%s\n", NR, $0}' "$FILE"
else
  echo "Missing $FILE" >&2
  exit 1
fi

echo
echo "== setup-node occurrences =="
rg -n "setup-node|node-version" .github/workflows/pr-validation.yml .github/workflows -S || true

echo
SCRIPT=".github/scripts/check-audit.mjs"
if [ -f "$SCRIPT" ]; then
  echo "== $SCRIPT =="
  awk 'NR>=1 && NR<=220 {printf "%d:%s\n", NR, $0}' "$SCRIPT"
else
  echo "Missing $SCRIPT" >&2
  exit 1
fi

Repository: reqcore-inc/reqcore

Length of output: 8324


Pin npm@11 (and surface audit-error.txt)—Node 20 is compatible

  • actions/setup-node@v6 uses node-version: 20; npm 11’s engines are ^20.17.0 || >=22.9.0, so the current Node 20 setup should satisfy the requirement.
  • audit-error.txt is still never surfaced in the PR summary; if npm audit fails before producing useful JSON, the stderr context won’t be visible (only audit-output.txt is).
  • npx -y npm@11 is floating; pinning to a specific npm 11.x version (e.g., npm@11.16.0) would make the audit gate reproducible over time.
🤖 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/pr-validation.yml around lines 55 - 56, Pin the floating
npm invocation and surface the stderr file so audit failures are reproducible
and visible: change the npx call (currently "npx -y npm@11 audit ...") to a
pinned release such as "npx -y npm@11.16.0 audit --json > audit-output.json 2>
audit-error.txt || true" and update the downstream invocation of the audit
checker (node .github/scripts/check-audit.mjs) to also consume or print
audit-error.txt (for example pass audit-error.txt as an additional argument to
check-audit.mjs or cat audit-error.txt into the piped output) so the contents of
audit-error.txt are included in audit-output.txt and the PR summary; ensure
references to "npx -y npm@11", "audit-error.txt", and "node
.github/scripts/check-audit.mjs" are updated accordingly.

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