Skip to content

chore(deps): clear dev-scoped npm alerts in the E2E harnesses and close the gaps that let them accumulate - #5523

Merged
robfrank merged 5 commits into
mainfrom
chore/deps-e2e-npm-hygiene
Jul 29, 2026
Merged

chore(deps): clear dev-scoped npm alerts in the E2E harnesses and close the gaps that let them accumulate#5523
robfrank merged 5 commits into
mainfrom
chore/deps-e2e-npm-hygiene

Conversation

@robfrank

Copy link
Copy Markdown
Collaborator

What does this PR do?

Clears all 6 open Dependabot alerts and closes the process gaps that let them accumulate.

Every open alert was a development-scope npm transitive inside the E2E test harnesses. The Maven ecosystem (the shipped Java product), Studio frontend, Docker, Go and Python ecosystems all had zero open alerts, so nothing here touches a shipped artifact.

# Sev Package CVE Lockfile Fix
157 high brace-expansion CVE-2026-13149 e2e-studio 2.1.1 → 2.1.3
154 high brace-expansion CVE-2026-13149 e2e-js 2.0.2 → 2.1.3
153 high brace-expansion CVE-2026-13149 e2e-js 1.1.14 → 1.1.16 (nested)
155 high js-yaml CVE-2026-59869 e2e-js 3.14.2 → 3.15.0
150 medium js-yaml CVE-2026-53550 e2e-js 3.14.2 → 3.15.0
139 low @babel/core CVE-2026-49356 e2e-js 7.29.0 → 7.29.7

Four commits, each independently reviewable:

  1. chore(deps) — lockfile refresh in both E2E projects. Every bump fits an existing semver range, so no package.json changes and no major upgrades.
  2. ci — group the /e2e-js and /e2e-studio npm ecosystems in dependabot.yml. They were the only npm entries without a groups: block, so each transitive patch bump consumed one of ten PR slots. Matches the existing /e2e-go and /studio conventions.
  3. ci — install E2E dependencies with npm ci instead of npm install.
  4. ci — new .github/workflows/e2e-dependency-audit.yml, a scope-split audit.

Motivation

Two findings drove the scope beyond a plain lockfile bump.

The lockfile was not authoritative in CI. Both E2E jobs ran npm install, which is free to re-resolve. Dependabot scans the lockfile, so pinning a patched transitive there proved nothing about what CI actually installed — Tier 1 alone would have been cosmetic. Both jobs already declared cache-dependency-path pointing at the lockfile, so npm ci is the pattern they were written for.

