After you remove a bad package version from your dependency file, what is still compromised is everything that already touched it: artifacts built during the window, caches that stored it, secrets the build could read, and machines that installed it. A clean manifest does not clean any of those.
The myth
Myth: we pinned the safe version and merged, so we are done. Fact: the merge changes future builds. It does nothing for past ones. The registry removing the package does not delete copies already downloaded.
What can still be tainted
| Item | Why it persists | Fix |
|---|---|---|
| Released artifacts and images | Built before the fix | Rebuild from a clean state and redeploy |
| CI caches | Restored files are not signed or verified | Delete the caches |
| Package proxy or mirror | May still serve the bad version | Block or purge it |
| Secrets in the job | Already readable by the malware | Rotate |
| Developer machines | node_modules and global installs | Reinstall from a clean lockfile |
| Workflow and config files | Malware may have edited them | Review recent changes |
GitHub's caching documentation says cache contents are not signed or verified, so restored files can alter code that later runs. That is why caches belong on the list.
Steps
- Pin to a known good version, using an override if the package is a transitive dependency. The npm docs describe overrides in the root package.json.
- Delete CI caches that existed during the window. GitHub removes caches unused for over 7 days, but do not wait for that.
- Purge the bad version from any mirror and add a block rule.
- Rebuild affected artifacts from a clean checkout with a frozen lockfile install, which fails instead of changing the lockfile when they disagree.
- Redeploy by digest and confirm the old digests are gone from running environments.
- Rotate secrets as described in the rotation guide.
For overrides, see pinning a transitive dependency with npm overrides.
How to confirm the cleanup
A cleanup is only finished when you can show it. After the rebuild, list the image digests running in each environment and confirm none of them predate the fix for services that used the bad version. Run a search of lockfiles and SBOMs again and keep the empty result as a record. Then check the proxy log to confirm nobody is still downloading the bad version. If a developer reports the version after you declared the cleanup done, treat it as a gap in the inventory, not as a surprise, and widen the search to the place that person worked.
Quick check
Does the registry removing the package protect me?
Only from new downloads from that registry. Anything you already fetched, cached or built stays.
Do I need to rebuild every image?
Rebuild the ones built during the exposure window, or any whose build you cannot show was clean.
Safeguard's autonomous remediation can open fix pull requests for vulnerable dependencies, and it is off by default with every category on Manual. You can try a free scan at gold.safeguard.sh/scan.
Sources
- GitHub Docs, Caching dependencies to speed up workflows
- npm Docs, package.json overrides
- npm Docs, npm ci
Last reviewed: 19 October 2026.