惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Latest news
Latest news
T
Troy Hunt's Blog
V
Vulnerabilities – Threatpost
L
LINUX DO - 热门话题
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
V
V2EX
博客园 - 司徒正美
B
Blog RSS Feed
AWS News Blog
AWS News Blog
MyScale Blog
MyScale Blog
Scott Helme
Scott Helme
Cisco Talos Blog
Cisco Talos Blog
Last Week in AI
Last Week in AI
NISL@THU
NISL@THU
博客园 - Franky
P
Proofpoint News Feed
博客园_首页
C
CERT Recently Published Vulnerability Notes
雷峰网
雷峰网
S
Schneier on Security
P
Proofpoint News Feed
Hugging Face - Blog
Hugging Face - Blog
G
GRAHAM CLULEY
博客园 - 三生石上(FineUI控件)
月光博客
月光博客
WordPress大学
WordPress大学
The Hacker News
The Hacker News
T
Threatpost
阮一峰的网络日志
阮一峰的网络日志
A
Arctic Wolf
Microsoft Azure Blog
Microsoft Azure Blog
T
The Exploit Database - CXSecurity.com
Engineering at Meta
Engineering at Meta
罗磊的独立博客
T
The Blog of Author Tim Ferriss
D
Darknet – Hacking Tools, Hacker News & Cyber Security
I
Intezer
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
K
Kaspersky official blog
SecWiki News
SecWiki News
云风的 BLOG
云风的 BLOG
美团技术团队
C
Cybersecurity and Infrastructure Security Agency CISA
博客园 - 【当耐特】
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Security Latest
Security Latest
C
Cyber Attacks, Cyber Crime and Cyber Security
B
Blog
S
Security Affairs

Hacker News