The audit gate has to be scope-split to stay meaningful. brace-expansion GHSA-mh99-v99m-4gvg / CVE-2026-14257 is vulnerable at <= 5.0.7 and patched only in 5.0.8. There is no 2.x backport and minimatch 5/9 pin ^2.x, so it is not fixable without downgrading testcontainers and jest by several majors — which is literally what npm audit fix --force proposes (jest@25, testcontainers@7). GitHub already auto-dismissed it (alerts #156, #158).

So the new workflow blocks on runtime scope only (npm audit --omit=dev, currently zero findings in both projects, so the gate is real) and reports development-scope findings to the job summary without failing. A full-tree gate would be permanently red, and a permanently-red gate teaches people to ignore it.

Related issues

No issue filed; this is direct remediation of the open alerts at https://github.com/ArcadeData/arcadedb/security/dependabot.

Deliberately out of scope: the stale Maven Dependabot PRs #3235 (ANTLR 4.9.1 → 4.13.2, open since January, 13 failing checks, cross-cutting across gremlin/graphql/postgresw/engine) and #4969 (Groovy 4.0.32 → 5.0.7, 6 failing checks). Both are breaking-change majors needing their own branch and investigation; folding them in here would make this unreviewable. They are the larger real risk and worth separate attention.

Additional Notes

One manual step this PR cannot perform. The repository's Dependabot auto-triage rule dismisses development-scope alerts for CWE-400/770/835/674 but not CWE-407 (inefficient algorithmic complexity) or CWE-22. That gap is the actual reason these ReDoS-class advisories against test-only packages kept surfacing. Widening the rule to include CWE-407 for development scope is a Security → Dependabot → auto-triage rules setting in the GitHub UI with no config-file equivalent. The explanation is recorded as a comment at the top of .github/dependabot.yml so the next person finds it.

Verification actually run locally:

  • Confirmed the vulnerable versions were present before fixing, so the checks could have failed.
  • All 6 alerts clear; asserted against each advisory's exact patched-version floor.
  • js-yaml and @babel/core disappear from the audit entirely. Residual findings are only the CVE-2026-14257 family described above.
  • Runtime scope (--omit=dev) is zero in both projects, before and after.
  • npm ci exits 0 in both and installs exactly the patched versions. This gated the CI change rather than following it.
  • Both harnesses still work: Jest boots and enumerates 3 suites (including under --coverage, the path that actually loads @babel/core and js-yaml via load-nyc-config); Playwright enumerates 84 tests in 13 files. All three bumped packages exercised functionally.
  • The new workflow's summary step was extracted from the YAML and executed verbatim, so its heredoc is not first tested in CI. Its blocking gate passes today in both projects.
  • All three YAML files parse.

Not run locally: the full E2E suites, which need a built ArcadeDB Docker image. CI covers those, and this PR's npm installnpm ci change makes those runs the real test of the lockfile.

The implementation plan is committed at docs/superpowers/plans/2026-07-29-dependabot-e2e-npm-hygiene.md.

Checklist

  • I have run the build using mvn clean packagenot applicable and not run. This PR touches no Java, no pom.xml, and no studio/ code; the diff is two npm lockfiles, dependabot.yml, and two workflow files.
  • My unit tests cover both failure and success scenariosno unit tests added. This is dependency and CI configuration. The equivalent evidence is the verification list above, including the confirmed-failing baseline before the fix.

robfrank added 5 commits July 29, 2026 09:48
Refreshes the e2e-js and e2e-studio lockfiles to clear six Dependabot
alerts, all development-scope transitive dependencies:

  brace-expansion 2.0.2 -> 2.1.3, nested 1.1.14 -> 1.1.16 (CVE-2026-13149)
  js-yaml         3.14.2 -> 3.15.0 (CVE-2026-59869, CVE-2026-53550)
  @babel/core     7.29.0 -> 7.29.7 (CVE-2026-49356)

Every bump fits an existing semver range, so no package.json changes and
no major upgrades. Runtime-scope dependencies were already clean and stay
clean.

brace-expansion CVE-2026-14257 remains reported by npm audit. It is
vulnerable at <= 5.0.7 and patched only in 5.0.8, with no 2.x backport,
while minimatch 5/9 pin ^2.x. It is not fixable without downgrading
testcontainers and jest by several majors, and GitHub auto-dismissed it.
/e2e-js and /e2e-studio were the only npm ecosystems without a groups
block, so every transitive patch bump consumed one of ten PR slots. Group
minor/patch into a single weekly PR per directory, matching the /e2e-go
and /studio conventions, and leave majors opening individually.

Also documents why ReDoS-class advisories against test-only packages keep
surfacing: the auto-triage rule covers CWE-400/770/835/674 for development
scope but not CWE-407. That rule lives in the GitHub UI, not in this file.
Both E2E jobs ran npm install, which re-resolves and may drift from the
committed lockfile. Dependabot scans the lockfile, so pinning a patched
transitive there proved nothing about what CI actually installed.

npm ci installs the lockfile exactly and fails loudly when it disagrees
with package.json. Both jobs already set cache-dependency-path to the
lockfile, so this is the pattern they were written for.
Adds a weekly and path-triggered audit for e2e-js and e2e-studio that
splits the gate by dependency scope. Runtime-scope findings fail the job
and are currently zero in both projects, so the gate is meaningful.
Development-scope findings are written to the job summary and never fail.

A blocking gate over the full tree would be permanently red: the
brace-expansion advisory CVE-2026-14257 is patched only in 5.0.8, has no
2.x backport, and minimatch pins ^2.x. npm audit proposes escaping it by
downgrading jest and testcontainers by several majors, which the workflow
header explicitly warns against.

The job also runs npm ci, so a lockfile that drifts out of sync with
package.json fails here rather than inside a full E2E run.
@mergify

mergify Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

@codacy-production

codacy-production Bot commented Jul 29, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 0 complexity

Metric Results
Complexity 0

View in Codacy

🟢 Coverage ∅ diff coverage · -5.60% coverage variation

Metric Results
Coverage variation -5.60% coverage variation
Diff coverage diff coverage

View coverage diff in Codacy

Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (5b4fd07) 146712 108862 74.20%
Head commit (8e234c7) 178704 (+31992) 122591 (+13729) 68.60% (-5.60%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#5523) 0 0 ∅ (not applicable)

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@claude

claude Bot commented Jul 29, 2026

Copy link
Copy Markdown

Code review

Reviewed the full diff. This is a careful, well-documented, low-risk PR: the lockfile bumps all stay inside existing semver ranges (so npm ci stays in sync), the Actions are SHA-pinned with version comments, job permissions are scoped to contents: read, fail-fast: false is set, and the audit-node matrix (e2e-js/24, e2e-studio/22) matches mvn-test.yml. The scope-split gate plus non-blocking summary is a sound design, and committing the plan under docs/superpowers/plans/ follows established repo convention. A few observations, none blocking:

  1. The blocking runtime gate is vacuous for e2e-studio. Its package.json declares only devDependencies (no dependencies block), so npm audit --omit=dev audits an empty production tree and can never fail regardless of what surfaces. The workflow header and PR frame the gate as "meaningful rather than decorative," which holds for e2e-js (real runtime deps: neo4j-driver, pg) but is only vacuously true for e2e-studio - there is nothing in runtime scope there to regress. Not a bug and harmless, but the "meaningful in both projects" framing is slightly overstated. A one-line note that the studio gate is structurally always-green would be more accurate.

  2. The "non-blocking" report step can still fail the job. In the report step, npm audit --json > audit.json || true guards the audit command, but the following json.load(fh) is not guarded. If npm audit emits nothing parseable (e.g. a registry/network hiccup leaves audit.json empty), json.load raises, the Python exits non-zero, and the step - hence the job - goes red. That contradicts the stated "development-scope findings never block" intent. An npm error response is normally still JSON with an error key (degrades gracefully to zero counts here), so this is low-probability, but a try/except around the load (or an empty-file guard) would make the guarantee airtight.

  3. The blocking gate has an external-availability dependency. npm audit --omit=dev --audit-level=high calls the npm advisory endpoint, so a registry outage produces a red gate that blocks merges rather than a dependency regression. Acceptable given the workflow is path-triggered and scheduled rather than on every PR, but worth awareness when it fires spuriously.

Minor:

  • audit-level=high means moderate/low runtime findings will not block - intentional and reasonable, just noting the gate only catches high/critical in runtime scope.
  • Doc nit: the PR-body table lists the e2e-studio brace-expansion bump as 2.1.1 to 2.1.3 while the plan alert table lists the patched floor as 2.1.2; and babel/core shows 7.29.7 in one table vs a 7.29.6 floor in the plan. Cosmetic, the lockfiles landed correctly.

Nothing here needs to hold the merge. Points 1 and 2 are the two I would consider addressing (a wording tweak and a defensive guard around json.load).

@robfrank
robfrank merged commit 6de851d into main Jul 29, 2026
25 of 28 checks passed
@robfrank
robfrank deleted the chore/deps-e2e-npm-hygiene branch July 29, 2026 08:35
@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 66.50%. Comparing base (5b4fd07) to head (8e234c7).
⚠️ Report is 28 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #5523      +/-   ##
============================================
+ Coverage     65.34%   66.50%   +1.16%     
============================================
  Files          1748     1748              
  Lines        146712   146712              
  Branches      31356    31356              
============================================
+ Hits          95868    97573    +1705     
+ Misses        37893    36034    -1859     
- Partials      12951    13105     +154     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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