chore(security): apply the Dependabot cooldown to npm installs - #48
chore(security): apply the Dependabot cooldown to npm installs#48devin-ai-integration[bot] wants to merge 1 commit into
Conversation
.github/dependabot.yml sets a 7-day cooldown for every ecosystem, but that binds Dependabot only. The repository had no .npmrc, so a developer's or CI's `npm install` could resolve a version published minutes ago. Add an .npmrc setting `min-release-age=7` to each directory with its own package-lock.json: superset-frontend, superset-frontend/cypress-base, superset-websocket, superset-websocket/utils/client-ws-app and superset-embedded-sdk. npm reads project config only from the directory it runs in, so one file per install path is required. `min-release-age` needs npm >= 11.10.0; superset-frontend and superset-websocket already require npm ^11.13.0, which node 24.16.0 (the version in every .nvmrc) ships. Older npm ignores the key without erroring. Lockfile-pinned versions are unaffected, so `npm ci` is unchanged. docs/ is excluded: it installs with yarn 1.22, which has no equivalent option. The repository root is excluded: .github/workflows/release.yml writes its own root .npmrc during publishing and would clobber it. Generated-by: Devin (https://devin.ai)
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
|
Upstream issue filed: apache#42983 Verified against Note: duplicate of #33 — both address the missing |
|
Confirmed the overlap with #33 — same defect, different coverage. Concrete differences, so whoever picks a winner can do it on facts: Directories with
Other differences:
Suggestion, not a decision: keep #33 (it has the better verification), add |
|
Superseded by #33. Same min-release-age=7 .npmrc change as #33, which is non-draft and also covers docs/ and the docker npm ci fix. Caveat for the human: #48 covers superset-embedded-sdk and superset-websocket/utils/client-ws-app, which #33 misses — graft those two files onto #33 before closing this. The two also disagree on the required npm version (11.10.0 vs 11.13.0); worth checking which is right. Closing in favour of #33. Reviewed together with the other open PRs on this fork; reopen if this was the wrong call. |
SUMMARY
.github/dependabot.ymlsetscooldown: default-days: 7for all six ecosystems. That cooldown binds Dependabot only. There was no.npmrcanywhere in the tree (find . -name .npmrc -not -path "*/node_modules/*"returned nothing), so anynpm install— a developer's, ordocker/docker-frontend.sh:36in dev mode — could resolve a version published minutes earlier.This adds
min-release-age=7in an.npmrcin each directory that has its ownpackage-lock.json:npm reads project config only from the directory it runs in (the sibling of
package.json), so one file per install path is required; a single root file would not apply tosuperset-frontend.min-release-agewas added in npm 11.10.0 (npm/cli#8965).superset-frontend/package.jsonandsuperset-websocket/package.jsonalready requirenpm: ^11.13.0, and every.nvmrcin the repo isv24.16.0, which ships npm 11.13.0 (https://nodejs.org/dist/index.json). Older npm parses the key as an unknown config and ignores it — measured below — so nothing breaks on a stale toolchain.Deliberate exclusions
docs/— installs with yarn 1.22 ("packageManager": "yarn@1.22.22",docs/yarn.lock). Yarn 1 has no equivalent option..github/workflows/release.yml:97doesecho ... > .npmrcin the root during publishing, which would clobber a committed root file. There is no rootpackage.json, so no install happens there..github/actions/*— vendored third-party actions with committeddist/; nothing installs them locally.superset/mcp_service—dependenciesanddevDependenciesare both empty and there is no lockfile.What this does not do
package-lock.jsonare installed as-is, sonpm cibehaviour is identical (measured below). The protection applies when a version is added or changed, which is where a fresh malicious release would enter.min-release-ageis mutually exclusive with npm'sbefore; anyone who needs--beforefor an install must remove or override this key for that run.npm install --min-release-age=0for that command.Dockerfile:70-77bind-mounts onlypackage.jsonandpackage-lock.jsonfor itsnpm ci, andCOPY superset-frontendhappens afterwards, so the image build never sees the new file. No change there either way, sincenpm ciis lockfile-driven.lerna publish from-packageinrelease.yml,npm publish --access publicinsuperset-embedded-sdk/release-if-necessary.js) were not exercised.min-release-ageflattens to abeforevalue used for version resolution, andnpm publish --dry-runwith the key set behaved normally in a scratch package, but a real publish was not run. The embedded-sdk release relies on there being no_authTokenline in an.npmrcfor OIDC trusted publishing; this file adds no auth line.npm outdateddiffs taken from a plainnpm install— shifts by up to a week at this commit and is not comparable across it. Dependabot's own PRs are unaffected, since they were already on the same 7-day cooldown.BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
Not applicable — no UI change.
TESTING INSTRUCTIONS
Local runs, exact commands and output.
1. The key is recognised by npm 11 and ignored by npm 10.
npm i -g --prefix /tmp/npmglobal npm@11gave npm 11.19.0; the system npm is 10.8.2.The ASF header comments parse fine (npm's ini reader treats
#as a comment). Under npm 10.8.2 the same file yieldsmin-release-age = "7"— an unknown config, retained as a string and unused, with no warning or error.2. It actually filters resolution. Scratch package,
min-release-age=3650:Same command with npm 10.8.2 and the same
.npmrcresolveslodash@4.18.1— i.e. the filter is npm-11-only, as documented above.3.
npm ciis unaffected. Scratch package withlodash@4.18.1inpackage-lock.jsonandmin-release-age=3650:In this repo,
npm ci --dry-run --no-audit --no-fundinsuperset-frontendproduces the same package set with and without the new.npmrc—diffof the two logs shows only two reorderedremovelines and the elapsed time (removed 12 packages in 4svs3s).npm ci --dry-runalso succeeds insuperset-websocket,superset-websocket/utils/client-ws-app,superset-frontend/cypress-baseandsuperset-embedded-sdk.4. Lint.
No pre-commit hook matches
.npmrc, so the five staged files exercise only the whitespace/EOF/large-file hooks.pre-commitis not installed in this environment, henceuvx.5. License check — this is the hook that a new dotfile can actually fail:
.rat-excludeslists.nvmrcbut not.npmrc, so each new file carries the ASF header in#comment form, matching.dockerignore. The script's own download of apache-rat 0.16.1 from Maven Central returned HTTP 429 here; the jar was fetched fromarchive.apache.organd placed at/tmp/lib/apache-rat-0.16.1.jarinstead, which is the path the script expects.6. Tests. No test covers
.npmrc; there is nothing to add without asserting on npm's own behaviour. Ran the frontend suite against an unrelated file to confirm the toolchain is intact:Manual verification
ADDITIONAL INFORMATION
Adversarial self-review of the diff. What was checked, and what came back:
.npmrcsuffice? No — npm project config is read from the local prefix only. Hence one file per install path. Checked that a root file would also be destroyed byrelease.yml:97.npm ciin CI or Docker? Tested: no.npm cireinstalled the lockfile version even atmin-release-age=3650, and thesuperset-frontenddry-run package set is byte-identical modulo ordering..nvmrc(allv24.16.0→ npm 11.13.0) and bothenginesblocks (npm: ^11.13.0); confirmed npm 10.8.2 ignores the key..rat-excludesexcludes.nvmrc, not.npmrc. Added ASF headers and ran RAT to confirm.npm config listin a repo directory: the value parses.docker/*.shfornpmrc: onlyrelease.yml(root, excluded) and a comment inembedded-sdk-release.ymlabout deliberately not writing an auth line. Adding a non-auth.npmrcinsuperset-embedded-sdkshould leave OIDC publishing alone, but this is the one path a real release exercises and this PR does not.superset-frontend/test-report.html, an artifact of my own jest run, not part of the diff. Removed; re-ran RAT clean. The diff is five files, 130 added lines, no deletions.ignore-scripts? Out of scope here.npm ci --dry-runinsuperset-frontendreports install scripts pending approval fornx,unrs-resolverand others; restricting them needs an allowlist and belongs in its own change, as the issue notes.AI DISCLOSURE
This change was authored with AI assistance (Devin). The commit message carries a
Generated-by:trailer per the ASF generative tooling guidance.AUTHOR'S NOTE
Link to Devin session: https://app.devin.ai/sessions/4a3cb5aceb3d4d148c943e5c8aa61590
Requested by: @jethac