Introducing Claude Opus 4.7 Qwen Studio The Future of Everything is Lies, I Guess: Where Do We Go From Here? GitHub - SeanFDZ/macmind: Single-layer transformer in HyperTalk for the classic Macintosh Show HN: Agent-cache – Multi-tier LLM/tool/session caching for Valkey and Redis Bonsai 1-bit WebGPU - a Hugging Face Space by webml-community Moving a large-scale metrics pipeline from StatsD to OpenTelemetry / Prometheus GitHub - Nightmare-Eclipse/RedSun: The Red Sun vulnerability repository GitHub - SethPyle376/hiraeth: Local AWS emulator focused on fast integration testing, with SQS support, SQLite-backed state, and a debug-friendly web UI. GitHub - macOS26/Agent: Any AI, replaces Claude Code, Cursor, OpenClaw. Over 18 LLM providers (Claude, OpenAI, Gemini, Ollama, Zai, HF, Qwen) wired into a native Mac app that writes code, builds Xcode projects, bumps versions, manages git, automates Safari, use AppleScript, JS or Accessibility, extend Agent! w/ MCP Servers, run tasks from your iPhone via Messages. YouTube now lets you turn off Shorts I Made a Terminal Pager Burgers | マクドナルド公式 Commands — HackerNews CLI documentation ChatGPT for Excel PiCore - Raspberry Pi Port of Tiny Core Linux Live Nation illegally monopolized ticketing market, jury finds Google Broke Its Promise to Me. Now ICE Has My Data. Founding Engineer at Adaptional | Y Combinator CRISPR takes important step toward silencing Down syndrome’s extra chromosome GitHub - saffron-health/libretto: The AI toolkit for building reliable browser automations US v. Heppner (S.D.N.Y. 2026) no attorney-client privilege for AI chats [pdf] Retrofitting JIT Compilers into C Interpreters IPv6 – Google The Accursèd Alphabetical Clock Cybersecurity Looks Like Proof of Work Now Fragments: April 14 Cal.com Goes Closed Source: Why AI Security Is Forcing Our Decision | Cal.com - Scheduling Software for Online Bookings Laravel raised money and now injects ads directly into your agent When moving fast, talking is the first thing to break Too much Discussion of the XOR swap trick – Heather Cafe Introduction to Spherical Harmonics for Graphics Programmers The Grand Line Building a Z-Machine in the worst possible language High-Level Rust: Getting 80% of the Benefits with 20% of the Pain GitHub - duguyue100/midnight-captain: Inspired by Midnight Commander, tailored to my taste. How to build a `git diff` driver · Jamie Tanna | Software Engineer Center for Responsible, Decentralized Intelligence at Berkeley The Local Universe’s Expansion Rate Is Clearer Than Ever, but Still Doesn’t Add Up - A new synthesis of astronomical measurements confirms a persistent mismatch that could point to physics beyond current models The air throughout our homes is infused with microplastics. But there are things you can do to breathe less of them The disturbing white paper Red Hat is trying to erase from the internet – OSnews The Future of Everything is Lies, I Guess: Annoyances ‘Abhorrent’: the inside story of the Polymarket gamblers betting millions on war Productive procrastination — Max van IJsselmuiden maps, territory and LMs 447 Terabytes per Square Centimetre at Zero Retention Energy: Non-Volatile Memory at the Atomic Scale on Fluorographane Show HN: Pardonned.com – A searchable database of US Pardons 20 Years on AWS and Never Not My Job The Seasons are Wrong Artemis II crew splashes down near San Diego after historic moon mission We gave an AI a 3 year retail lease in SF and asked it to make a profit | Andon Labs How a dancer with ALS used brainwaves to perform live On filing the corners off my MacBooks Installing every* Firefox extension OpenClaw’s memory is unreliable, and you don’t know when it will break Steve Blank Nowhere Is Safe Chimpanzees in Uganda locked in vicious 'civil war', say researchers watgo - a WebAssembly Toolkit for Go linux/Documentation/process/coding-assistants.rst at master · torvalds/linux GitHub - callumlocke/json-formatter: Makes JSON easy to read. Founding Product Engineer at Bild AI | Y Combinator A compelling title that is cryptic enough to get you to take action on it GitHub - Keychron/Keychron-Keyboards-Hardware-Design: Industrial design files for Keychron keyboards and mice. 100+ models with CAD assets in STEP, DXF, DWG, and PDF. Source-available, with commercial use allowed for original compatible accessories within the license terms. [ANNOUNCE] WireGuardNT v0.11 and WireGuard for Windows v0.6 Released 1D-Chess Helium Is Hard to Replace Cooperative Vectors Introduction | Evolve Keeping a Postgres queue healthy — PlanetScale Our response to the Axios developer tool compromise Do Americans read print books, e-books or audiobooks more? The Zettelkasten Method in Obsidian: A Practical Setup Guide Artemis II Is Competency Porn and We Are Starving For It WeakC4 Flight Viz — Cockpit View A Mexican surveillance giant you’ve never heard of is now watching the U.S. border Surelock: Deadlock-Free Mutexes for Rust RISC-V 101 – what is it and what does it mean for Canonical? | Ubuntu The Problem That Built an Industry How Much Linear Memory Access Is Enough? | Solidean Investigating Split Locks on x86-64 Simplest hash functions Sybilproof reputation mechanisms (2005) [pdf] What is a property? How Complex is my Code? Static code analysis in Kotlin — tools overview Toffoli gates are all you need PGLite evangelism dcmake: a new CMake debugger UI Clojure on Fennel part one: Persistent Data Structures Fragments: April 2 Python Release Python install manager 26.1 The Life and Death of the Book Review - Liberties Introducing Database Traffic Control — PlanetScale Bitcoin miners are losing $19,000 on every BTC produced as difficulty drops 7.8% God sleeps in the minerals Building slogbox Apple Silicon and Virtual Machines: Beating the 2 VM Limit Who was “Not Even Wrong” first? Pokemon Evolution Vs Darwinian Evolution The APL Programming Language Source Code
Postmortem: TanStack npm supply-chain compromise | TanStack Blog
Tanner Linsley · 2026-05-12 · via Hacker News

by Tanner Linsley on May 11, 2026.

Status (2026-05-15): All clear ✅

