Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Feeling the heat from Malicious Packages? Cool ...

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for Leif Leif
June 10, 2026
19

Feeling the heat from Malicious Packages? Cool off with Cooldowns

We’ve seen a surge in attacks that compromise third-party packages, resulting in costly and disruptive incident response for engineering and security teams.

The good news is that detection is getting faster. Many malicious package versions are identified and removed from public registries within hours or days of being published.

If you avoid installing recently released versions, you can dramatically reduce your exposure to these attacks. In response, package managers are introducing cooldowns—simple controls that delay adopting new releases long enough for malicious versions to be caught and removed.

In this talk, I'll share how we rolled out dependency cooldowns across multiple package managers at Semgrep. I’ll provide concrete examples and takeaways you can use to protect your organization without disrupting development workflows.

Avatar for Leif

Leif

June 10, 2026

Transcript

  1. © 2025, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. SEC205-S Leif Dreizler Feeling the heat from Malicious Packages? Cool off with Cooldowns he/him AppSec Engineer Semgrep
  2. 2 Third-party package attacks are heating up 2025 Aug 2025

    Sep 2026 Mar 2026 Mar Nx Shai-Hulud LiteLLM Axios 2025 Sep Chalk/Debug 2026 May TanStack 2025 Nov Sha1-Hulud 2.0 Thursday Miasma
  3. 3 Shai-Hulud changed everything Shai-Hulud - September 2025 • First

    self-replicating worm on the npm registry • 200+ packages and 500+ versions compromised over 3 days • Harvested npm, GitHub, AWS, and GCP credentials, used those to auto-publish backdoored versions • Made private repos public Sha1Hulud: The Second Coming - November 2025 • Roughly 800 packages, 1000+ versions compromised over the course of a day https://www.reversinglabs.com/blog/shai-hulud-worm-npm https://securitylabs.datadoghq.com/articles/shai-hulud-2.0-npm-worm/
  4. 5 Incident Approx. Window of Opportunity Year xz-utils 5 weeks

    2024 polyfill.io 4 months 2024 tj-actions 1 day 2025 Nx (s1ngularity) 4 hours 2025 Chalk + debug 2 hours 2025 Shai-Hulud 1 day 2025 Sha1-Hulud 2.0 3 days 2025 LiteLLM 40 minutes 2026 axios 3 hours 2026 TanStack 30 minutes 2026
  5. 6 Reference links • xz-utils: https://research.swtch.com/xz-timeline • Polyfill: https://blog.qualys.com/vulnerabilities-threat-research/2024/06/28/polyfill-io-supply-chain-attack#polyfill-io-ti meline

    • tj-actions: https://www.stepsecurity.io/blog/harden-runner-detection-tj-actions-changed-files-action-is-compromised • nx: https://socket.dev/blog/nx-packages-compromised • Chalk + debug: https://www.wiz.io/blog/widespread-npm-supply-chain-attack-breaking-down-impact-scope-across-debug-chalk • Shai-Hulud Sept 25 https://www.reversinglabs.com/blog/new-shai-hulud-worm-spreads-what-to-know • Shai-Hulud 2 Nov 25 https://www.wiz.io/blog/shai-hulud-20-ongoing-supply-chain-attack • LiteLLM https://docs.litellm.ai/blog/security-update-march-2026 • Axios: https://www.stepsecurity.io/blog/axios-compromised-on-npm-malicious-versions-drop-remote-access-trojan • TanStack: https://tanstack.com/blog/npm-supply-chain-compromise-postmortem https://daniakash.com/posts/simplest-supply-chain-defense/
  6. Without a cooldown 🙁 Example: • Your project uses [email protected]

    • 1.80.2 - safe, released 5 weeks ago 9 # pyproject.toml dependencies = [ “litellm#=1.80,<2” ] $ uv lock #-upgrade Updated litellm v1.80.2 #> v1.80.8 😈 • 1.80.6 - safe, released 3 weeks ago ✅ • 1.80.8 - malicious, released yesterday 😈
  7. With a cooldown 😁 Example: • Your project uses [email protected]

    • 1.80.2 - safe, released 5 weeks ago • 1.80.6 - safe, released 3 weeks ago ✅ • 1.80.8 - malicious, released yesterday 😈 10 # pyproject.toml dependencies = [ “litellm#=1.80,<2” ] [tool.uv] exclude-newer = "7 days" $ uv lock #-upgrade Updated litellm v1.80.2 #> v1.80.6 ✅
  8. 11

  9. 13 How I rolled out cooldowns at Semgrep 1. Wrote

    Semgrep rules to find uv and yarn configs without cooldowns 2. Updated a few configs using Claude and put up PRs 3. Asked Claude to create a /uv-cooldown command based on what we had learned 4. Ran the slash command in a bunch of repos in parallel and opened PRs 5. Used another slash command to get PRs into a mergeable state using /loop to respond to test failures, linter errors, PR comments from other bots, etc.
  10. 1 Step 1 /uv-cooldown 1 2 3 4 5 6

    Find all pyproject.toml files that use uv [tool.uv] modify [tool.poetry] skip https://gist.github.com/leifdreizler/eef30e758fc6b76627b956063d62bcc9
  11. 2 Step 2 /uv-cooldown 1 2 3 4 5 6

    Add cooldown settings to each pyproject.toml [tool.uv] exclude-newer = "1 week" required-version = "#=0.10.0" https://gist.github.com/leifdreizler/eef30e758fc6b76627b956063d62bcc9
  12. 3 Step 3 /uv-cooldown 1 2 3 4 5 6

    Exempt internal/private packages • Published by the Semgrep • Installed from private indexes or git repos • buf.build / internal protobuf packages [tool.uv.exclude-newer-package] my-internal-pkg = false https://gist.github.com/leifdreizler/eef30e758fc6b76627b956063d62bcc9
  13. 4 Step 4 /uv-cooldown 1 2 3 4 5 6

    Check for other uv version references Dockerfiles ghcr.io/astral-sh/uv:* image tags CI workflows astral-sh/setup-uv pre-commit astral-sh/uv-pre-commit → bump anything below 0.10.0 to 0.10.12 https://gist.github.com/leifdreizler/eef30e758fc6b76627b956063d62bcc9
  14. 5 Step 5 /uv-cooldown 1 2 3 4 5 6

    Update lock files and prevent downgrades $ uv lock # any downgrades? check git diff *.lock [tool.uv.exclude-newer-package] ty = "2026-03-26T16:28:00Z" Use a timestamp after the LAST artifact upload - not the first, round up to the nearest minute https://gist.github.com/leifdreizler/eef30e758fc6b76627b956063d62bcc9
  15. 6 Step 6 /uv-cooldown 1 2 3 4 5 6

    Summary • Which pyproject.toml files were modified • Which internal packages were exempted, and why • Version bumps made Dockerfiles, CI, pre-commit) • Any files skipped, and why (e.g. uses poetry) https://gist.github.com/leifdreizler/eef30e758fc6b76627b956063d62bcc9
  16. 22 CLAUDE.md ### Package Manager Cooldowns When creating any new

    package manager manifest or lockfile, always add a 1-week cooldown where supported to guard against newly-published malicious packages. | Tool | File | Setting | |------|------|---------| | uv | `pyproject.toml` or `uv.toml` | `exclude-newer = "1 week"` under `[tool.uv]` | | Yarn | `yarnrc.yml` | `npmMinimalAgeGate: 1w` | | npm | `.npmrc` | `min-release-age=7` | | pnpm | `pnpm-workspace.yaml` | `minimumReleaseAge: 10080` (7 days in minutes) |
  17. 23 Global environment variables # ~/.zshrc export UV_EXCLUDE_NEWER="7 days" export

    pnpm_config_minimumReleaseAge=10080 https://pnpm.io/settings#minimumreleaseage https://docs.astral.sh/uv/reference/environment/#uv_exclude
  18. 24 Final Tips • Do some migrations yourself to learn

    about your companyʼs package managers • Understand minimum version required for the cooldown • Rolling things out in batches helps limit problems • Try to fix minor things as you go • Add cooldowns to repository templates • Add cooldown guidance to org-wide CLAUDE.md • Cooldowns are a guideline, they have built-in exception mechanisms. Use them!