# Dependabot × private-registry authentication, the complete guide: npm/Docker/Maven/PyPI, CodeArtifact, OIDC, self-hosted runners

> An implementation guide to updating internal/private-registry dependencies with Dependabot. Faithful to the official documentation (as of June 2026), it explains, with copy-paste real code and least-privilege design: the authentication fields per registries-block type, Dependabot secrets (≠ Actions secrets), GitHub Packages auto-authentication, OIDC for AWS CodeArtifact / Google Artifact Registry / JFrog Artifactory, static AWS auth for ECR, and self-hosted runners (the dependabot label) that reach a private network.

- Published: 2026-06-28
- Author: 友田 陽大
- Tags: Dependabot, サプライチェーンセキュリティ, GitHub Actions, DevSecOps, 依存関係管理, セキュリティ
- URL: https://tomodahinata.com/en/blog/dependabot-private-registries-authentication-self-hosted-runners-guide
- Category: Dependabot & dependency automation
- Pillar guide: https://tomodahinata.com/en/blog/dependabot-production-guide

## Key points

- Private-registry support has two walls — 'authentication (credentials)' and 'reachability (network).' Clear the former with the registries block + Dependabot secrets, the latter with a self-hosted runner.
- registries credentials are passed with ${{secrets.NAME}}, but the reference is the Dependabot-dedicated secret store (Settings→Secrets and variables→Dependabot). It's separate from regular Actions secrets, and Dependabot jobs can't see Actions secrets.
- The types are npm-registry / docker-registry / maven-repository / python-index / nuget-feed / rubygems-server / composer-repository / cargo-registry / terraform-registry / git / helm-registry / hex-* / goproxy-server / pub-repository. Many take username/password or a token, and some support replaces-base.
- GitHub Packages / Container Registry are special, with no registries entry needed. Dependabot auto-authenticates with GITHUB_TOKEN. CodeArtifact / Azure Artifacts / Cloudsmith / Google Artifact Registry / JFrog Artifactory support OIDC, letting you avoid static tokens.
- Update registries on a private network unreachable from GitHub-hosted runners with a self-hosted runner. Without the dependabot label on the runner, jobs queue indefinitely. Isolate the runner and operate it at least privilege.

---

"Public packages got auto-updated with Dependabot. But **the internal npm registry, Artifactory, and ECR private images** don't get updated" — a wall you always hit in enterprise. The cause decomposes into two. Does **authentication (credentials) not pass**, or is there **no network reachability (network)?** These two have completely different fixes.

This article comprehensively covers **private-registry support** at the implementation level, as a topic of the [Dependabot production-operations guide](/blog/dependabot-production-guide). From per-type authentication to OIDC and self-hosted runners, it explains with **settings usable as-is.**