After a three-day full security sweep and hardening pass, we're issuing an official all-clear on TanStack repo and package security.

  • Only the Router/Start repo was affected — 42 monorepo packages, 2 versions each. All were deprecated within the hour and removed by npm shortly after.
  • All other TanStack repos and packages were unaffected and remain secure: Query, DB, Store, AI, Table, Form, HotKeys, Virtual, Pacer, Config, Devtools, CLI, Intent, etc.
  • Every currently-available published version of every TanStack package — Router and Start included — is safe to install.

See also: Hardening TanStack After the npm Compromise — the companion piece covering what we're changing because of this incident.

Last updated 2026-05-15 — see Changelog.

On 2026-05-11 between 19:20 and 19:26 UTC, an attacker published 84 malicious versions across 42 @tanstack/* npm packages by combining: the pull_request_target "Pwn Request" pattern, GitHub Actions cache poisoning across the fork↔base trust boundary, and runtime memory extraction of an OIDC token from the GitHub Actions runner process. No npm tokens were stolen and the npm publish workflow itself was not compromised.

The malicious versions were detected publicly within 20 to 26 minutes (depending on which of the two publish batches a given version came from) by an external researcher ashishkurmi working for stepsecurity. All affected versions have been deprecated; npm security has been engaged to pull tarballs from the registry. We have no evidence of npm credentials being stolen, but we strongly recommend that anyone who installed an affected version on 2026-05-11 rotate AWS, GCP, Kubernetes, Vault, GitHub, npm, and SSH credentials reachable from the install host.

Tracking issue: TanStack/router#7383 GitHub Security Advisory: GHSA-g7cv-rxg3-hmpx

Packages affected

42 packages, 84 versions (two per package, published roughly 6 minutes apart). See the tracking issue for the full table. Confirmed-clean families: @tanstack/query*, @tanstack/table*, @tanstack/form*, @tanstack/virtual*, @tanstack/store, @tanstack/start (the meta-package, not @tanstack/start-*).

What the malware does

When a developer or CI environment runs npm install, pnpm install, or yarn install against any affected version, npm resolves the malicious optionalDependencies entry, fetches the orphan payload commit from the fork network, runs its prepare lifecycle script, and executes a ~2.3 MB obfuscated router_init.js smuggled into the affected tarball. The script:

  • Harvests credentials from common locations: AWS IMDS / Secrets Manager, GCP metadata, Kubernetes service-account tokens, Vault tokens, ~/.npmrc, GitHub tokens (env, gh CLI, .git-credentials), SSH private keys
  • Exfiltrates over the Session/Oxen messenger file-upload network (filev2.getsession.org, seed{1,2,3}.getsession.org) — end-to-end encrypted with no attacker-controlled C2, so blocking by IP/domain is the only network mitigation
  • Self-propagates: enumerates other packages the victim maintains via registry.npmjs.org/-/v1/search?text=maintainer:<user> and republishes them with the same injection

Because the payload runs as part of npm install's lifecycle, anyone who installed an affected version on 2026-05-11 must treat the install host as potentially compromised.


All times UTC. Local timestamps from GitHub API and npm registry.

Pre-attack (cache poisoning phase)

TimeEvent
2026-05-10 17:16Attacker creates fork github.com/zblgg/configuration (a fork of TanStack/router, deliberately renamed to evade fork-list searches)
23:29Malicious commit 65bf499d16a5e8d25ba95d69ec9790a6dd4a1f14 authored on the fork by fabricated identity claude <claude@users.noreply.github.com>. Adds packages/history/vite_setup.mjs (a ~30,000-line bundled JS payload). Commit message prefixed with [skip ci] to suppress CI on the push event
2026-05-11 ~10:49PR #7378 opened against TanStack/router#main titled "WIP: simplify history build" by zblgg
10:49 onwardsbundle-size.yml and labeler.yml (both pull_request_target) auto-run for the PR — no first-time-contributor approval required because pull_request_target bypasses that gate. pr.yml (which uses pull_request) does NOT run, blocked pending approval that never came
11:01–11:11Multiple force-pushes by zblgg to the PR head, each triggering more pull_request_target runs
11:11Force-push lands 65bf499d (the malicious commit) on the PR head. bundle-size.yml's benchmark-pr job checks out refs/pull/7378/merge, runs pnpm install + pnpm nx run @benchmarks/bundle-size:build — this executes vite_setup.mjs
11:29Cache entry Linux-pnpm-store-6f9233a50def742c09fde54f56553d6b449a535adf87d4083690539f49ae4da11 (1.1 GB) saved to GitHub Actions cache for TanStack/router, scope refs/heads/main — keyed to match what release.yml will look up on the next push to main
11:31Attacker force-pushes the PR back to current main HEAD (b1c061af), making the visible PR a 0-file no-op. PR closed and branch deleted in the same minute. Cache poison persists.

Detonation (publish phase)

TimeEvent
2026-05-11 19:15:44Workflow run 25613093674 (Release) is re-run as attempt #4 against main HEAD b1c061af. Original trigger was PR #7369 (Shkumbin's CSS.supports fix), merged 2026-05-09 22:11:51 UTC. Poisoned cache is restored on the runner.
19:16:18Manuel merges PR #7382 (jiti tsconfig paths fix) → push to main triggers a fresh release.yml run
19:16:22Workflow run 25691781302 starts (attempt #1). Same poisoned cache restored.
19:20:39npm registry receives publish for @tanstack/history@1.161.9 and 41 sibling packages from run 25613093674 (~half of the eventual 84 versions; the remainder come during run #2). Publish is authenticated via OIDC trusted-publisher binding for TanStack/router release.yml@refs/heads/main — but it does not come from the workflow's defined Publish Packages step, which was skipped because tests failed. It comes from the malware running during the test/cleanup phase, which mints an OIDC token via the workflow's id-token: write permission and POSTs directly to registry.npmjs.org
19:20:48Run 25613093674 completes (status: failure)
19:26:14npm registry receives publish for the second-version-per-package set (@tanstack/history@1.161.12 etc.) from run 25691781302. Same OIDC mechanism
19:26:22Run 25691781302 completes (status: failure)

Detection and response

TimeEvent
2026-05-11 19:46External researcher ashishkurmi working for StepSecurity opens issue #7383 with a complete writeup of the malicious optionalDependencies fingerprint and the package list (initially 14 of the 42)
~19:50Researcher notifies npm security directly
~20:00Manuel acknowledges in #7383 — incident response begins
~20:10Manuel removes all other team push permissions on GitHub in case of user machines have been compromised
20:19Tanner deprecates @tanstack/history@1.161.9 and @1.161.12 — the first two versions taken out of circulation
20:41Batch deprecation runs across the initial 14-package / 28-version scope from issue #7383
~21:00Comprehensive scan of all 295 @tanstack/* packages confirms full scope: 42 packages, 84 versions (28 more than the StepSecurity report).

Public Twitter/X/LinkedIn/Bluesky disclosure from @tan_stack and maintainers

21:03Final batch deprecation runs across the remaining versions to cover the full 42-package / 84-version scope
21:30Investigation identifies bundle-size.yml pull_request_target cache-poisoning vector and the zblgg/configuration fork.

All cache entries for all TanStack/* GitHub repositories purged via API.

Hardening PR merged: bundle-size.yml restructured, repository_owner guards added, third-party action refs pinned to SHAs.

Official GitHub Security Advisory is published, CVE requested

22:13–23:55npm removes the affected tarballs registry-side in response to the StepSecurity notification from earlier in the evening — first removal at 22:13:38 (@tanstack/query-core), last at 23:55:26 (@tanstack/router-core)
2026-05-12 05:02Tanner emails security@npmjs.com and GitHub security with full IOC list and a formal request to pull tarballs registry-side.

Formal malware reports are submitted via npm

Response timing

Elapsed time from two reference points: the first malicious publish (19:20 UTC) and the moment the incident became known (StepSecurity issue #7383, 19:46 UTC).

MilestoneFrom publishFrom known
Compromise publicly detected~26 min
First versions deprecated (2 of 84)~59 min~33 min
Initial scope deprecated (28 of 84)~1h 21m~55 min
Full scope deprecated (84 of 84)~1h 43m~1h 17m
First package removed by npm~2h 53m~2h 27m
Last package removed by npm~4h 35m~4h 9m

Three vulnerabilities chained together. Each is necessary for the attack; none alone is sufficient.

1. pull_request_target "Pwn Request" pattern in bundle-size.yml

bundle-size.yml ran pull_request_target for fork PRs and, inside that trigger context, checked out the fork's PR-merge ref and ran a build:

The author of the workflow attempted a trust split (the comment-pr job is separate from benchmark-pr, with a comment in the YAML noting the intent to keep benchmark-pr "untrusted with read-only permissions"). The split is correct in spirit but missed two facts:

  • actions/cache@v5's post-job save is not gated by permissions:. Cache writes use a runner-internal token, not the workflow GITHUB_TOKEN. Setting permissions: contents: read does not block cache mutation.
  • Cache scope is per-repo, shared across pull_request_target runs (which use the base repo's cache scope) and pushes to main. A PR running in the base repo's cache scope can poison entries that production workflows on main will later restore.

2. GitHub Actions cache poisoning across trust boundaries

The malicious vite_setup.mjs was specifically designed to write data into the pnpm-store directory under a key the legit release.yml workflow would compute and look up: Linux-pnpm-store-${hashFiles('**/pnpm-lock.yaml')}. When the benchmark-pr job ended, actions/cache@v5's post-step saved the (now-poisoned) pnpm store to that exact key. When release.yml next ran on a push to main, its Setup Tools step restored the poisoned entry — entirely as designed.

