Skip to content

fix(deps): remove @umpirsky/country-list malware; harden provision-keep-client#3905

Open
piotr-roslaniec wants to merge 5 commits into
mainfrom
eng-630/security-fixes
Open

fix(deps): remove @umpirsky/country-list malware; harden provision-keep-client#3905
piotr-roslaniec wants to merge 5 commits into
mainfrom
eng-630/security-fixes

Conversation

@piotr-roslaniec
Copy link
Copy Markdown
Collaborator

@piotr-roslaniec piotr-roslaniec commented Mar 16, 2026

Summary

Three unique-value security fixes that main does not currently have:

  1. Removes @umpirsky/country-list malware from solidity-v1 by upgrading @celo/contractkit 1.0.1 → 10.0.3. Main still ships this package (7 references in solidity-v1/package-lock.json on main as of this PR). The malware classification is supported by GHSA-hj79-42mx-m4gr (severity: critical, CWE-506) and OSV MAL-2022-689; the package is replaced on npm by 0.0.1-security.
  2. First-time security overrides for the provision-keep-client init container. Main has zero overrides on this file; this PR adds 34, covering elliptic, @babel/traverse, axios, async, ws, tar, body-parser, cookie, qs, send, path-to-regexp, serialize-javascript, etc.
  3. Bumps the provision-keep-client Dockerfile runtime so the overrides are honored at build time. The container was pinned to FROM node:11 (npm 6.7.0), which predates the overrides field (npm 8.3+) and cannot read lockfileVersion: 3. Without this bump, the override block from item (2) is silently ignored during npm install and the deployed image keeps legacy versions like tar@4.4.19, ws@3.3.3, async@1.5.2, qs@6.5.5, tough-cookie@2.5.0. Switched to node:20-slim (active LTS, npm 10) and npm ci --omit=dev for a deterministic install from the lockfile; lockfile regenerated under npm 10.

Also adds defense-in-depth overrides to solidity-v1 beyond the two (http-cache-semantics, get-func-name) already on main from #61a58d777.

Context

  • solidity-v1/ is marked legacy and preserved-for-reference (per its README, updated 2026-05-06), but the malware path still resolves in its lockfile and the upgrade is the cleanest fix.
  • provision-keep-client is a Kubernetes init container last touched 2023-02 but presumably still deployed; it had no security override coverage at all, and its Dockerfile was last touched in 2020.

Changes

File Change
solidity-v1/package.json @celo/contractkit 1.0.1 → 10.0.3; add 31 npm overrides; add eslint-plugin-no-only-tests (required for the lint pass); pin js-yaml to ^3.14.0 for eslint 6.x compat
solidity-v1/package-lock.json Regenerated; @umpirsky/country-list no longer resolved
provision-keep-client/package.json Add 34 npm overrides (no prior coverage)
provision-keep-client/package-lock.json Regenerated with overrides under npm 10
provision-keep-client/Dockerfile FROM node:11FROM node:20-slim; RUN npm installRUN npm ci --omit=dev

Verification

Check Status
@umpirsky/country-list references in solidity-v1/package-lock.json 0 (was 7 on main)
npm ci on provision-keep-client/ under Node 20.19 / npm 10.8 clean install, 541 packages
elliptic in provision-keep-client tree 6.6.1 (was 6.5.3)
ws in provision-keep-client tree 8.21.0 (was 3.3.3)
tar in provision-keep-client tree 6.2.1 (was 4.4.19)
cookie / qs / send / path-to-regexp / body-parser / tough-cookie 0.7.2 / 6.15.2 / 0.19.2 / 0.1.13 / 1.20.5 / 4.1.4
elliptic / @babel/traverse / async in solidity-v1 tree 6.6.1 / 7.29.0 / 2.6.4
CI on rebased branch (latest commit) contracts-* PASS; client-* SKIPPED by path filter (no client code touched)

Notes

  • Remaining npm audit warnings on provision-keep-client come from deeper transitive deps inherited from web3@1.2.9 (form-data, request, ethereumjs-* chain). Addressing them requires a web3 major-version upgrade and is out of scope for this PR.
  • Remaining audit warnings in solidity-v1 come from legacy tooling (truffle, ganache, web3.js v1.x) where no upstream fix exists without a major modernization effort. Follow-up tracked separately.
  • The @celo/contractkit v1→v10 jump touches the alfajores deployment path in solidity-v1/truffle-config.js, which is not exercised in CI. The Celo testnet deployment is not part of regular workflows; flagging here so whoever next runs it knows to verify.

