Repository navigation
npm: v3 lockfiles emit workspace paths and alias keys as registry dependencies with allow: all #16488
Description
Activity
- addedL: dockerDocker containersDocker containersL: ruby:bundlerRubyGems via bundlerRubyGems via bundler
on Oct 7, 2026 Proposed repair: #16490 (commit 8c005c7).
The fix retains alias installation keys for native npm commands and uses the real package name only at registry/metadata boundaries; canonicalizing Dependency.name alone would lose independently constrained aliases. It also removes local workspace descriptors from registry candidates and preserves target/version identity through collisions.
Local verification on the pinned npm updater image: 836 examples, 0 failures, 19 changed Ruby files lint clean, real update/reparse plus npm ci/runtime checks for both lockfile formats and a mixed-target alias collision. Existing manifest-alias rewriting, canonical advisory matching and native workspace-update limits are explicitly unchanged. Full details and regressions are in the PR. This is a proposed code fix, not confirmation that the managed updater has been deployed.
Deeper identity-path follow-up is now in #16490, head
5c071c04aaece71e10007a520d6859e3edf4f42e.- Lockfile selection now compares the requested registry target’s own version, not an unrelated namesake’s minimum. A 972-case target/version/order matrix went from 384 mismatches to zero.
- Canonical-package
all_versionsis separated from the full installation-slot records. Registry vulnerability checks no longer consume unrelated target versions, while installation-name blocked-version rules still cover every sibling alias. Raw parser records remain acyclic and dependency graph identities are preserved. - Verification: 941 npm/common examples and 14 updater-policy examples, zero failures; 24-file Ruby lint; 16 metadata/advisory/policy cases; real native lockfile updates followed by npm ci and module execution. Hosted CI caught an ecosystem-dependent test import; the corrected test also passes in the bundler-only updater image.
- A separate native npm 12.2.0 defect allowed successful install/ci to execute ordinary ms@2.0.0 in a workspace explicitly requesting npm:is-odd@2.0.0. Minimal explicit-alias validator fix and public reproducer: fix(arborist): preserve explicit npm alias target identities npm/cli#10090 (142 assertions and native before/after runtime checks).
No dependency exclusions, manifest rewrites, or reduced coverage. These are upstream proposals, not a hosted Dependabot rollout. Installation-name scheduling, canonical advisory matching for alias names, and native cross-workspace target isolation are not presented as solved. Current CI status and the earlier follow-redirects snapshot differences are documented in the PR.
All three upstream branches are now synchronized without rewriting published history:
- Fix npm workspace and alias identities in lockfile updates #16490 — head
a923659, current main included, all 21 fresh required checks pass. The final complete rollup is 149 successful, 4 skipped, 3 failed optional smoke checks, with no jobs left running or queued. All three failures have exact unmodified-base controls. The previous BEHIND blocker is cleared. Detailed CI evidence and historical smoke diagnosis. - fix(arborist): preserve explicit npm alias target identities npm/cli#10090 — head
737460c, current latest included, review diff limited to the three intended Arborist files. 5,225 assertions passed, three platform skips, 100% coverage, ESLint passed. - fix(arborist): scope named updates to selected workspaces npm/cli#10091 — head
483252f, current latest included, review diff limited to the four intended Arborist files. Added behavioral coverage for adopted cyclic/link graphs, absent optional peers, disabled-workspace boundaries, and invalid-root repair. 5,147 assertions passed, three platform skips, 100% coverage, ESLint passed.
Actual npm12.2.0 source CLI checks passed independently and composed: installation-name/version collisions retain canonical identities; only the selected workspace is eagerly updated; npm ci, real module calls, manifest bytes, and ci lockfile bytes check out. No coverage threshold was relaxed and no failure was ignored.
Maintainer gates: approve fork workflows (alias run, workspace run), review and merge the PRs, then release/adopt the native npm changes and verify hosted Dependabot rollout. Current credentials have read-only upstream access and cannot approve workflows or merge. The issue stays open. All three optional failures (npm, group-rules, group-semver) were proven identical to their respective unmodified-base controls (each two hunks, 12 changed lines); tracked separately at dependabot/smoke-tests#592. Canonical-alias scheduling/advisory gaps are not claimed resolved. Existing review requests already target the appropriate maintainer teams, so no duplicate requests were sent. The Core PR uses a non-closing issue reference to preserve the rollout gate.
No application dependency, lockfile, or Dependabot-ignore changes were made during this continuation.
- Fix npm workspace and alias identities in lockfile updates #16490 — head
Latest Smoke diagnosis (2026-10-09)
At unchanged discovery head
29e40163970538243917eaef8f742ebe220bf086, Smoke run 37867769858 executed 97 E2E jobs: 95 passed their test and Diff steps; 2 failed. The failures in this run are NuGet and pip-compile, not Gradle. Required-check success must not be described as an entirely green Smoke run; earlier head-specific results below remain historical.- NuGet aborts during clone/fetch, before registry replay (0/0 cached calls). Its unchanged ShellGitCommandHandler discards non-authentication Git failures. A host .NET 8 runtime probe linked to the production process/handler files, using real Git and a deliberately non-listening loopback proxy, observed clone exit 128, successful handler return, then fetch raising
Win32Exception(2)because the checkout directory did not exist. This verifies the misleading-error mechanism, not the original CI clone error, whose stderr was discarded. - [INFERENCE] The CI startup log order is consistent with the existing proxy-readiness race: clone/fetch errors appear before the proxy's
Listening (:1080)message. CLI #658 already addresses that startup-ordering gap and remains open. It is independent of discovery Fail smoke discovery on GitHub API and pipeline errors #16498 and replay-clock Go modules (vgo) support #668; no duplicate fix, retry, weakened assertion, or new NuGet change was added to this chain. - pip-compile produces the same five expected dependency updates; its diff is the five
pycparser==3.0→3.1lockfile changes already recorded in smoke-tests #595, with 96/130 calls cached.
The six reviewed PR heads, review feedback, release gates and upstream cache publication are unchanged. Core/CLI latest releases remain v0.399.0/v1.94.0; matching upstream artifacts are still absent. Maintainer approval, release and cache-publication steps remain required. The previously denied upstream workflow dispatch was not retried, and no branch or fixture was changed by this investigation.
Gradle/pip-compile follow-up (2026-10-08)
The two residual suites are now diagnosed and their clean recordings are published separately in smoke-tests#595, head
ddcf3e24cea11fcd30a7e8de4b2f62d5278b6421. Gradle's old Maven cache keys omit:443; pip's old PyPI keys include a Cache-Control header the current client no longer sends. These misses reached live registry data.Actual clean-cache regeneration changes only five uncapped
pycparser==3.1lines and adds real Hibernate release notes. All job inputs, source commits, ignore conditions, selected primary versions and expected PR sets are preserved. Final released-CLI v1.94.0 replays are full-YAML byte-identical: Gradle 119/119 cached; pip-compile 130/130 cached; both PASS, with no metadata/job errors. No Core/proxy workaround or weakened check was needed.Released CI for #595: pip-compile passes; Gradle still fails. Gradle now creates all four PRs; its sole diff is the 29-line Hibernate release-note block absent from the old cached releases response (75/116 cached). pip-compile is green at 96/130 cached. Suite discovery and yamllint pass. This confirms why matching Cache One artifacts are still required; expectations must not be weakened to accommodate stale metadata.
Hosted proof added (23:02 UTC): the unchanged Cache One workflow passes in the writable fork at the same #595 head: Gradle and pip-compile. Both downloadable artifacts were replayed without editing responses: full-YAML byte-identical at 119/119 and 130/130 cached. #595 contains artifact links, upload digests and download commands. This is fork-hosted evidence only; the upstream consumer still requires maintainer-published artifacts in
dependabot/smoke-tests. No code or constraints changed; fork workflows are inactive again.Upstream gate remains: a maintainer must run Cache One at
refs/pull/595/headforgradleandpython-pip-compile, publish both matching caches, and rerun/review the fixture PR before merging. Then rerun Core #16498 Smoke against the new main fixture blobs. #595 is now ready for review, withdependabot/maintainersalready requested; matching upstream caches and passing Smoke checks remain required before merge. Fork/local proof does not turn the historical 95/97 CI result green. The independent npm #593, Core review and CLI clock-release gates remain unchanged.Initial investigation (historical)
Separate baseline-smoke investigation completed: Core #16492 fixes npm transitive resolver/writer cooldown disagreement without changing the existing alias/workspace PR branches. Verification: 234 passing examples, clean Ruby lint, and four actual resolver→writer smoke scenarios with matching versions.
The clock experiment also proved that HTTP fixture replay remains sensitive to elapsed release age; that distinct limitation is documented in smoke-tests #592. No snapshots were weakened or hand-repinned. Initial cooldown-head CI: 21/21 required checks passed; the three optional smoke failures exactly match the unmodified-base controls. Completed CI evidence. Maintainer review/merge is still required; existing upstream review/release gates remain separate.
Review routing: requesting the same
maintainersteam used by the existing Core PR returned HTTP 404 from the review-request API with the current account. No approval or merge was attempted. This failed request did not establish that no existing team requests existed; see the REST-verified routing correction below.Replay-clock continuation: dependabot/cli#668 captures and replays Ruby/native npm clocks. Actual Core updates at Oct 2 and Oct 7 produced matching dependency/lockfile versions, and the original replay was byte-identical with 20/20 HTTP calls cached. Full local Go suite passed twice with race detection; Current CLI CI is complete after integrating v1.94.0: 104/104 checks passed, including 2/2 required checks, with no failed or pending checks (dependabot/cli#668 (comment)). Maintainer review remains required; the CLI CODEOWNERS team-review request returned HTTP 404 with this account. No existing PR branches or application code changed. Smoke fixture regeneration and the separately tracked ignored-version cap remain outstanding.
Current integration status
Latest runtime heads are Core #16492
97c3cac44b62df8ecf93b08f9041849e85ffa20fand Core #16496de4a7cb8bf466b2667fdb4b8bc5948a1061d86c2, both incorporating main0286aa0868b1f0de1b908ce3358bbf994e5272c1. The merge changes shared notice rendering and Julia stdlib notices, without weakening npm policy guards or fixture contracts.Full-repository Sorbet passed on all three refreshed Core branches and again after the policy spec-isolation correction. Direct shared-notice rendering confirms INFO/fallback → NOTE, WARN → WARNING, ERROR → IMPORTANT. Three complete CLI replays at cooldown
97c3cac44b62df8ecf93b08f9041849e85ffa20f+ policy260f77e6e25e0b6cbcf00882ada974398de69a82are byte-identical, with 202/202, 200/200 and 249/249 cached calls, unchanged clocks and no metadata/job errors. Policy’s subsequentde4a7cb8bf466b2667fdb4b8bc5948a1061d86c2commit changes only spec isolation and its README; all mounted runtime library trees are unchanged. CLI source is unchanged; no new Go-suite run is claimed.Test-isolation follow-up at
de4a7cb8bf466b2667fdb4b8bc5948a1061d86c2: package-manager specs left npm selectors active across examples, producing 24 failures in the previous full npm run. Shared cleanup now resets both active and per-directory selectors after each example; redundant local cleanup hooks were removed. The existing two-example reproducer fails before / passes after, the complete previously failing worker passes 564 examples, 0 failures at seed 16904, all five changed Ruby files pass RuboCop, and full-repository Sorbet reports no errors. No production runtime code, cooldown/ignore guard or fixture contract changed.Core #16492 CI: 21/21 required checks passed; 55 successful / 4 skipped check records. Full npm/yarn specs: 2231 examples, 0 failures, 4 existing pending. No E2E jobs ran: discovery logged
jq: Cannot index string with string "name"but reported success; the overall Smoke workflow concluded failure. Green check records are not E2E coverage.Core #16496 CI: 21/21 required checks passed; 65 successful / 3 failed / 4 skipped check records, none pending. Full npm/yarn CI at
de4a7cb8bf466b2667fdb4b8bc5948a1061d86c2: 2231 examples, 0 failures, 4 existing pending, seed 28164. The previous 24 required-spec failures are resolved.Smoke actually ran 13 E2E jobs: 10 passed both the test and
Diffsteps, 3 failed. npm and rules omit the out-of-policy follow-redirects 1.16.1 / form-data 4.0.6 PRs still expected by main fixtures; cache coverage is 124/197 and 122/196. semver omits those dependencies from the expected group and has corresponding lockfile/metadata differences, with 148/223 cached calls. All three used released CLI v1.94.0 and main fixtures/official caches, not draft #593. These failures remain visible; no baseline-identical or released-toolchain-pass claim is made.Core #16498 at
f4f87c4f4645b14edfbe7aee80c63ab38243126e: 21/21 required checks passed; 150 checks succeeded, 2 failed, 4 skipped. Smoke run discovered and executed all 97 E2E jobs: 95 passed both the actual ecosystem test andDiffsteps; 2 failed. All 13 npm E2E jobs passed. The failures are Gradle (missing expected PR events after Maven metadata HTTP 404s; 95/125 calls cached) and pip-compile (pycparser3.0 → 3.1; 96/130 cached). This is main runtime/main fixtures, not the unreleased npm policy or draft recordings; the overall Smoke run is not green. No fixture assertion or unrelated ecosystem code was changed, and no failed job was rerun.CLI #668 remains at
49b4c7532aa9fbeb59b300432713bd1b5ed859ea: 104/104 checks, including 2/2 required, passed. Its full local Go race suite passed previously at the same head; it was not rerun during this Core-only update. The actual released v1.94.0 binary was already shown to dropinput.recorded-atdespite a successful event comparison; that failed release behavior was not rerun merely to confirm it.Maintainer actions: (1) review/merge the independent discovery workflow fix and obtain genuine runtime-branch E2E evidence; (2) review/merge CLI #668 and Core #16492/#16496, then release the CLI clock support and an updater containing both runtime fixes; (3) run Cache One for
npm,npm-group-rules, andnpm-group-semverat fixture headaeed1cf2ffe310b228b69cc493de09182455372f, with read-only recording credentials and checked metadata-fetch logs; (4) run released-toolchain Smoke and obtain fixture review. CLI v1.94.0 still lacks clock replay. No upstream approval, upstream merge, release, official cache refresh, raised cap, changed source commit, or workflow/protection bypass was performed.Review-routing correction: REST
GET /repos/{owner}/{repo}/pulls/{number}/requested_reviewersconfirms thatdependabot/maintainersis already requested on Core #16492, #16496, #16498 and CLI #668. CLI #668 also requestsdependabot/azure-dev-ops. These requests predate this continuation: Core requests are dated October 7/8 and both CLI requests October 7.gh pr viewdisplayed empty reviewer lists, while GraphQL reports the existing requests withrequestedReviewer: null; the empty display did not mean reviews were unassigned. Core REST evidence; CLI REST evidence.The later individual requests for
JamieMageeandjakecoffmanreturned HTTP 404 and added no individual reviewers. Existing team requests need review responses, not duplicate assignment. All four prerequisite PRs still reportREVIEW_REQUIRED; the account remains read-only upstream. No new review request, approval, upstream merge, release, official cache refresh or protection bypass was performed.Draft smoke-tests #593 is unchanged at
aeed1cf2ffe310b228b69cc493de09182455372f. It preserves every original policy input and recorded clock. Historical released-toolchain CI remains 2 passed / 3 failed; the complete local replay proof is not a claim of released-toolchain compatibility. Maintainer handoff.Independent AI review completed
Three independent reviewer agents covered all six PRs. Four reproduced defects were fixed: legacy npm v1 policy bypass, unsafe rebinding after nested removal, in-place alias identity substitution, and inconsistent duplicate-
.npmrcrelease-age precedence. Final re-review found no remaining actionable correctness finding.Core PR Current head Required checks Cooldown #16492 50d4e4221/21 pass Policy #16496 17d417e21/21 pass Discovery #16498 29e401621/21 pass Canonical npm suites: cooldown 2235 examples, 0 failures, 4 pending; final policy 2283 examples, 0 failures, 4 pending. The policy follow-up fixes old acceptance tests that tolerated a changed nested Acorn 6.4.2 under a 6.0.2 cap; production validation was not relaxed.
Local proof: four production-Ruby before/after cases, 85 helper/parser examples, 10 cooldown examples, four actual-workflow discovery cases, and all three complete npm fixture YAMLs byte-identical with the repaired combined Core runtime and CLI
49b4c75. The final policy commits after683673cchange only tests/docs, so those runtime replay pins remain valid. Earlier head-specific results above remain historical.AI-authored technical reviews: clock · cacheFixtures · policy · cooldown · discovery · npmFixtures. These were submitted as COMMENT, not maintainer approval.
Remaining external gates are unchanged: Core/CLI release and upstream cache publication, plus required maintainer approval. Direct upstream
gh workflow run cache-one.ymlreturned 403: Must have admin rights to Repository. #595 is ready for review; #593 remains draft. Fork cache evidence is not upstream cache publication, and stale-cache smoke failures remain real.- NuGet aborts during clone/fetch, before registry replay (0/0 cached calls). Its unchanged ShellGitCommandHandler discards non-authentication Git failures. A host .NET 8 runtime probe linked to the production process/handler files, using real Git and a deliberately non-listening loopback proxy, observed clone exit 128, successful handler return, then fetch raising
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsNo status
Summary
With npm lockfile v3 and
allow: [{ dependency-type: all }], a hosted version-update job attempts registry lookups for local workspace paths and npm alias keys. The job records workspace-path HTTP 405 and alias-key HTTP 404 registry errors and exits nonzero, even when it creates other dependency-update PRs.The same invalid dependency identities reproduce offline through the unmodified full npm parser in the exact hosted updater image. This report uses only a synthetic fixture; no original repository files or credentials are needed.
Runtime
ghcr.io/dependabot/dependabot-updater-npm:3507ad510e0351d2bcd8e3975e9c323aa6d00e02sha256:4beb224504e150d978da4212e06eb390ba4abb630eeedcfc7d44b265aa1e0d1eMinimal fixture
Create
repro/package.json:{ "name": "dependabot-parser-repro", "version": "1.0.0", "private": true, "workspaces": ["packages/*"], "dependencies": { "is-number-alias": "npm:is-number@7.0.0" } }Create
repro/packages/local/package.json:{ "name": "local-workspace", "version": "1.0.0", "private": true }From
repro/, runnpm install --package-lock-only --ignore-scripts --legacy-peer-deps --no-audit --no-fund. The resulting lockfile is:{ "name": "dependabot-parser-repro", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "dependabot-parser-repro", "version": "1.0.0", "workspaces": [ "packages/*" ], "dependencies": { "is-number-alias": "npm:is-number@7.0.0" } }, "node_modules/is-number-alias": { "name": "is-number", "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "license": "MIT", "engines": { "node": ">=0.12.0" } }, "node_modules/local-workspace": { "resolved": "packages/local", "link": true }, "packages/local": { "name": "local-workspace", "version": "1.0.0" } } }For hosted reproduction, configure:
(The fixture files above belong at the hosted test repository root, without the local
repro/wrapper.)Offline reproduction
Save this next to the local
repro/directory asreproduce.rb:Run from their parent directory:
Observed output:
{"dealias_packages":false,"dependencies":[{"name":"is-number-alias","version":"7.0.0","top_level":false},{"name":"packages/local","version":"1.0.0","top_level":false}]} {"dealias_packages":true,"dependencies":[{"name":"is-number","version":"7.0.0","top_level":true},{"name":"local-workspace","version":"1.0.0","top_level":false}]}With default parser options, the only two dependencies are
is-number-aliasandpackages/local, both treated as non-top-level dependencies. The alias target is actuallyis-number;packages/localis an entirely local workspace.The internal
dealias_packages: truecontrol resolves the alias but still incorrectly emitslocal-workspaceas a registry dependency. It is not a repository-level workaround, nor does this probe establish alias-update support.Cause and expected behavior
packagesentries include workspace package records as well as installed registry packages.Local workspace records must not become registry-update candidates. Aliases must not query the registry under an unrelated alias key; correct update support must preserve the alias identity and target/range, rather than silently remove update coverage. This is about parser identity, not registry availability or npm lockfile validity.
Related alias history: #1693 and #15847. #15849 addressed a Bun manifest guard; this reproduction is npm lockfile parsing. The internal alias flag was introduced in #15070 for dependency graphing, not as a supported hosted-update switch.
No ignores, direct-only filters, package removals, or lockfile downgrades were applied to hide the errors.