> **Rules for this article**: the `registries` types, authentication fields, and OIDC support are based on the **GitHub official documentation (as of June 2026).** **Never hardcode credentials in the repository**; pass them with Dependabot secrets. Always confirm the latest in the [official private-registry configuration](https://docs.github.com/en/code-security/dependabot/working-with-dependabot/configuring-access-to-private-registries-for-dependabot) before production.

---

## 0. The two walls: authentication and reachability

| Wall | Symptom | How to clear it |
| --- | --- | --- |
| **Authentication** | `private_source_authentication_failure` | The `registries` block + **Dependabot secrets** |
| **Reachability** | `private_source_not_reachable` / `timed_out` | A **self-hosted runner** (place the runner on the private network) |

A cloud managed registry (CodeArtifact, Artifact Registry, Artifactory SaaS) is **a public endpoint + authentication**, so only the "authentication wall." A registry **unreachable from the internet, like inside a VPC**, also needs to clear the "reachability wall." First discern which you have.

---

## 1. The basics of the registries block

Define `registries` at the top level of `dependabot.yml` and link it from each `updates` job.

```yaml
version: 2
registries:
  my-npm:
    type: npm-registry
    url: https://npm.example.com
    token: ${{secrets.DEPENDABOT_NPM_TOKEN}}   # ← Dependabot シークレットを参照

updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    registries:
      - my-npm        # このジョブで使うレジストリ
```

> **Most important**: what `${{secrets.NAME}}` references is the **Dependabot-dedicated secret store.** The location is **Settings → Secrets and variables → Dependabot** (repository or organization). It's **separate from regular Actions secrets**, and Dependabot jobs can't see Actions secrets. This is a design to prevent "a compromised dependency stealing secrets via CI." Secrets are encrypted before reaching GitHub and stay encrypted until the moment Dependabot uses them.

---

## 2. Authentication reference by type

The usable authentication fields are fixed per `type` (official). Here's a table of the commonly used ones.

| `type` | Main authentication fields | replaces-base | Note |
| --- | --- | --- | --- |
| `npm-registry` | `username`/`password` or `token` | ✓ | npm/yarn/pnpm |
| `docker-registry` | `username`/`password`, or static AWS auth for ECR | ✓ | Container images |
| `maven-repository` | `username`/`password`, or OIDC (`tenant-id`/`client-id`) | ✓ | Maven/Gradle |
| `python-index` | `username`/`password`, `token`, or OIDC | ✓ | pip/uv/poetry |
| `nuget-feed` | `username`/`password`, `token`, or OIDC | ✗ | .NET |
| `rubygems-server` | `username`/`password` or `token` | ✓ | Bundler |
| `composer-repository` | `username`/`password` | — | PHP (GitHub PAT OK) |
| `cargo-registry` | `token` (optionally `registry`) | — | Rust |
| `terraform-registry` | `token` | — | Terraform |
| `git` | `username`/`password` | — | Git-sourced dependencies |
| `helm-registry` | `username`/`password` | — | **HTTP Basic auth only**, no OCI |
| `hex-organization` | `organization`/`key` | — | Elixir |
| `hex-repository` | `repo`/`url`/`auth-key` (optionally `public-key-fingerprint`) | — | Elixir self-hosted repo |
| `goproxy-server` | `username`/`password` | — | Go module proxy |
| `pub-repository` | `url`/`token` | — | Dart/Flutter |

> `replaces-base: true` specifies "use this private registry as the default instead of the public registry (e.g. registry.npmjs.org)." Use it when you want an internal mirror to be the sole fetch source.

---

## 3. GitHub Packages is "special" (no registries needed)

GitHub Packages / GitHub Container Registry (`ghcr.io`) **don't need a `registries` entry written.**

> Official: "Dependabot can **auto-authenticate with `GITHUB_TOKEN`.** This uses the same 'Manage Actions access' grant that GitHub Actions workflows use. No PAT or registry entry in `dependabot.yml` is needed."

So internal packages placed in the same organization's GitHub Packages become update targets with **zero additional configuration.** Access is managed by the repository's "Manage Actions access." This is one of the biggest benefits of leaning into the GitHub ecosystem.

---

## 4. "Don't place static tokens" with OIDC

Static tokens/passwords come with the hassle of revocation management, leakage risk, and inventory. With an **OIDC (OpenID Connect)-capable registry**, you can authenticate with short-lived federation tokens and design it so you **store no long-term secrets.**

The OIDC-capable ones the official docs list are as follows.

- **AWS CodeArtifact**
- **Azure DevOps Artifacts**
- **Cloudsmith**
- **Google Cloud Artifact Registry**
- **JFrog Artifactory**

The form using `tenant-id` / `client-id` in `maven-repository` / `python-index` / `nuget-feed`, etc., applies. For both security and cost efficiency (reduced key-management operational load), **make OIDC the first choice where possible.** It's the same philosophy as keyless CI/CD.

---

## 5. Cloud-by-cloud examples

### 5.1 AWS CodeArtifact (npm / pip)

```yaml
version: 2
registries:
  codeartifact-npm:
    type: npm-registry
    url: https://my-domain-111122223333.d.codeartifact.ap-northeast-1.amazonaws.com/npm/my-repo/
    token: ${{secrets.DEPENDABOT_CODEARTIFACT_TOKEN}}
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    registries: ["codeartifact-npm"]
```

CodeArtifact **also supports OIDC**, so where possible lean to OIDC federation rather than a static token.

### 5.2 Amazon ECR (Docker, static AWS auth)

```yaml
registries:
  ecr:
    type: docker-registry
    url: 111122223333.dkr.ecr.ap-northeast-1.amazonaws.com
    username: ${{secrets.DEPENDABOT_AWS_ACCESS_KEY_ID}}
    password: ${{secrets.DEPENDABOT_AWS_SECRET_ACCESS_KEY}}
```

`docker-registry` can use static AWS auth for **pulling from ECR** (a read-only least-privilege IAM is recommended). For Docker-base-image-update operations, head to the [Docker base-image update guide](/blog/dependabot-docker-base-image-digest-pinning-updates-guide).

### 5.3 JFrog Artifactory (npm example)

```yaml
registries:
  artifactory-npm:
    type: npm-registry
    url: https://artifactory.example.com/artifactory/api/npm/npm-virtual
    username: ${{secrets.DEPENDABOT_ARTIFACTORY_USER}}
    password: ${{secrets.DEPENDABOT_ARTIFACTORY_TOKEN}}
    replaces-base: true
```

Artifactory **supports OIDC** too. The stricter the governance requirements, the more it's worth choosing OIDC.

---

## 6. The reachability wall: self-hosted runners

So far it's about "authentication." A registry **reachable only inside a VPC / internal network** **simply doesn't reach** from GitHub-hosted runners. In this case, run Dependabot on a **self-hosted runner.**

### 6.1 When it becomes necessary

- An internet-private internal Artifactory / Nexus / private PyPI / internal Go proxy
- CodeArtifact / Artifact Registry reachable only via a VPC endpoint

### 6.2 The key points of setup (official)

1. **Prerequisites**: Dependabot enabled, GitHub Actions enabled.
2. **Prepare the runner**: register a self-hosted runner at the repository or organization level.
3. **Meet the environment requirements**: an execution environment where Dependabot jobs run (the needed tools, network).
4. **Attach the `dependabot` label**: for a single repository, the **`dependabot` label**; for an organization, the prescribed label.

> **A gotcha (must-read)**: when you enable this feature, **Dependabot jobs run only on runners with the `dependabot` label.** Forgetting the label is a serious pitfall where jobs **keep queuing forever** (= it looks like nothing happens). Always verify "does a labeled runner truly exist" before enabling.

### 6.3 Network and security design

- **Network**: the runner can reach **both GitHub and the target registry.** Arrange the firewall/proxy allowlist.
- **Isolation**: a self-hosted runner is an execution environment where Dependabot **can touch outside the trust boundary (the updated dependencies).** **Isolate it from other uses** and operate it at **least privilege** (both network and credentials). Don't run it where it can touch production secrets.

---

## 7. Security checklist

- [ ] All credentials in **Dependabot secrets** (not in Actions secrets, not hardcoded)
- [ ] **OIDC** for capable registries (CodeArtifact / Azure Artifacts / Cloudsmith / Artifact Registry / Artifactory) to eliminate static tokens
- [ ] Tokens at **least privilege, read-only** (only the scope needed to fetch updates)
- [ ] Use `GITHUB_TOKEN` auto-authentication for GitHub Packages, don't create extra PATs
- [ ] Self-hosted runners **isolated, at least privilege**, verify the `dependabot` label
- [ ] On an auth error, isolate with the [four-category error codes](/blog/dependabot-troubleshooting-not-creating-pull-requests-errors-guide#4-プライベートレジストリのエラー4分類)

---

## 8. FAQ

**Q. Where do I put the registries token?**
A. In **Dependabot secrets** (Settings → Secrets and variables → Dependabot). It's a separate store from Actions secrets, and Dependabot jobs can't reference Actions secrets.

**Q. Do internal GitHub Packages packages also need a registries definition?**
A. No. Dependabot auto-authenticates with `GITHUB_TOKEN`. Access is managed by "Manage Actions access."

**Q. I don't want to place static tokens.**
A. With an OIDC-capable registry (CodeArtifact / Azure Artifacts / Cloudsmith / Google Artifact Registry / JFrog Artifactory), OIDC federation lets you avoid storing long-term secrets.

**Q. I configured it but get `private_source_not_reachable`.**
A. It's not authentication but a **reachability** problem. For a private-network registry, stand up a **self-hosted runner** and attach the `dependabot` label to it (without the label, jobs queue indefinitely).

**Q. May I share the self-hosted runner with my usual CI runner?**
A. Not recommended. Operate the Dependabot one **isolated, at least privilege**, in an environment that can't touch production secrets.
