# Dependabot Confusion: Gaining Access to Private GitHub Repositories using Dependabot

Dependabot converted private Git dependencies to public NPM packages, letting attackers publish a same-named package and inject code via a Dependabot PR.

- Payout: $2,500
- Severity: high
- Program: GitHub
- Credited: Giraffe Security
- Disclosed: 2023-05-06
- Write-up quality: 8/10
- Original: https://giraffesecurity.dev/posts/dependabot-confusion/
- Library page: https://bugbountylibrary.com/r/blog%3Agiraffesecurity-dev-posts-dependabot-confusion
- Tags: domain:oss impact:rce kind:bounty platform:blog sev:high tech:ci-cd tech:nodejs technique:chained technique:source-review vuln:dependency-confusion

**Target:** Dependabot dependency update service (NPM/Yarn/Bundler ecosystems)
**Root cause:** Dependabot's Git-to-registry source conversion treated any Git dependency as a temporarily-pinned public package, and validated the commit-history condition against the Git repo referenced in the attacker-controlled public NPM package's package.json rather than the original private repo.
**Steps:**
1. Identify a private Git dependency name (e.g. from public JS bundles or source maps), such as `giraffe-utils` referenced as `git+ssh://git@github.com:giraffesecurity/giraffe-utils#master`.
2. Publish an NPM package with that exact name to the public registry, version v1.0.0, containing a `preinstall` script with attacker code.
3. In the published package's package.json, point the repository field to an attacker-controlled Git repo with one commit on master tagged v1.0.0.
4. Dependabot sees the Git dependency, checks the commit condition against the attacker repo (which trivially matches), and opens a PR switching the source to the public NPM registry.
5. PR merge or CI install runs the `preinstall` script, executing attacker code in CI.
**How found:** Author noticed Dependabot's Git-to-registry source conversion feature and reasoned about how it decides a Git dependency is temporary vs. intentionally private; reading Dependabot's open-source code revealed all Git dependencies are eligible for conversion and the commit check uses the public package's own repository field.
**Exploitation:** Attacker guesses/derives an unclaimed private Git dependency name, publishes a malicious same-named NPM package with a preinstall script, and sets up a matching Git repo/tag so Dependabot's commit-history check passes. Dependabot opens a PR converting the dependency to the public registry; if auto-merged or installed by CI, the preinstall script runs, exfiltrating source code, secrets, or AWS credentials from the CI environment.
**Escalation:** Chained into CI compromise: preinstall script executes in CI, enabling theft of cloud credentials (e.g. S3) and access to firewall-internal resources; auto-merge workflows amplify to production deployment.
**Insight:** When a tool validates a condition by reading metadata from the artifact it is about to trust (here, the public package's package.json repository field), the check is attacker-controlled; look for trust decisions that resolve references through the untrusted side.
