On 15 April 2022, GitHub disclosed that its npm and GitHub Actions infrastructure had been hit by a campaign the company traced to stolen OAuth tokens — not stolen from GitHub, but from its own enterprise vendors: Heroku and Travis CI, whose maintained OAuth integration applications held standing access to GitHub organisations. The attacker had compromised Heroku’s environment weeks earlier (late March / early April, with Travis CI’s matching compromise surfaced alongside), exfiltrated the OAuth tokens for GitHub’s own first-party integration apps, and then used those mother-keys to pivot into npm’s infrastructure — where, GitHub later confirmed in a painstaking multi-part postmortem, they accessed npm’s integration tokens and, critically, downloaded private customer manifest-tokens plus metadata for every public package, and tampered with three npm packages (including one used internally). For the ecosystem that had spent 2021 internalising supply-chain trauma from SolarWinds, Codecov, and ua-parser-js, this was the darkest-timeline rerun: the trust graph itself — vendor OAuth apps with org-wide standing scopes — became the intrusion vector, and the custodians of the world’s largest package registry were the ones reminding everyone that third-party integration tokens are production secrets with infinite blast radius. The response became a template: GitHub revoked the integration tokens, rotated npm credentials, forced-rotated affected customer tokens, published a rolling four-part disclosure with an engineering-grade timeline, and the industry moved integration-app token hygiene permanently up the hardening checklist.
April 2022 campaign: attackers compromised Heroku (late March) and Travis CI, extracting OAuth tokens for GitHub’s first-party integration apps (Heroku Dashboard, Travis CI apps with org access). Because these apps were trusted by thousands of GitHub orgs, the stolen tokens bypassed the orgs’ own secret hygiene entirely — GitHub’s own npm org among them. attacker used the tokens to access npm infrastructure: downloaded all private npm manifest-tokens (~109,000) + all public-package tarball metadata, and used the access to tamper with three npm packages (incl. an internal one). No evidence of package-registry tampering beyond those; no customer passwords/SSH keys/PMs affected (npm did force-rotate the exposed tokens and advised rotating any secrets that lived inside package manifests). Disclosure: GitHub blog 2022-04-15 (“Incident report” series) + detailed npm postmortems. Reform fallout: GitHub moved npm integration tokens to a new vaulting design, restricted Heroku/Travis app scopes, forced expiration/rotation for legacy integration tokens, and the ecosystem absorbed the lesson: vendor OAuth integration apps are standing org-wide credentials — inventory them, scope them, rotate them.
What happened
The intrusion began upstream of GitHub entirely. In late March 2022, an attacker compromised Heroku’s infrastructure and gained access to the OAuth tokens belonging to GitHub’s Heroku integration app — a first-party application that thousands of organisations had authorised with repository and organisation-level scopes. With Travis CI’s integration similarly compromised (anywhere between late March and early April), the attacker held tokens that GitHub’s permission model rightfully trusted: from GitHub’s perspective, the requests looked like the vendor’s official app acting within its granted scopes, because that is precisely what they were.
The pivot target was npm. Using the stolen Heroku app tokens against GitHub’s own organisations, the attacker reached npm’s private infrastructure including its integration tooling, and by 12 April had used npm’s own integration tokens to access a mirror environment holding the registry’s databases. There they downloaded private npm manifest-tokens — authentication material embedded in package manifests used for publishing workflows — for roughly 109,000 packages, plus metadata (tarballs’ worth for public packages) enabling offline analysis. Three packages were tampered with before detection; one was an internal npm package.
GitHub’s disclosure rhythm defined the incident’s public shape: 15 April announcement (token revocations, investigation ongoing), then steadily deepening postmortems through May that enumerated exactly what was taken — the sequence, the token classes, the three packages, and the remediation state. The company rotated npm’s internal secrets, revoked the compromised integration tokens org-wide, designed new vaulting for integration tokens, and notified affected package maintainers whose private manifest-tokens required rotation.
The trust-graph attack
April 2022 OAuth campaign kill-chain:
T1 - VENDOR COMPROMISE
attacker -> Heroku infra
(late March 2022)
-> exfiltrates OAuth tokens of
GitHub's Heroku integration
app
parallel: Travis CI app tokens
also compromised
T2 - FIRST-PARTY APP AUTHORITY
tokens belong to a GitHub
TRUSTED app
org permissions granted by every
org that ever authorized the app
-> requests look legitimate to
GitHub's audit surface
T3 - PIVOT TO NPM
attacker uses vendor-app tokens
against GitHub's own orgs
-> access npm integration tooling
-> steal npm's own integration
tokens
T4 - REGISTRY ACCESS
2022-04-12: token access to npm
mirror environment with registry
databases
-> download ~109,000 private
manifest-tokens (publishing
credentials inside package
manifests)
-> download all public tarballs'
metadata
T5 - TAMPERING + DETECTION
three npm packages modified
(incl one internal)
GitHub detects, revokes token
chain, halts, discloses
(2022-04-15+)
POST-RESPONSE
npm tokens force-rotated
integration tokens moved to
vaulted design
maintainers advised: assume any
secret inside a package manifest
is burned
Impact and numbers
| Metric | Value |
|---|---|
| Initial compromise | Heroku infrastructure, late March 2022 (Travis CI parallel) |
| Stolen from vendors | OAuth tokens for GitHub first-party Heroku/Travis integration apps |
| Registry pivot | GitHub’s npm orgs breached via vendor-app tokens; npm integration tokens stolen |
| Data accessed | ~109,000 private npm manifest-tokens; public package metadata/tarballs |
| Packages tampered | 3 (incl. 1 internal npm package) |
| Customer impact | No passwords/SSH keys/payment data; manifest-token rotation burden on maintainers |
| Disclosure | GitHub blog 2022-04-15 + multi-part npm postmortem series (April–May) |
Timeline
| Date | Event |
|---|---|
| 2022-03 late | Attacker compromises Heroku; GitHub-integration OAuth tokens exfiltrated (Travis CI similarly) |
| 2022-04-12 | Using stolen tokens, attacker accesses npm mirror environment; downloads manifest-tokens and metadata |
| 2022-04-15 | GitHub discloses campaign, revokes compromised integration tokens, investigation public |
| 2022-04→05 | Rolling postmortems quantify exposure (~109K tokens, 3 packages); npm credentials rotated; customer token rotations pushed |
| 2022 onward | Integration-token vaulting redesign; vendor-app scope restrictions; ecosystem-wide OAuth-app audits become standard practice |
Why it still matters in 2026
Because it proved the hardest supply-chain lesson twice over: you are not just responsible for your secrets — you are responsible for the secrets held about you. Every OAuth integration app ever authorised by your organisation is a standing credential living on someone else’s infrastructure, with scopes your security team hasn’t re-read since the authorisation click; when that vendor is breached, your exposure is exactly as large as that app’s scopes — nothing less. The 2022 event made this concrete at maximum stakes — the custodians of the JavaScript ecosystem itself were popped through a CI vendor’s token stash — and the remediation became the reference architecture: inventory every third-party integration app as a privileged service account, expire and rotate their tokens on a schedule, scope them down from org-wide standing access, and treat vendor-side compromise as a threat model row, not a disclaimer. Four years later, this is exactly the playbook invoked against the OAuth-app audit findings of 2024–2025 (the Snowflake-customer campaign’s core lesson — inventory standing non-human credentials — is the same doctrine), by regulators now writing third-party dependency rules (EU CRA, NIS2 vendor-oversight clauses) in the SPDX/SBOM era. And npm specifically: the manifest-token haul forced the registry to grow up — vaulted integration tokens, publish-credential separation, and transparency about what “metadata” reveals — changes that mattered again in 2025 when npm needed them for the Shai-Hulud-era trust rebuild. The trust graph is infrastructure; April 2022 was the year’s clearest demonstration that attackers had learned to climb it faster than defenders were auditing it.
Detection and hardening takeaways
- Inventory OAuth apps as privileged accounts. Maintain a live registry of every third-party integration app authorised against your orgs, its scopes, and the last review date; the attacker’s token was “legitimate” in every way except whose hands held it — which audit logs only surface if you’re watching app-identity anomalies, not just user logins.
- Scope, expiry, and rotation for integration tokens. Prefer apps supporting granular scopes and short-lived tokens; schedule rotation; kill org-wide standing access where scoped alternatives exist — the difference between “vendor breach touches one repo” and “vendor breach touches everything” is decided at authorisation time — scopes set the blast radius.
- Secrets don’t belong in package manifests. npm’s manifest-tokens were collateral precisely because publishing workflows embedded credentials in files an intruder could bulk-download; modern publish pipelines use short-lived OIDC-bound or vaulted tokens that are worthless as exfiltrate-and-replay targets.
- Alert on app-identity anomalies. GitHub’s detection surface eventually showed the vendor-app tokens acting against unusual orgs; telemetry keyed on which app is exercising which grants from where converts a silent vendor pivot into a pageable event.
- Rehearse multi-party disclosure. GitHub+Heroku+Travis+npm coordination produced admirably precise disclosures; organisations with integration-heavy platforms now pre-negotiate disclosure timelines and telemetry-sharing with their own vendor mesh, because the 2022 campaign showed the incident report is co-authored whether you planned it or not.
FAQ
Were my packages compromised?
Almost certainly not by tampering — only three packages were modified, and GitHub published their names and remediation state in the postmortem series. But if you published to npm before April 2022, your package’s manifest-token (the publishing credential inside the manifest) was likely among the ~109,000 downloaded, which is why npm forced rotation and why any long-lived secret baked into a package file — manifest or otherwise — had to be considered burned and rotated.
Why couldn’t GitHub just revoke everything immediately?
Because the tokens weren’t GitHub’s secrets to revoke cleanly — they belonged to integration apps whose legitimate use was woven into thousands of customers’ CI/CD pipelines. Revocation meant breaking builds globally while attackers still held valid tokens if the revocation lagged; the choreography (revoke, rotate, notify, vault) took weeks of staged work, and that latency is itself the lesson: standing third-party credentials cannot be emergency-evicted, so they must be pre-engineered for eviction.
How is this different from SolarWinds?
Mechanism, not magnitude of ambition. SolarWinds: a build-system compromise inserted malicious code into signed updates shipped to customers — the product itself weaponised. npm/Heroku: stolen OAuth tokens abused to read registries and tamper with three packages — the trust graph abused rather than the build pipeline. Both taught the same meta-lesson the industry keeps re-learning: the most valuable attack surface in modern software is the implicit trust between platforms, vendors, and the credentials that bind them, and defending it requires auditing relationships, not just artifacts.
