Dependabot can now access private packages hosted in GitHub Packages without requiring a personal access token.
This is a useful change for teams that previously had to create a personal access token, store it as a Dependabot secret, and maintain that credential just so Dependabot could read an internal package.
The newer approach uses Dependabot's GITHUB_TOKEN and the package's existing repository access rules.
There is one important requirement: the repository running Dependabot must be explicitly granted access to the private package through the package's Manage Actions access settings.
Once that access is configured, Dependabot can authenticate to supported GitHub-hosted registries without a PAT-based registry entry in dependabot.yml.
The Old Approach
Before automatic access to GitHub-hosted registries, a common setup looked like this:
version: 2
registries:
github-packages:
type: nuget-feed
url: https://nuget.pkg.github.com/my-company/index.json
token: ${{secrets.GITHUB_PACKAGES_TOKEN}}
updates:
- package-ecosystem: nuget
directory: "/"
registries:
- github-packages
schedule:
interval: weekly
The token stored in the Dependabot secret was typically a personal access token with permission to read packages.
That worked, but it introduced another credential that an organization had to manage.
The token could expire, be revoked, lose the required permission, or remain in the system after the person who created it left the organization.
For a dependency bot that only needs read access to a package, maintaining a personal credential is unnecessary overhead.
The New Approach
Dependabot can now request packages: read using its own GITHUB_TOKEN.
The package grants access to the repository, and Dependabot uses that grant when it pulls the package.
The resulting model is simpler:
Private GitHub Package
|
v
Manage Actions access
|
+---- Repository A: Read
+---- Repository B: Read
|
v
Dependabot
|
v
GITHUB_TOKEN
|
v
packages: read
The important point is that authentication and authorization are still separate concepts.
The token provides the identity and authentication mechanism. The package's access configuration determines whether that repository is allowed to read the package.
Configure Package Access First
The most important configuration step happens in the package settings, not in dependabot.yml.
For every private package that Dependabot needs to read:
Open the package settings.
Find Manage Actions access.
Add the repository where Dependabot runs.
Give that repository Read access.
Repeat the process for each private package.
Dependabot only needs read access when it is checking package versions.
You do not need to grant write or administrative package permissions simply because Dependabot creates pull requests.
Example with a Private NuGet Package
Suppose an organization publishes:
Company.Security.Core
Company.Data.Client
Company.Logging
to GitHub Packages.
An application repository contains:
<ItemGroup>
<PackageReference
Include="Company.Security.Core"
Version="4.2.0" />
<PackageReference
Include="Company.Data.Client"
Version="7.1.0" />
</ItemGroup>
The package repositories must grant the application repository read access through Manage Actions access.
After that, Dependabot can access the packages using its GitHub-provided token.
The important part is that the dependabot.yml file does not need a PAT-based registry entry for these GitHub-hosted packages.
A minimal configuration can therefore remain focused on dependency updates:
version: 2
updates:
- package-ecosystem: nuget
directory: "/"
schedule:
interval: weekly
The package access is handled through GitHub's package permissions.
What Happens to an Existing PAT Configuration?
If you already have a PAT-based configuration, you do not necessarily need to keep it.
For a package that qualifies for automatic GitHub-hosted registry access, you can remove the PAT-based registry configuration after verifying that repository access has been granted.
For example, this:
registries:
github-packages:
type: nuget-feed
url: https://nuget.pkg.github.com/my-company/index.json
token: ${{secrets.GITHUB_PACKAGES_TOKEN}}
updates:
- package-ecosystem: nuget
directory: "/"
registries:
- github-packages
schedule:
interval: weekly
can become:
version: 2
updates:
- package-ecosystem: nuget
directory: "/"
schedule:
interval: weekly
Do not delete the secret first and assume everything will continue working.
First grant package access, run a Dependabot update, verify that the private package can be resolved, and then remove the obsolete credential configuration.
Why This Is Better Than a Personal Access Token
The biggest improvement is credential lifecycle management.
With a PAT-based configuration:
Developer creates PAT
|
v
PAT stored as Dependabot secret
|
v
Dependabot uses PAT
|
+---- Token expires
+---- Token revoked
+---- User leaves organization
+---- Permission changes
With automatic GitHub-hosted registry access:
Repository
|
v
Package access grant
|
v
Dependabot GITHUB_TOKEN
|
v
Read package
The package access relationship is tied to the repository instead of an individual developer's credential.
That makes the configuration easier to audit and maintain.
Repository Access Is Still Required
Removing the PAT does not mean private packages become publicly available to Dependabot.
The repository must still have permission to access the package.
For example:
Company.Security.Core
|
+-- Application-A: Read
+-- Application-B: Read
+-- Application-C: No access
If Application-C uses Company.Security.Core but has not been granted access, Dependabot cannot simply bypass that restriction.
This is an important security boundary.
GitHub Actions Access and Dependabot
The new mechanism follows the same general package-access model used by GitHub Actions.
Dependabot jobs can request the package read permission through their GITHUB_TOKEN.
This is particularly useful because Dependabot now runs its jobs using GitHub Actions infrastructure.
The package itself decides which repositories are allowed to use it.
That means an organization can maintain a clear relationship:
Package
|
+-- Repository that publishes it
|
+-- Repository that consumes it
|
+-- Repository used for testing
Each repository can be given only the access it requires.
What About GitHub Container Registry?
The same automatic access mechanism also applies to GitHub-hosted container registries supported by Dependabot.
For example, a repository may depend on an internal container image.
The same principle applies:
Private container image
|
v
Manage Actions access
|
v
Repository gets Read access
|
v
Dependabot uses GITHUB_TOKEN
This avoids creating a separate long-lived personal credential for the package pull.
Supported GitHub Package Ecosystems
The automatic authentication mechanism applies across the GitHub Packages ecosystems supported by Dependabot.
That can include package types such as:
NuGet
npm
Maven
RubyGems
Gradle
Docker/Container Registry
The exact package configuration still depends on the ecosystem.
For example, a .NET application uses NuGet, while a JavaScript application uses npm.
The important part is that the package is hosted by GitHub and the consuming repository has been granted access.
Private Registry vs Private GitHub Package
Do not confuse a private GitHub Package with an unrelated private registry.
This automatic mechanism is specifically for GitHub-hosted package registries.
For example:
Registry | Automatic GitHub token access |
|---|---|
GitHub Packages | Yes |
GitHub Container Registry | Yes |
Private Azure Artifacts feed | No |
Private JFrog Artifactory | No |
Private Nexus registry | No |
Internal package server | No |
External registries still need their own authentication mechanism.
For those registries, Dependabot's private registry configuration and encrypted secrets remain relevant.
A Common .NET Scenario
Consider an organization with two repositories:
company-data-library
|
+---- Company.Data.Client
|
v
customer-api
The library publishes a private NuGet package.
The API project consumes it:
<ItemGroup>
<PackageReference
Include="Company.Data.Client"
Version="3.4.1" />
</ItemGroup>
The setup should be:
Step 1: Publish the Package
The package is available through GitHub Packages.
Step 2: Grant Repository Access
In the package settings, add:
customer-api
with:
Read
access under Manage Actions access.
Step 3: Configure Dependabot
Keep the NuGet update configuration simple:
version: 2
updates:
- package-ecosystem: nuget
directory: "/"
schedule:
interval: weekly
Step 4: Trigger an Update
Allow Dependabot to check the repository.
If the package has a newer version, Dependabot should be able to resolve the private package using its GitHub token.
Step 5: Verify the Pull Request
Check that:
The private package was resolved.
The dependency update was generated.
No PAT-based registry secret was required.
The pull request workflow succeeds.
Package Source Mapping Still Matters
Authentication is only one part of secure package management.
If a .NET project uses both NuGet.org and GitHub Packages, consider NuGet package source mapping.
For example:
<configuration>
<packageSources>
<add key="nuget.org"
value="https://api.nuget.org/v3/index.json" />
<add key="github"
value="https://nuget.pkg.github.com/my-company/index.json" />
</packageSources>
<packageSourceMapping>
<packageSource key="nuget.org">
<package pattern="*" />
</packageSource>
<packageSource key="github">
<package pattern="Company.*" />
</packageSource>
</packageSourceMapping>
</configuration>
This tells NuGet which source should provide which packages.
That is useful for private packages because a package with an internal naming convention should not unexpectedly resolve from a public registry.
Authentication and package-source selection solve different problems.
Troubleshooting
Dependabot Still Reports Authentication Failure
Check the package's Manage Actions access settings first.
Make sure the repository running Dependabot has Read access.
The Package Works in GitHub Actions but Not Dependabot
Verify that the package access grant is configured for the exact repository where Dependabot is running.
Do not assume that access granted to one repository automatically applies to another.
Some Packages Work and Others Fail
Check every private package individually.
A repository may have access to one package but not another.
Public Dependencies Start Failing
If GitHub Packages is configured alongside a public registry, inspect your package source configuration.
For NuGet, package source mapping can prevent unrelated public packages from being resolved through the private GitHub Packages source.
You Removed the PAT Too Early
If you removed the PAT before granting package access, Dependabot may immediately start failing.
Restore the previous working configuration if necessary, establish repository package access, verify the new method, and then remove the old credential.
Common Mistakes
Granting Too Much Access
Dependabot generally needs package read access.
Do not grant write or administrative permissions when they are unnecessary.
Granting Access to the Wrong Repository
Package permissions are repository-specific.
Verify the exact repository that contains the Dependabot configuration.
Keeping PATs Forever
Once automatic access is confirmed, review whether old PAT-based secrets and registry entries are still required.
Unused credentials increase maintenance overhead.
Assuming All Private Registries Work This Way
The automatic token mechanism applies to GitHub-hosted registries.
It does not replace authentication for external registries.
Removing Package Access Because the PAT Is Gone
The PAT has been removed from the authentication path, not the authorization requirement.
The package still needs to grant the repository access.
Security Benefits
Removing personal access tokens from this workflow provides several practical benefits:
Fewer long-lived credentials.
Less secret rotation work.
No dependency on an individual developer's token.
Easier repository-level access auditing.
Smaller credential-management surface.
Better alignment between package access and repository identity.
It also reduces one common source of Dependabot failures: an expired or revoked personal credential.
Advantages and Disadvantages
Advantages | Disadvantages |
|---|---|
No PAT required for qualifying GitHub-hosted packages | Requires package access configuration |
Reduces secret management | Access must be granted per repository |
Avoids PAT expiration problems | Does not apply to unrelated private registries |
Uses repository-based permissions | Existing PAT configurations may need cleanup |
Easier to audit | Troubleshooting still requires understanding package permissions |
Works across supported GitHub Packages ecosystems | Incorrect package access still causes restore failures |
Recommended Migration Checklist
If your repository currently uses a PAT for private GitHub Packages, use this sequence:
[ ] Identify every private GitHub Package used by the repository
[ ] Open each package's access settings
[ ] Add the consuming repository under Manage Actions access
[ ] Grant Read access
[ ] Keep the existing PAT configuration temporarily
[ ] Run a Dependabot update
[ ] Confirm the private package resolves correctly
[ ] Check the generated pull request
[ ] Remove the PAT-based registry entry
[ ] Remove the obsolete Dependabot secret
[ ] Run another Dependabot update
[ ] Confirm everything still works
Final Takeaway
Dependabot no longer needs a personal access token to read qualifying private packages hosted in GitHub Packages.
The newer approach uses Dependabot's GITHUB_TOKEN and the repository's package access grant. The repository must be given Read access through Manage Actions access, after which Dependabot can authenticate automatically.
For .NET teams using private NuGet packages, this is a meaningful simplification. The dependabot.yml file can stay focused on dependency-update behavior, while package authorization remains in GitHub's package access controls.
The best migration strategy is straightforward: grant repository access, verify Dependabot can resolve the package, then remove the PAT-based configuration and secret.

Join the conversation! Your thoughts help the community grow.