Skip to main content

TanStack Got Compromised โ€” What It Means for Your npm Dependencies ๐Ÿ”’

ยท 7 min read
Gergely Sipos
Frontend Architect

TanStack packages โ€” @tanstack/query, @tanstack/router, @tanstack/table โ€” collectively pull tens of millions of weekly downloads. They sit deep in dependency trees across a huge number of production apps. In early 2026, an attacker obtained an npm publish token from TanStack's CI pipeline and used it to push malicious versions of several packages. Obfuscated postinstall hooks phoned home to attacker infrastructure. The window was short โ€” hours โ€” but hours is a lot of npm install runs.

This isn't a new pattern. The same playbook worked against lottie-player in 2025 and ua-parser-js in 2021. What changes each time is the name on the package and the number of people scrambling. This post walks through what happened, why the pattern keeps repeating, and what you can do about it today.

What Happenedโ€‹

The short version: an attacker compromised an npm automation token used in TanStack's GitHub Actions CI/CD pipeline. With that token, they published malicious versions of @tanstack/config, @tanstack/query, @tanstack/router, @tanstack/table, and other packages in the TanStack org.

The malicious versions contained obfuscated code in postinstall hooks โ€” scripts that run automatically after npm install. The code called out to attacker-controlled infrastructure. The community noticed unexpected version bumps within hours. The TanStack team responded quickly: revoked the token, unpublished the malicious versions, republished clean releases, and published a detailed postmortem.

One detail is worth highlighting: automation tokens exist specifically to bypass 2FA. That's their purpose โ€” you can't enter a TOTP code in a CI pipeline. It's also their risk. If the token leaks, an attacker can publish as the package owner without any second factor. The token is the keys.

The TanStack team's postmortem is thorough and worth reading in full: TanStack npm Supply Chain Compromise Postmortem.

Why This Keeps Happeningโ€‹

The CI/CD token compromise is becoming the dominant supply chain attack vector in the npm ecosystem. It works because the security model has an inherent tension: automation tokens must bypass interactive authentication, but that bypass is exactly what makes them valuable to attackers.

This is the same vector that hit lottie-player in October 2025 โ€” a compromised publish token, malicious versions pushed, users affected before anyone noticed. Months apart, same playbook, same result.

Other npm supply chain attacks have used different mechanics to reach the same outcome:

  • ua-parser-js (2021) โ€” the maintainer's npm account was taken over directly. Different entry point, same result: malicious code in a trusted package.
  • event-stream (2018) โ€” a new maintainer was social-engineered into the project and added a malicious dependency. No credential theft at all โ€” just trust.

The common thread isn't a single vulnerability. It's that npm's publishing model is optimized for low friction, and any credential or trust relationship that can be compromised gives an attacker the ability to push code to millions of machines.

The other factor is the window of exposure. Even "hours" is enough. CI pipelines run around the clock. Developers run npm install on new projects. Lock files get regenerated. A malicious version published at 2 AM UTC can land in production builds before anyone in the maintainer's timezone wakes up.

For a deeper look at the full taxonomy of npm supply chain attack vectors, see npm Supply Chain Attacks in our docs.

What You Can Do Right Nowโ€‹

These are the most relevant actions for this specific class of attack โ€” CI/CD token compromise leading to malicious package versions.

  1. Check if you installed a malicious version. If you use any TanStack packages, verify your lock file. Run:

    npm ls @tanstack/query @tanstack/router @tanstack/table

    Compare the installed versions against the known-good versions listed in the TanStack postmortem. If you find a malicious version, delete node_modules, revert your lock file to a known-good commit, and reinstall.

  2. Use npm ci in CI, always. The npm ci command installs exactly what your lock file specifies, nothing more. If your lock file pins @tanstack/query@5.62.0 and an attacker publishes 5.62.1, npm ci won't pick it up. npm install might, depending on your version ranges. This single practice blocks most "surprise version" attacks.

  3. Disable install scripts. This attack used postinstall hooks โ€” scripts that run automatically during npm install. You can disable them globally:

    .npmrc
    ignore-scripts=true

    Most packages work without install scripts. Test your build after enabling this to identify any that need them. See Ignore Install Scripts in our docs.

  4. Audit your own npm publish tokens. If you maintain packages, treat your automation tokens like production database credentials:

    • Use granular access tokens scoped to specific packages
    • Set short expiry windows โ€” 90 days or less
    • Rotate them on a schedule, not just after incidents
    • Store them in your CI platform's secret management, never in repository files
    caution

    Automation and publish tokens bypass 2FA by design. A leaked token gives an attacker full publish access to every package the token covers. Scope them as narrowly as possible and rotate them aggressively.

  5. Set a minimum release age policy. Both npm 11+ and pnpm support quarantine windows that refuse to install any version published less than a configured duration ago.

    tip

    A minimum release age of 3โ€“7 days would have blocked every version published during the TanStack incident. The malicious versions were unpublished within hours.

    npm (v11+) โ€” add to .npmrc:

    .npmrc
    min-release-age=7

    pnpm โ€” add to package.json:

    package.json
    {
    "pnpm": {
    "minimumReleaseAge": "3d"
    }
    }
  6. Run behavioral analysis tools. npm audit checks against the npm advisory database โ€” but advisories are published after an incident is discovered and reported. During the active attack window, npm audit would have shown nothing. Tools like Socket.dev analyze actual package behavior โ€” network calls, filesystem access, obfuscated code โ€” and can flag malicious versions before an advisory exists.

For the full checklist of npm security practices, see the npm Security Checklist in our docs.

The Bigger Pictureโ€‹

The npm trust model was designed for a world where publishing speed mattered more than publishing safety. That was a reasonable trade-off when the ecosystem was small. It is a less reasonable trade-off when npm install runs on millions of machines daily and a single publish token can push code to all of them.

The most promising structural fix is npm provenance. Built on Sigstore, provenance ties a published package version to a specific source commit and build workflow. If a version has a valid provenance attestation, you can verify it was built from the source you can inspect โ€” not from an attacker's laptop using a stolen token. Provenance doesn't prevent all attacks, but it makes token-only compromises verifiable after the fact and detectable during install.

No single tool or practice solves supply chain security. Defense is layers: lock files and npm ci prevent surprise upgrades, token hygiene reduces the attack surface, behavioral scanning catches what advisory databases haven't cataloged yet, and provenance links published artifacts back to source. Each layer catches what the others miss.

TanStack's response to this incident was fast and transparent. The postmortem names what went wrong, how the team responded, and what they changed. That kind of transparency makes the entire ecosystem more resilient. It's worth reading in full.