Closes: ENG-630

Summary by CodeRabbit

  • Chores
    • Updated Node.js runtime base image to version 20-slim.
    • Upgraded @celo/contractkit dependency from 1.x to 10.x.
    • Implemented explicit version constraints for transitive dependencies across build configuration.
    • Added development-time linting tooling for test validation.

Review Change Stack

@linear
Copy link
Copy Markdown

linear Bot commented Mar 16, 2026

- Upgrade @celo/contractkit 1.0.1 → 10.0.3 (removes @umpirsky/country-list malware)
- Add npm overrides for elliptic >=6.5.7 (GHSA-vjh7-7g9h-fjfh)
- Add npm overrides for @babel/traverse >=7.23.2 (GHSA-8hfj-j24r-ancp)
- Add npm overrides for async >=2.6.4 (CVE-2021-43138)
- Add npm overrides for 30+ other vulnerable transitive dependencies
- Create .npmrc with audit-level=moderate
- Document all fixes in SECURITY-FIXES.md

Verified: elliptic 6.6.1, @babel/traverse 7.29.0, async 2.6.4 installed
Tests: 74 core tests passing, contracts compile successfully

Closes: ENG-630
- Add eslint-plugin-no-only-tests to devDependencies
- Change js-yaml override from ^4.1.0 to ^3.14.0 for eslint 6.x compatibility
- Update package-lock files

This achieves 0 critical/high vulnerabilities per npm audit.
@piotr-roslaniec piotr-roslaniec force-pushed the eng-630/security-fixes branch from ee302e3 to 6c8cd6b Compare May 23, 2026 13:05
The audit-level=moderate setting did not behave as the comment claimed
(it does not suppress critical/high) and the file referenced the
removed SECURITY-FIXES.md. Drop it entirely.
@piotr-roslaniec piotr-roslaniec force-pushed the eng-630/security-fixes branch from 6c8cd6b to 0219b74 Compare May 23, 2026 13:14
@piotr-roslaniec piotr-roslaniec changed the title fix(deps): remediate critical npm security vulnerabilities fix(deps): remove @umpirsky/country-list malware; harden provision-keep-client May 23, 2026
The initcontainer Dockerfile was pinned to `FROM node:11`, which ships
npm 6.7.0. That npm predates the `overrides` field (introduced in npm
8.3.0) and cannot read `lockfileVersion: 3`. As a result, the security
overrides added to package.json were silently ignored at image build
time and a fresh install resolved transitive deps from semver — leaving
legacy versions like tar@4.4.19, ws@3.3.3, async@1.5.2, qs@6.5.5, and
tough-cookie@2.5.0 in the deployed tree.

Bump to `node:20-slim` (active LTS, ships npm 10), switch the install
step to `npm ci --omit=dev` for a deterministic install from the
lockfile, and regenerate the lockfile under npm 10.

After this change the built image consumes the hardened versions
declared in the overrides block (elliptic 6.6.1, ws 8.21.0, tar 6.2.1,
cookie 0.7.2, qs 6.15.2, send 0.19.2, path-to-regexp 0.1.13,
body-parser 1.20.5, tough-cookie 4.1.4, etc.).

Deeper transitive vulnerabilities inherited from web3@1.2.9 (form-data,
request, ethereumjs-* chain) are not addressed here — they require a
web3 major version upgrade and are out of scope for this PR.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 28, 2026

📝 Walkthrough

Walkthrough

This PR updates dependencies and build configurations across two service manifests: modernizing the keep-client container image to Node.js 20-slim with tightened npm installation, and bumping the solidity-v1 contract kit to a major version with explicit transitive dependency pinning in both projects.

Changes

Dependency and Build Configuration Updates

