Skip to content

fix(deps): clear production npm audit advisories - #146

Open
BenSheridanEdwards wants to merge 1 commit into
mainfrom
fix/audit-prod-advisories
Open

BenSheridanEdwards wants to merge 1 commit into
mainfrom
fix/audit-prod-advisories

Conversation

@BenSheridanEdwards

Copy link
Copy Markdown
Owner

Summary

The production audit reported 24 high + 1 low advisories and blocked the
NativeProof checks Buildkite pipeline. All 25 entries collapse to nine
transitive leaf packages
— no advisory targets wdio, appium or
webdriverio themselves. Every @wdio/*, @appium/*, webdriver,
expect-webdriverio and @puppeteer/browsers entry was propagation from one of
those leaves.

That is why npm's suggested remedy (@wdio/local-runner@7.40.0) was rejected: it
is a major downgrade of the runner that fixes nothing at the source. It only
appears because npm walked backwards looking for a wdio tree not depending on
vulnerable deepmerge-ts.

Fixed at the source with npm overrides — the lever this repo already uses for
serialize-javascript — keeping each leaf inside its own major line wherever a
patched release exists:

Leaf Before After Note
brace-expansion 1.1.15, 2.1.1, 5.0.6 1.1.18, 2.1.4, 5.0.9 three copies, per-major selectors
undici 6.27.0, 7.28.0 6.28.0, 7.29.0 two copies, per-major selectors
body-parser 2.2.2 2.3.0 in-major
fast-uri 3.1.2 3.1.6 in-major
js-yaml 4.2.0 4.3.2 in-major (v5 not needed)
shell-quote 1.8.4 1.10.0 in-major
ip-address 10.2.0 dropped from tree
deepmerge-ts 7.1.5 8.0.2 major bump — see Risk
@puppeteer/browsers 2.x 3.2.1 major bump — removes extract-zip

Two cases needed more than a version bump:

  • deepmerge-ts — the newest wdio (9.31.4, already inside our ^9.29.1
    range) still pins deepmerge-ts@^7.0.3, so no wdio release clears this,
    forwards or backwards. An override is the only lever.
  • extract-zip — advisory GHSA-jmr9-qjv8-65gv has range *; latest
    (2.0.1) is the newest ever published and there is no patched release. Rather
    than accept it as permanent residue, @puppeteer/browsers@3.2.1 drops the
    dependency entirely
    , so extract-zip is now absent from the tree.

appium is floored at ^3.7.0: @appium/support@7.2.7 already carries patched
shell-quote and body-parser, clearing the whole @appium/* cluster without
an override. The old ^3.5.2 floor could still resolve to the vulnerable 3.5.2.

No residue — nothing had to be accepted or silenced, so there is no
documented-exception section.

Proof

  • npm run check
  • npm test
  • Generated project/device proof, or N/A: covered by npm test
    package-smoke.test.ts packs the real tarball and exercises the
    init/onboard scaffold (packed package exposes the onboarding CLI bins and ESM scaffold, 1592ms). No CLI, template or device behaviour changed.

All commands run from a clean npm ci on this branch.

The gate that was failing:

$ npm audit --omit=dev --audit-level=high
found 0 vulnerabilities
AUDIT EXIT: 0

Zero residue even at the strictest thresholds:

$ npm audit --omit=dev --audit-level=moderate   # exit 0
$ npm audit --omit=dev                          # exit 0 (all severities)

Repo gates:

$ npm run check
> biome check . && tsc --noEmit
Checked 56 files in 33ms. No fixes applied.
CHECK EXIT: 0

$ npm test
ℹ tests 224
ℹ suites 5
ℹ pass 224
ℹ fail 0
TEST EXIT: 0

Because the unit suite only loads @wdio/globals, it would not have caught a
broken named ESM import from the two major overrides — a bad import throws at
module load, not at call time. Verified the runtime surface explicitly:

$ node -e 'await import(m)' for each wdio runtime module
  OK    @wdio/utils/node        <- imports @puppeteer/browsers
  OK    webdriver               <- uses deepmergeCustom({mergeArrays:false})
  OK    @wdio/config
  OK    @wdio/local-runner
  OK    @wdio/mocha-framework
  OK    @wdio/spec-reporter
  OK    @wdio/globals
  OK    webdriverio
  OK    expect-webdriverio
All wdio runtime modules load cleanly

And that deepmerge-ts@8 preserves the exact semantics wdio relies on:

deepmergeCustom({ mergeArrays: false }) -> {"a":{"cmd":1,"cmd2":2},"arr":[3]}   # replaces
deepmerge(...)                          -> {"args":["--a","--b"],"binary":"x"}  # concatenates

Risk

  • deepmerge-ts 7 → 8 (major). wdio imports only deepmerge and
    deepmergeCustom. v8 is purely additive on exports (adds
    deepmergeFastUnsafe*, getKeysOfObjects); both used exports survive, and
    both merge behaviours are asserted identical above. The real v8 break is an
    engine floor of node >=16.9.0 — this package already requires node >=20.
  • @puppeteer/browsers 2 → 3 (major). wdio imports eight names
    (install, canDownload, resolveBuildId, detectBrowserPlatform,
    Browser, ChromeReleaseChannel, computeExecutablePath); all are still
    exported by 3.2.1, confirmed against its actual export list. This module is
    only reached by startWebDriver for desktop-browser driver downloads, which
    NativeProof's native-mobile lane never invokes.
  • Overrides are root-only. npm applies overrides only for the root
    project, so consumers installing the published nativeproof package do not
    inherit these pins and may still resolve the vulnerable transitives. This PR
    fixes NativeProof's own gate; propagating the pins to generated projects would
    be a separate change to the init template.

Notes

  • Full device coverage not run: this change touches only the dependency tree —
    no device, Appium or driver behaviour changed, so the device lane adds no
    signal beyond the runtime load check above.
  • No CHANGELOG entry: this repo writes CHANGELOG entries when cutting a release,
    not per fix commit (none of the last four fix commits touched it).

PR Proof Law

  • I followed .agents/DEFINITION_OF_DONE.md and .agents/skills/pr-inline-screenshot-proof/SKILL.md.
  • Screenshots are committed and embedded inline with ![alt](...png?raw=1), or the proof section says Not applicable with the technical reason.
    Not applicable — this change alters only the resolved dependency tree
    (package.json + package-lock.json). It renders no UI and changes no
    on-device behaviour, so there is no visual surface to screenshot. The
    proof surface is command exit codes, reproduced verbatim above.
  • The PR body has no bare screenshot links, local paths, relative paths, or proof placeholders.

The production audit reported 24 high and 1 low advisory. All 25 entries
resolve to nine transitive leaf packages; no advisory targets wdio, appium
or webdriverio themselves, so npm's suggested @wdio/local-runner@7.40.0
remedy is a major downgrade of the runner that fixes nothing at the source.

Pin the vulnerable leaves with npm overrides instead, keeping each within
its own major line where a patched release exists:

- brace-expansion 1.1.18 / 2.1.4 / 5.0.9 (per-major selectors; three copies)
- undici 6.28.0 / 7.29.0 (two copies)
- body-parser 2.3.0, fast-uri 3.1.6, js-yaml 4.3.2, shell-quote 1.10.0
- deepmerge-ts 8.0.2 — major bump; latest wdio 9.31.4 still pins ^7.0.3,
  so no wdio release clears this and an override is the only lever
- @puppeteer/browsers 3.2.1 — drops extract-zip, whose advisory
  (GHSA-jmr9-qjv8-65gv) covers all published versions and has no fix

Raise the appium floor to ^3.7.0; @appium/support 7.2.7 already carries
patched shell-quote and body-parser, clearing the @appium/* cluster.

npm audit --omit=dev --audit-level=high now exits 0 with no residue.
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