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

BSides NYC - Feeling the heat from malicious de...

Avatar for Leif Leif
October 17, 2026

BSides NYC - Feeling the heat from malicious dependencies? 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

October 17, 2026

More Decks by Leif

Other Decks in Technology

Transcript

  1. 2 About Me • Raindrop Founding Security Eng • Semgrep

    Eng Manager->AppSec • Segment AppSec->Eng->Eng Manager • Bugcrowd Sales Engineer • Redspin AppSec Consultant
  2. Nx 2025 Aug Chalk/Debug 2025 Sep Shai-Hulud 2025 Sep Sha1-Hulud

    2.0 2025 Nov LiteLLM 2026 Mar Axios 2026 Mar TanStack 2026 May Miasma 2026 Jun Keyv/Cacheable 2026 Aug Third-party package attacks are heating up 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
  4. 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 7
  5. 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/ 8
  6. Without a cooldown 🙁 Example: • Your project uses [email protected]

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

  9. How I rolled out cooldowns at Semgrep (April 2026) 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. https://gist.github.com/leifdreizler/eef30e758fc6b76627b956063d62bcc9 15
  10. 1 1 Step /uv-cooldown 1 2 3 4 Find all

    pyproject.toml files that use uv [tool.uv] modify [tool.poetry] skip 5 6
  11. 2 2 Step /uv-cooldown 1 2 3 4 5 Add

    cooldown settings to each pyproject.toml [tool.uv] exclude-newer = "1 week" required-version = "-=0.11.33 6
  12. Capability Minimum uv Relative cooldowns, e.g. exclude-newer = "1 week"

    0.9.17 Per-package cooldown exemption with false 0.9.25 Better lock-preservation when changing cooldown 0.10.0 Per-index exclude-newer / index-exclude-newer preview 0.11.5
  13. 3 3 Step /uv-cooldown 1 2 Exempt internal/private packages [tool.uv.exclude-newer-package]

    my-internal-pkg = false [[tool.uv.index]] exclude-newer = false # rest of index definition 3 4 5 6
  14. 5 5 Step /uv-cooldown 1 2 3 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.11.33 4 5 6
  15. 6 6 Step /uv-cooldown 1 Summary • Which pyproject.toml files

    were modified • Which packages were exempted, and why • Version bumps made Dockerfiles, CI, pre-commit) • Any files skipped, and why (e.g. uses poetry) 2 3 4 5 6
  16. Scalable rollout of cooldowns at Semgrep (Aug 2026) 1. Create

    a GitHub App with write access to your repos 2. Clone each repo 3. Run tooling to add cooldowns and update your package manager versions. Add a small agentic fix loop. 4. Open a bunch of PRs 25
  17. 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) | 26
  18. Environment variables # ~/.zshrc export UV_EXCLUDE_NEWER="7 days" export pnpm_config_minimumReleaseAge=10080 #

    pre-commit.yml e.g. UV_EXCLUDE_NEWER="1 week" uv tool install pre-commit --with pre-commit-uv https://pnpm.io/settings#minimumreleaseage https://docs.astral.sh/uv/reference/environment/#uv_exclude 27
  19. 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! https://substack.com/@leif 28