On April 15, 2022, GitHub publicly disclosed that stolen OAuth user tokens, originally issued to Heroku and Travis CI, had been used to access private repositories belonging to dozens of organizations. The breach was a sobering demonstration of how third-party integrations create attack paths that organizations often fail to account for in their threat models.
The Full Timeline
The attack unfolded over weeks before detection:
- April 9, 2022: GitHub Security identifies anomalous activity involving GitHub API access using OAuth tokens from Heroku and Travis CI
- April 12, 2022: GitHub discovers unauthorized access to npm's production infrastructure using AWS keys found in downloaded private repositories
- April 13-14, 2022: GitHub notifies Heroku (Salesforce) and Travis CI. Begins systematic analysis of affected OAuth tokens
- April 15, 2022: GitHub publicly discloses the incident. Heroku begins revoking all GitHub integration OAuth tokens
- April 16-18, 2022: GitHub completes token revocation for Heroku Dashboard and Heroku Review Apps OAuth applications
- April 22, 2022: Travis CI revokes all OAuth tokens for its GitHub integration
- May 26, 2022: Heroku discloses that the initial compromise involved a machine account's OAuth token accessing a Heroku database containing customer tokens
The gap between initial compromise and detection — estimated at potentially weeks — highlights the challenge of detecting token abuse when the tokens are used in ways that look superficially legitimate.
Attack Mechanics
The attack followed a pattern that is becoming disturbingly common:
Step 1: Initial Access
Attackers gained access to Heroku's internal infrastructure, likely through a compromised machine account. From there, they accessed a database containing OAuth tokens that Heroku's GitHub integration stored on behalf of its users.
Step 2: Token Harvesting
With database access, the attackers extracted OAuth tokens for users who had connected their GitHub accounts to Heroku. These tokens had the scopes originally granted by each user — in many cases, repo scope, which provides full read/write access to all of the user's repositories, including private ones.
Step 3: Repository Enumeration and Download
Using the stolen tokens, attackers authenticated to GitHub's API as the legitimate users and:
- Listed all repositories accessible to each user
- Identified high-value targets (private repositories with sensitive content)
- Downloaded repository contents using the Git API
Step 4: Lateral Movement
In repository contents, the attackers found additional credentials — AWS access keys, API tokens, database passwords — that enabled access to additional systems. The most significant lateral movement was into npm's AWS infrastructure.
The npm Dimension
The most alarming aspect of this breach was the compromise of npm's infrastructure. Attackers used AWS keys found in npm's private GitHub repositories to access npm's S3 storage.
GitHub's investigation determined:
- Package metadata was accessed (including package manifests that could reveal dependency relationships)
- No packages were modified (the attackers had read access but apparently did not leverage write access)
- npm user credentials were not exposed (password hashes and 2FA tokens were stored separately)
But the hypothetical scenario — attackers modifying popular npm packages to include malicious code — would have constituted one of the largest software supply chain attacks in history. The npm registry serves billions of downloads per week. A compromised package like lodash or express could have affected millions of applications.
Why This Breach Was Different
Most supply chain attacks target the software itself — injecting malware into packages, compromising build systems, or exploiting vulnerabilities. This attack targeted the development infrastructure surrounding software.
The attacker did not need to:
- Find a vulnerability in any application
- Compromise any maintainer's credentials directly
- Bypass any package signing or verification
They simply needed to compromise one third-party integration that had broad access to code repositories. This is a fundamentally different threat model than most organizations plan for.
Organizational Blind Spots
Forgotten Integrations
How many GitHub OAuth integrations does your organization have? Most security teams cannot answer this question confidently. Integrations are typically set up by individual developers or teams, often without security review.
Overprivileged Tokens
When Heroku asks for repo scope, it gets access to every private repository the user can see — not just the ones relevant to Heroku. Most OAuth integrations request more access than they strictly need, and users grant it without scrutiny.
No Token Lifecycle Management
OAuth tokens persist indefinitely unless explicitly revoked. An integration authorized three years ago by a developer who has since left the company still has a valid token. Most organizations never audit or rotate these tokens.
Shared Risk, Unshared Visibility
Your organization's GitHub security posture is only as strong as the weakest third-party integration connected to it. But you have no visibility into Heroku's internal security practices. You cannot audit their token storage, monitor their incident response, or assess their risk.
Concrete Remediation Steps
Immediate Actions
- Audit all GitHub OAuth integrations at
github.com/settings/applicationsfor personal accounts and organization settings for org-level integrations - Revoke unnecessary integrations — if you have not used an integration in 6 months, revoke it
- Rotate all secrets stored in GitHub repositories — even private ones
- Enable GitHub audit log streaming to detect anomalous API access patterns
Structural Changes
- Use GitHub Apps instead of OAuth where possible — GitHub Apps have granular, repository-specific permissions rather than user-wide access
- Implement SAML/SSO for your GitHub organization to centralize access control
- Deploy IP allowlists for API access to limit where tokens can be used from
- Never store secrets in repositories — use proper secrets management (Vault, AWS Secrets Manager, etc.)
How Safeguard.sh Helps
Safeguard.sh monitors your development infrastructure for credential exposure and integration risks. Our platform inventories all third-party integrations connected to your code repositories, tracks their permission scopes, and alerts on anomalous access patterns. When a breach like the Heroku/Travis CI incident is disclosed, Safeguard.sh helps you immediately assess your exposure by identifying which repositories were accessible through compromised integrations and whether any secrets in those repositories need rotation.