feat(enrichment): add overly-broad dependency version-range analyzer - #3241
Conversation
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
|
Warning 🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨 ⏸️ Gittensory review result - manual review recommendedReview updated: 2026-07-04 22:12:34 UTC
⏸️ Suggested Action - Manual Review Review summary Nits — 6 non-blocking
Review context
Contributor next steps
Signal definitions
🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3241 +/- ##
=======================================
Coverage 94.10% 94.10%
=======================================
Files 274 274
Lines 30092 30092
Branches 10985 10985
=======================================
Hits 28319 28319
Misses 1127 1127
Partials 646 646
🚀 New features to boost your workflow:
|
Closes #2036
What
A new local REES analyzer,
looseRange, that flags newly-added/changed npm dependency specifiers using dangerously loose ranges instead of a pinned/caret/tilde range — a reproducibility and supply-chain drift risk, since a loose range lets any future publish (including a compromised one) flow into the next install:*/x: accepts ANY published versionlatestdist-tag: floats to whatever is published next>=x/>xwith no upper bound: accepts every future major, breaking changes included18,18.x): floats across the whole major lineDistinct from the vuln/typosquat analyzers: this judges only the SPECIFIER, never the package. Pure compute over added
package.jsonpatch lines — no registry call, no network.Detection
package.jsonpatches only, with the shared hunk/line-counter conventions from the sibling local analyzers (pre-hunk preamble skipped,+++xadded-content not mistaken for a header,\ No newlinemarkers do not advance the counter, per-line char cap)."name": "spec"line shape asdependency-scan.tsand unwrapsnpm:pkg@rangealiases exactly as it does; like that sibling, parsing is a documented line-based heuristic, not a full manifest parse."section": {state is tracked from added AND context lines (the same current-block state shape aslockfile-drift.ts's package-lock parser) and reset at every hunk boundary so state never leaks across discontinuous hunks. A line is judged ONLY when its enclosing block is a visibledependencies/devDependencies/peerDependencies/optionalDependenciesheader — inside one, every entry is classified with no suppression, so a real dependency literally namednpm,node, orvscodewith a loose range is still flagged. Inside any other visible block (engines,publishConfig,scripts, …) nothing is a dependency, so the legitimate and extremely common"node": ">=18"in engines never fires. When a hunk starts mid-block with no section header in view, the analyzer stays silent rather than guessing — a hunk starting mid-enginesor mid-scriptsmust not report"some-engine": "*"or"releaseTag": "latest"as a dependency, and for an advisory brief a wrong finding costs more than a missed one (the same no-findings-on-uncertainty posture as the sibling analyzers).>=1 <2), non-latestdist-tags, andworkspace:protocol specifiers are never flagged. Findings capped (maxFindings: 20) per file and globally.Registration
Registered as a local descriptor (category
supply-chain, costlocal, requires["files"]) with an inlinerender(), following thetestRatio/migrationSafetydescriptor shape. All wiring updated:types.ts(LooseRangeFinding+looseRange?key),render.ts,analyzer-registry.test.ts, rootsrc/review/enrichment-analyzer-names.ts, roottest/unit/enrichment-wire.test.ts, and the generatedanalyzer-metadata.json/rees-analyzers.ts/.env.examplevianode scripts/generate-analyzer-metadata.mjs.Tests
review-enrichment/test/loose-range.test.ts(15 tests) covers: each loose kind viaclassifyRange(includingx/Xwildcards,>as well as>=, and18.x.x), pinned/caret/tilde/bounded/minor-given/dist-tag/workspace:specifiers not flagged,npm:alias unwrapping, each kind end-to-end with exact file/line locations inside a visible dependencies block, non-range manifest values not flagged, a dependency literally namednpm/node/vscodestill flagged inside a visible dependencies block (the name-collision regression), entries inside a visible engines/publishConfig block never flagged, a hunk with NO visible section header staying completely silent — including"some-engine": "*"and"releaseTag": "latest"shapes (the fail-closed regression), section state reset at hunk boundaries with context-line tracking, removed/context lines ignored for classification, line-number accuracy across mixed hunks, the per-file cap +maxFindings: 0, the entrypoint's package.json-only gating + global cap across files, the no-files case, and the rendered brief section. Analyzer metadata is regenerated and committed.