Layer / File(s) Summary
keep-client Docker provisioning and overrides
infrastructure/kube/templates/keep-client/initcontainer/provision-keep-client/Dockerfile, infrastructure/kube/templates/keep-client/initcontainer/provision-keep-client/package.json
Dockerfile base image upgraded from node:11 to node:20-slim with AS runtime stage naming, and npm ci --omit=dev replaces npm install. New overrides block added to package.json to pin transitive dependencies like @babel/traverse, axios, ws, tar, and utilities.
solidity-v1 contract kit and tooling updates
solidity-v1/package.json
@celo/contractkit dependency bumped from ^1.0.1 to ^10.0.3, eslint-plugin-no-only-tests added to devDependencies at ^3.3.0, and overrides section expanded with pinned versions for multiple transitive dependencies including babel, signing libraries, and utility packages.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 Hop along to node twenty we go,
Dockerfile's slimmer, let dependencies flow!
Overrides pinned, contractkit's up high,
Build tools refreshed as we test and comply! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title directly describes the main changes: removing a malware dependency and hardening the provision-keep-client component, which aligns with the changeset's primary objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch eng-630/security-fixes

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
infrastructure/kube/templates/keep-client/initcontainer/provision-keep-client/Dockerfile (1)

1-19: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Run this init container as a non-root user.

Line 1 upgrades the base image, but the file never sets USER, so the process runs as root by default. That leaves unnecessary privilege in this security-hardening PR.

Suggested hardening diff
 FROM node:20-slim AS runtime
 
 WORKDIR /tmp
 
 COPY ./package.json /tmp/package.json
 COPY ./package-lock.json /tmp/package-lock.json
 
 RUN npm ci --omit=dev
 
 COPY ./TokenStaking.json /tmp/TokenStaking.json
 COPY ./KeepToken.json /tmp/KeepToken.json
 COPY ./KeepRandomBeaconService.json /tmp/KeepRandomBeaconService.json
 COPY ./KeepRandomBeaconOperator.json /tmp/KeepRandomBeaconOperator.json
 
 COPY ./keep-client-config-template.toml /tmp/keep-client-config-template.toml
 
 COPY ./provision-keep-client.js /tmp/provision-keep-client.js
+
+RUN chown -R node:node /tmp
+USER node
 
 ENTRYPOINT ["node", "./provision-keep-client.js"]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@infrastructure/kube/templates/keep-client/initcontainer/provision-keep-client/Dockerfile`
around lines 1 - 19, The Dockerfile runs the provisioning script as root because
no USER is set; update the Dockerfile to create or use a non-root user (e.g.,
the existing node user in the node:20-slim image or a custom user), ensure
WORKDIR /tmp and all copied files (TokenStaking.json, KeepToken.json,
KeepRandomBeaconService.json, KeepRandomBeaconOperator.json,
keep-client-config-template.toml, provision-keep-client.js) are owned by that
non-root user (chown or copy into a user-owned directory) and then add a USER
instruction before the ENTRYPOINT so ENTRYPOINT ["node",
"./provision-keep-client.js"] runs without root privileges.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In
`@infrastructure/kube/templates/keep-client/initcontainer/provision-keep-client/Dockerfile`:
- Around line 1-19: The Dockerfile runs the provisioning script as root because
no USER is set; update the Dockerfile to create or use a non-root user (e.g.,
the existing node user in the node:20-slim image or a custom user), ensure
WORKDIR /tmp and all copied files (TokenStaking.json, KeepToken.json,
KeepRandomBeaconService.json, KeepRandomBeaconOperator.json,
keep-client-config-template.toml, provision-keep-client.js) are owned by that
non-root user (chown or copy into a user-owned directory) and then add a USER
instruction before the ENTRYPOINT so ENTRYPOINT ["node",
"./provision-keep-client.js"] runs without root privileges.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 46e780c8-a999-47f5-bec7-9047add44b00

📥 Commits

Reviewing files that changed from the base of the PR and between 980587b and b7a9f86.

⛔ Files ignored due to path filters (2)
  • infrastructure/kube/templates/keep-client/initcontainer/provision-keep-client/package-lock.json is excluded by !**/package-lock.json
  • solidity-v1/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • infrastructure/kube/templates/keep-client/initcontainer/provision-keep-client/Dockerfile
  • infrastructure/kube/templates/keep-client/initcontainer/provision-keep-client/package.json
  • solidity-v1/package.json

@lrsaturnino
Copy link
Copy Markdown
Member

Heads-up for whoever ships this: the initcontainer image at gcr.io/keep-dev-fe24/initcontainer-provision-keep-client-ethereum is not built by CI, so the new Dockerfile only takes effect after a manual docker build + push of the image after merge.

Copy link
Copy Markdown
Member

@lrsaturnino lrsaturnino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

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.

2 participants