fix(doctor): avoid unsafe npm audit fallback

Root-level npm audit fix can crash with isDescendantOf on the same monorepo tree, so workspace audit advisories should explain the lockfile-bump path instead of recommending another manual npm fix command.
This commit is contained in:
Teknium
2026-06-13 05:09:56 -07:00
parent bea6c1c01f
commit 905ed413d1
2 changed files with 42 additions and 25 deletions
+22 -12
View File
@@ -1411,12 +1411,15 @@ class TestDoctorStaleMaxIterationsDrift:
def test_npm_audit_fix_hint_avoids_crashing_workspace_flag(monkeypatch, tmp_path):
"""`hermes doctor` must not hand users `npm audit fix --workspace <name>`:
that exact form crashes npm with "Cannot read properties of null (reading
'edgesOut')" (an arborist bug with workspace-filtered audit fix). The
remediation hint for a workspace vulnerability must be the root-level
`npm audit fix`, which works.
'edgesOut')" (an arborist bug with workspace-filtered audit fix).
Regression for the Docker reports (Pinched-Nerve / lynch1972) where doctor
flagged the web/ui-tui workspaces and the suggested fix command errored out.
It must not recommend root-level `npm audit fix` for workspace advisories
either: current npm can crash there too with "Cannot read properties of null
(reading 'isDescendantOf')" on this tree. The safe guidance is that these
build-tool advisories clear via the lockfile/package bump.
Regression for user reports where doctor flagged the web/ui-tui workspaces
and the suggested fix command errored out.
"""
home = tmp_path / ".hermes"
home.mkdir(parents=True, exist_ok=True)
@@ -1434,12 +1437,18 @@ def test_npm_audit_fix_hint_avoids_crashing_workspace_flag(monkeypatch, tmp_path
)
def mock_run(cmd, **kwargs):
if "audit" in cmd:
if "audit" in cmd and "--workspace" in cmd:
payload = (
'{"metadata": {"vulnerabilities": '
'{"critical": 0, "high": 2, "moderate": 0}}}'
)
return SimpleNamespace(returncode=1, stdout=payload, stderr="")
if "audit" in cmd:
payload = (
'{"metadata": {"vulnerabilities": '
'{"critical": 0, "high": 0, "moderate": 0}}}'
)
return SimpleNamespace(returncode=0, stdout=payload, stderr="")
return SimpleNamespace(returncode=0, stdout="", stderr="")
import subprocess
@@ -1454,14 +1463,15 @@ def test_npm_audit_fix_hint_avoids_crashing_workspace_flag(monkeypatch, tmp_path
# The workspace vulnerability is still reported ...
assert "web workspace" in out
# ... but the remediation must NOT use the npm-crashing per-workspace form
# (`npm audit fix --workspace web` / `--workspace ui-tui`). The unrelated
# root target's `--workspaces=false` is a different, non-crashing command.
# (`npm audit fix --workspace web` / `--workspace ui-tui`).
assert "npm audit fix --workspace web" not in out
assert "npm audit fix --workspace ui-tui" not in out
# ... it offers the safe root-level command instead.
assert "&& npm audit fix)" in out
# ... and it must not point at the root-level form either: npm can crash
# there too with `isDescendantOf` on this monorepo tree.
assert "npm audit fix" not in out
# ... and explains the workspace advisories are build-time tooling whose
# `npm audit fix` may itself hit a known npm arborist crash, so the user
# isn't left thinking a crashing command means a broken Hermes install.
# manual remediation may hit a known npm arborist crash, so the user isn't
# left thinking a crashing command means a broken Hermes install.
assert "build-time tooling" in out
assert "known npm bug" in out
assert "lockfile bump" in out