Incident Response

Heroku and GitHub OAuth Token Theft: The Early Warning Signs

Stolen OAuth tokens from Heroku's integration with GitHub gave attackers access to private repositories across dozens of organizations. The breach revealed systemic weaknesses in third-party OAuth integrations.

Michael
Security Analyst
5 min read

In April 2022, GitHub disclosed that attackers had stolen OAuth user tokens issued to two third-party integrators — Heroku and Travis CI — and used them to download private repositories from dozens of organizations. But the attack did not start in April. The initial compromise of Heroku's systems likely occurred weeks or months earlier, and the early warning signs were there for anyone paying attention.

This post examines the timeline, the technical mechanics, and the lessons for any organization that grants third-party applications access to their code repositories.

The Attack Chain

The attack leveraged a fundamental property of OAuth integrations: when you authorize a third-party application (like Heroku) to access your GitHub account, that application receives a token that can be used to act on your behalf. If the third-party application is compromised, so are all the tokens it holds.

Here is what happened:

  1. Attackers compromised Heroku's internal systems, gaining access to a database containing OAuth tokens for Heroku's GitHub integration
  2. Using these tokens, attackers could authenticate to GitHub's API as the users who had authorized Heroku
  3. Attackers enumerated private repositories accessible to those users and downloaded their contents
  4. In some cases, attackers used the repository contents (which included secrets, credentials, and infrastructure code) to pivot to additional systems

The blast radius was significant. GitHub identified that the attackers downloaded data from approximately 100 organizations, including npm (which is owned by GitHub).

Why OAuth Tokens Are Dangerous

OAuth tokens are bearer tokens — anyone who possesses them can use them. They are designed to delegate access without sharing passwords, which is good for usability but creates a concentrated target for attackers.

When you click "Authorize" on a GitHub OAuth prompt, you are creating a token that:

  • Persists until explicitly revoked
  • May have broad scopes (repo access, org membership, etc.)
  • Is stored by the third-party application, not by GitHub
  • Can be used programmatically without any additional authentication

This means the security of your GitHub data is now dependent on the security of every third-party application you have authorized. Your GitHub account might have excellent security — 2FA, hardware keys, IP restrictions — but if Heroku stores your OAuth token in a database that gets breached, none of that matters.

The npm Compromise

Perhaps the most concerning aspect of this incident was the impact on npm. The attackers used stolen tokens to access npm's private GitHub repositories, which contained AWS access keys. Using these keys, they accessed npm's S3 buckets containing package data.

GitHub's investigation concluded that no packages were modified, but the implication was clear: a compromise of a CI/CD integration could potentially lead to the modification of packages in the world's largest JavaScript package registry.

The supply chain implications are staggering. npm serves billions of downloads per week. A successfully modified package could have affected millions of developers and applications.

Timeline

  • April 12, 2022: GitHub Security identifies unauthorized access to npm's cloud infrastructure
  • April 13, 2022: GitHub discovers stolen OAuth tokens from Heroku and Travis CI
  • April 15, 2022: GitHub notifies Heroku and Travis CI; begins revoking compromised tokens
  • April 16, 2022: GitHub notifies affected organizations
  • April 18, 2022: Heroku revokes all OAuth tokens for its GitHub integration
  • May 2022: Heroku discloses that the breach originated from compromised Heroku database credentials

The gap between the initial compromise and detection highlights a persistent challenge in security: dwell time. Attackers had access to stolen tokens for an unknown period before GitHub's security team detected anomalous API activity.

Lessons for Every Organization

Audit Your OAuth Authorizations

Go to github.com/settings/applications right now and review every authorized application. For each one, ask:

  • Do I still use this application?
  • Does it need the level of access it currently has?
  • Is the company behind this application trustworthy and well-secured?

Revoke anything you do not actively need.

Minimize OAuth Scopes

When authorizing a new application, pay attention to the scopes it requests. An application that only needs to read public repositories should not have repo scope (which grants access to private repositories). Push back on applications that request more access than they need.

Implement Token Monitoring

GitHub provides audit logs for organizations that show when OAuth tokens are used. Monitor these logs for:

  • Unusual access patterns (bulk repository cloning)
  • Access from unexpected IP ranges
  • API calls at unusual times
  • Access to repositories that the integration should not need

Rotate Tokens Regularly

OAuth tokens should be treated like any other credential: rotate them periodically. Many organizations authorize third-party apps once and never revisit the decision. Build a quarterly review process.

Do Not Store Secrets in Repositories

The npm compromise was escalated because AWS credentials were stored in a private repository. Use dedicated secrets management tools (HashiCorp Vault, AWS Secrets Manager, etc.) instead of relying on repository privacy for secret protection.

Segment Your Integrations

Consider using machine accounts or service accounts for third-party integrations rather than personal accounts. This limits the blast radius — if a service account's token is stolen, the attacker only has access to the repositories explicitly granted to that account, not everything the human user can access.

How Safeguard.sh Helps

Safeguard.sh monitors your development pipeline for credential exposure and integration risks. Our platform tracks which third-party services have access to your code repositories, alerts on anomalous access patterns, and helps you maintain an inventory of all OAuth integrations across your organization. When the next third-party breach occurs, Safeguard.sh helps you quickly assess your exposure and take targeted remediation actions.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.