This is the class of attack documented by Adnan Khan in 2024. It's not a TanStack-specific bug; it's a known GitHub Actions design issue that requires conscious mitigation.

release.yml declares id-token: write (legitimately needed for npm OIDC trusted publishing). When the poisoned pnpm store is restored on the runner, attacker-controlled binaries are now on disk and get invoked during the build step. Those binaries:

  • Locate the GitHub Actions Runner.Worker process via /proc/*/cmdline
  • Read /proc/<pid>/maps and /proc/<pid>/mem to dump the worker's memory
  • Extract the OIDC token (which the runner mints lazily, in memory, when id-token: write is set)
  • Use the token to authenticate POST requests directly to registry.npmjs.org — bypassing the workflow's Publish Packages step entirely

This is the same memory-extraction technique (and verbatim Python script, with attribution comment) used in the tj-actions/changed-files compromise of March 2025. The attacker did not invent novel tradecraft; they recombined published research.

Why none alone is enough

  • pull_request_target alone is fine for trusted operations (labeling, comments)
  • Cache poisoning alone (e.g., from inside an already-compromised dep) requires a separate publish vehicle
  • OIDC token extraction alone requires existing code execution on the runner

The chain only works because each vulnerability bridges the trust boundary the others assumed: PR fork code crossing into base-repo cache, base-repo cache crossing into release-workflow runtime, and release-workflow runtime crossing into npm registry write access.


How we found out

Detection was external. External researcher ashishkurmi working for StepSecurity opened issue #7383 ~20 minutes after the publish, with full technical analysis. Tanner received a phone call from Socket.dev just moments after starting the war room confirming the situation.

IOC fingerprints (for downstream maintainers and security tools)

In any @tanstack/* package's manifest:

  • File: router_init.js (~2.3 MB, package root, not in "files")
  • Cache key: Linux-pnpm-store-6f9233a50def742c09fde54f56553d6b449a535adf87d4083690539f49ae4da11
  • 2nd-stage payload URLs: https://litter.catbox.moe/h8nc9u.js, https://litter.catbox.moe/7rrc6l.mjs
  • Exfiltration network: filev2.getsession.org, seed{1,2,3}.getsession.org
  • Forged commit identity: claude <claude@users.noreply.github.com> (note: not the real Anthropic Claude — fabricated GitHub no-reply email)
  • Real attacker accounts: zblgg (id 127806521), voicproducoes (id 269549300)
  • Attacker fork: github.com/zblgg/configuration (fork of TanStack/router renamed to evade fork searches)
  • Orphan payload commit (in fork network): 79ac49eedf774dd4b0cfa308722bc463cfe5885c
  • Workflow runs that performed the malicious publishes:

What went well

  • External researchers noticed and reported with full technical detail within ~20 min of the incident
  • Maintainer team coordinated immediately and effectively across many timezones
  • The detection community already had a clear public IOC pattern within hours

What could have been better

  • No internal alerting. We learned about the compromise from a third party. We need monitoring on our own publishes. We'll be working closely with security researcher firms in the ecosystem that have the ability to detect these issues very quickly, potentially even in-house, and making the feedback loop even tighter.
  • pull_request_target workflows had not been audited despite being a long-known dangerous pattern
  • Floating refs (@v6.0.2, @main) on third-party actions create standing supply-chain risk independent of this incident
  • Unpublish was unavailable for nearly all affected packages because of npm's "no unpublish if dependents exist" policy. We have to rely on npm security to pull tarballs server-side, which adds hours of delay during which malicious tarballs remain installable
  • The 7-maintainer list on the npm scope means seven separate credential-theft targets for the same blast radius
  • OIDC trusted-publisher binding has no per-publish review. Once configured, any code path in the workflow can mint a publish-capable token. We need either (a) move to short-lived classic tokens with manual review, or (b) add provenance-source-verification to detect publishes from unexpected workflow steps

What we got lucky on

  • The attacker chose a payload that broke tests, which made the publish step (which would have produced cleaner-looking tarballs) skip — meaning the attack was loud enough to detect quickly. A more careful attacker who didn't break tests could have published silently for hours longer
  • The attacker reused public tradecraft (verbatim memory-dump script with attribution comment) instead of writing novel code — making the IOC-matching faster

These need answers before we close the postmortem.

  • Did bundle-size.yml's Setup Tools step actually call actions/cache@v5? Verify by reading the post-job logs from one of the pull_request_target runs against PR #7378 (e.g., run id 25666610798). Tanner has access; needs to be done manually
  • What was in the initial PR head commit (before the force-pushes wiped it)? GitHub's reflog may have it. Check via gh api or the GitHub support team
  • How did the malicious commit get into the fork's git object store specifically — was it pushed directly via git, or was it created via the GitHub web UI (which would leave audit-log entries)?
  • Was voicproducoes a real account or a sock puppet? Cross-reference its activity history
  • Did the npm cache also get poisoned (the 6 duplicate linux-npm-store-* entries)? Were any actually used?
  • Can we identify any other fork in the TanStack/router fork network that contains the orphan payload commit? (If yes, the cleanup is harder — every fork hosting it keeps it accessible via github:tanstack/router#79ac49ee...)
  • Are any other TanStack repos (router, query, table, form, virtual, etc.) using the same bundle-size.yml-style pattern? Audit needed
  • How many users actually downloaded the affected versions during the publish window? Get from npm support
  • Did any of the seven listed maintainers' machines get compromised separately? (None of the malicious publishes used a maintainer's npm token, but maintainer machines could have been the secondary target via the self-propagation logic)


See the GitHub Security Advisory for the full list of affected versions: GHSA-g7cv-rxg3-hmpx

  • 2026-05-15 — Refined the timeline with verified timestamps from GitHub, npm registry, and internal shell history. Notable corrections:
    • PR #7369 was merged 2026-05-09 (the 19:15 UTC May 11 event was a re-run of that workflow, not a fresh merge).
    • The StepSecurity issue was opened at 19:46:46 UTC (not ~19:50).
    • Deprecation actually ran in two phases at ~20:19 / ~20:41 / ~21:03 UTC (not a single ~21:00 batch).
    • The npm-side tarball removal window of 22:13–23:55 UTC was reattributed to npm acting on the StepSecurity notification rather than to our later email.
    • The formal IOC email to npm/GitHub Security went out at 05:02 UTC May 12 (not ~20:30 UTC May 11).
    • Added a Response timing summary and an All-clear status banner.