Skip to main content
友田 陽大
Dependabot & dependency automation
Dependabot
サプライチェーンセキュリティ
GitHub Actions
DevSecOps
依存関係管理
セキュリティ

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
Last updated
Updated
Reading time
8 min read
Author
友田 陽大
Share

"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. 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 before production.


0. The two walls: authentication and reachability

WallError code (official)How to clear it
Authenticationprivate_source_authentication_failureThe registries block + Dependabot secrets
Authentication (certificate)private_source_certificate_failureMake the internal-CA / self-signed cert trusted (in practice, a self-hosted runner where you can install the CA)
Reachabilityprivate_source_not_reachableA self-hosted runner (place the runner on the private network)
Reachability (timeout)private_source_timed_outCheck the network route and proxy allowlist. For a private network, a self-hosted runner

Triage by symptom first: the error code in the registry console or the Dependabot job log identifies which wall you're on. authentication / certificate is the "authentication wall," not_reachable / timed_out is the "reachability wall." For the full error-code taxonomy, see the troubleshooting guide.

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.

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.

typeMain authentication fieldsreplaces-baseNote
npm-registryusername/password or tokennpm/yarn/pnpm
docker-registryusername/password, or static AWS auth for ECRContainer images
maven-repositoryusername/password, or OIDC (tenant-id/client-id)Maven/Gradle
python-indexusername/password, token, or OIDCpip/uv/poetry
nuget-feedusername/password, token, or OIDC.NET
rubygems-serverusername/password or tokenBundler
composer-repositoryusername/passwordPHP (GitHub PAT OK)
cargo-registrytoken (optionally registry)Rust
terraform-registrytokenTerraform
gitusername/passwordGit-sourced dependencies
helm-registryusername/passwordHTTP Basic auth only, no OCI
hex-organizationorganization/keyElixir
hex-repositoryrepo/url/auth-key (optionally public-key-fingerprint)Elixir self-hosted repo
goproxy-serverusername/passwordGo module proxy
pub-repositoryurl/tokenDart/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)

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)

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. Scope the IAM to a read-only least privilege. The pull actions can be limited to the target repository ARN, and no write permission is needed.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DependabotEcrGetToken",
      "Effect": "Allow",
      "Action": "ecr:GetAuthorizationToken",
      "Resource": "*"
    },
    {
      "Sid": "DependabotEcrPullReadOnly",
      "Effect": "Allow",
      "Action": [
        "ecr:BatchCheckLayerAvailability",
        "ecr:GetDownloadUrlForLayer",
        "ecr:BatchGetImage",
        "ecr:DescribeImages",
        "ecr:ListImages"
      ],
      "Resource": "arn:aws:ecr:ap-northeast-1:111122223333:repository/my-app"
    }
  ]
}

ecr:GetAuthorizationToken is an account-level permission whose Resource can't be narrowed, so * is required; but the pull actions that actually fetch images can be limited to the target repository ARN. If you'd rather not store an IAM user's long-lived access key, consider a setup that assumes a role via OIDC.

For Docker-base-image-update operations, head to the Docker base-image update guide.

5.3 JFrog Artifactory (npm example)

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. A copy-paste "everything" dependabot.yml

The practical pattern for handling multiple private registries in one file. Define registries at the top level and explicitly link only the registries each updates job uses.

version: 2

registries:
  # ① AWS CodeArtifact(npm)— 可能なら静的トークンではなく OIDC 連携へ寄せる
  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}}
  # ② Amazon ECR(Docker)— 読み取り専用IAMの静的AWS認証
  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}}
  # ③ JFrog Artifactory(Maven)— 社内ミラーを唯一の取得元に
  artifactory-maven:
    type: maven-repository
    url: https://artifactory.example.com/artifactory/libs-release
    username: ${{secrets.DEPENDABOT_ARTIFACTORY_USER}}
    password: ${{secrets.DEPENDABOT_ARTIFACTORY_TOKEN}}
    replaces-base: true
  # ④ 社内プライベート PyPI(pip)
  internal-pypi:
    type: python-index
    url: https://pypi.example.com/simple
    token: ${{secrets.DEPENDABOT_PYPI_TOKEN}}

updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    registries:
      - codeartifact-npm      # このジョブは CodeArtifact だけを参照

  - package-ecosystem: "docker"
    directory: "/"
    schedule:
      interval: "weekly"
    registries:
      - ecr

  - package-ecosystem: "maven"
    directory: "/"
    schedule:
      interval: "weekly"
    registries:
      - artifactory-maven

  - package-ecosystem: "pip"
    directory: "/"
    schedule:
      interval: "weekly"
    registries:
      - internal-pypi

  # GitHub Packages はここに書かない(GITHUB_TOKEN で自動認証)
  - package-ecosystem: "npm"
    directory: "/packages/internal"
    schedule:
      interval: "weekly"

The least-privilege point: by default each updates job has access to none of the registries. Only the ones listed in that job's registries: are usable. The npm job can't see the ECR credentials, minimizing the exposure surface of credentials. Don't write registries for the GitHub Packages job — it's auto-authenticated with GITHUB_TOKEN (see section 3).


7. 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.

7.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

7.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.

7.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.

8. 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

To extend this configuration into dependency automation across your whole CI/CD, see the Dependabot production-operations guide; for errors beyond authentication and reachability, see the troubleshooting guide.

Frequently asked questions

Where do I put the registries token? (Not in Actions secrets?)
In Dependabot secrets (Settings → Secrets and variables → Dependabot). This is a separate store from regular Actions secrets, and Dependabot jobs cannot reference Actions secrets. If you registered it on the Actions side and it won't authenticate, re-register it as a Dependabot secret. This design prevents a compromised dependency from stealing secrets via CI.
Do internal GitHub Packages / ghcr.io packages also need a registries definition?
No. Dependabot auto-authenticates with GITHUB_TOKEN, using the same Manage Actions access grant that GitHub Actions workflows use. Internal packages in the same organization become update targets without a PAT or a registry entry in dependabot.yml.
I want to authenticate without placing static tokens.
An OIDC-capable registry lets you authenticate with short-lived federation tokens and store no long-term secrets. The official docs list AWS CodeArtifact / Azure DevOps Artifacts / Cloudsmith / Google Cloud Artifact Registry / JFrog Artifactory. Make OIDC the first choice where possible.
I configured it but get private_source_not_reachable.
This is reachability, not authentication. A registry on a private network (e.g. inside a VPC) is unreachable from GitHub-hosted runners. Stand up a self-hosted runner and, for a standalone repository, attach the dependabot label to it. Without the label, jobs queue indefinitely and it looks like nothing happens.
What's the difference between private_source_certificate_failure and private_source_timed_out?
certificate_failure means Dependabot can't validate the registry's TLS certificate — common with an internal-CA or self-signed Artifactory / Nexus — and is resolved with a self-hosted runner that can trust the CA. timed_out is a variant of reachability: check the network route, proxy allowlist, and firewall.
May I share the self-hosted runner with my usual CI runner?
Not recommended. Because Dependabot can touch dependencies outside the trust boundary (the updated ones), isolate a dedicated runner from other uses, operate it at least privilege for both network and credentials, and keep it where it can't touch production secrets.
What's the minimum IAM permission needed to pull from ECR?
ecr:GetAuthorizationToken (Resource must be *) plus the pull actions ecr:BatchCheckLayerAvailability / ecr:GetDownloadUrlForLayer / ecr:BatchGetImage are the core (add ecr:DescribeImages / ecr:ListImages if you need to enumerate or check tags). The pull actions can be scoped to the target repository ARN, and no write permission is needed. A read-only least-privilege IAM is recommended.

References

友田

友田 陽大

Developer of a METI Minister's Award–winning product. With TypeScript + Python + AWS, I deliver SaaS, industry DX, and production-grade generative AI (RAG) end to end — from requirements to infrastructure and operations — single-handedly.

I can take on the implementation from this article as an engagement

Dependency auto-updates & supply-chain defense, from design to production

From enabling alerts/security/version updates, to dependabot.yml design (groups, cooldown, monorepo directories, private registries), safe auto-merge via GitHub Actions + fetch-metadata (auto for patch/minor, human review for major), severity-based-SLA vulnerability response, and observability of the open count. With experience wiring dependency updates into CI quality gates, I implement automation that doesn't flood you with PRs or pile up technical debt.

Available for both project-based (contract) and advisory engagements. Start with a free 30-minute consult.

最短ルート:カレンダーから直接予約

相談内容が固まっている方は、フォーム送信よりその場で日程を確定する方がスムーズです。下記から空き時間をお選びください。

  • 30分のオンライン無料相談
  • Google Meet / Zoom / Microsoft Teams
  • NDA 商談前締結可・無理な営業はいたしません
無料相談の空き枠を予約する

Also worth reading