Fix GitHub CLI NO_PUBKEY / EXPKEYSIG Errors After the September 2026 Key Rotation
Fix GitHub CLI NO_PUBKEY / EXPKEYSIG Errors After the September 2026 Key Rotation
If apt update, dnf update gh, or yum update gh suddenly started failing on a Linux box that has the GitHub CLI installed from GitHub's own package repository, you're not imagining it. The PGP key GitHub CLI used to sign its Linux packages and repository metadata expired on September 5, 2026, and any system that hadn't picked up the replacement key by then starts throwing signature verification failures on every package operation โ not just gh upgrades.
Why this happens
GitHub CLI's apt/dnf/yum/zypper repositories are signed. Every time you run a package manager command, it checks the repo metadata (and the .deb/.rpm files themselves) against a known public key stored locally in your keyring. GitHub published a replacement key back on April 8, 2026, and the repo metadata has been signed with both the old and new key since then โ so if you installed or updated gh any time after that date using the official instructions, you already have the new key and none of this affects you.
The problem hits systems that:
- Installed
ghfrom the official apt/rpm repo before April 8, 2026, and - Never re-ran the install/setup steps since, so the local keyring still only has the old key
Once the old key formally expired on September 5, 2026, GPG (correctly) stops trusting anything signed only with it โ and because the repository metadata itself is what's unverifiable, the failure isn't limited to gh โ a plain apt update on an affected Debian/Ubuntu box will report an error against the whole cli.github.com repo entry until it's fixed.
Errors you'll actually see
Depending on distro and package manager, the exact message varies:
1Failed to fetch https://cli.github.com/packages/... EXPKEYSIG 23F3D4EA75716059
1The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 5612B36462313325
1Warning: File 'repomd.xml' from repository 'gh-cli' is signed with an unknown key
1Certificate for key ... is invalid: certificate is not alive. Expired on 2026-09-05
If you see any of these referencing cli.github.com or a repo named gh-cli, this is the same issue โ go straight to the fix for your package manager below.
Who's affected (check this first)
You only need to do anything if all of these are true:
- You're on Linux (this does not affect Windows, macOS, Homebrew, Conda, direct
.deb/.rpmdownloads, or building from source) - You installed
ghvia the official apt or rpm repository - You haven't re-run the official install steps since April 8, 2026
Quick check on Debian/Ubuntu โ look at the modification time on the keyring file:
1ls -l /etc/apt/keyrings/githubcli-archive-keyring.gpg /usr/share/keyrings/githubcli-archive-keyring.gpg 2>/dev/null
If that file predates April 2026, or apt update is already throwing the errors above, you need the fix.
The fix
Debian / Ubuntu (apt)
Re-download the current keyring โ this pulls both keys and immediately restores trust:
1sudo mkdir -p -m 755 /etc/apt/keyrings
2sudo curl -fsSL -o /etc/apt/keyrings/githubcli-archive-keyring.gpg https://cli.github.com/packages/githubcli-archive-keyring.gpg
3sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg
4sudo apt update
5sudo apt install gh
If your system doesn't have curl, wget works identically:
1sudo wget -qO /etc/apt/keyrings/githubcli-archive-keyring.gpg https://cli.github.com/packages/githubcli-archive-keyring.gpg
Some older installs still keep the keyring at /usr/share/keyrings/githubcli-archive-keyring.gpg instead of /etc/apt/keyrings/ โ check your /etc/apt/sources.list.d/github-cli.list to see which path your signed-by line actually points at, and overwrite that file specifically.
Fedora 41+ (dnf5)
1sudo dnf config-manager addrepo --overwrite --from-repofile=https://cli.github.com/packages/rpm/gh-cli.repo
2sudo dnf update gh
CentOS, RHEL, Fedora 40 or earlier (dnf4)
1sudo dnf config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo
2sudo dnf update gh
Amazon Linux 2 (yum)
1sudo yum-config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo
2sudo yum update gh
openSUSE / SUSE (zypper)
1sudo zypper removerepo gh-cli
2sudo zypper addrepo https://cli.github.com/packages/rpm/gh-cli.repo
3sudo zypper update gh
The RPM-based commands all work the same way: re-adding the repo definition pulls the current signed repo file, which references the new key, resolving the NO_PUBKEY/expired-certificate errors on the next update.
Verifying the fix worked
After running the appropriate commands above, confirm two things separately โ don't just trust that the command exited 0:
1gh --version
2sudo apt update # or dnf/yum/zypper equivalent โ should complete with no signature warnings
If apt update is still clean and gh --version reports the latest release, you're done. On Debian/Ubuntu you can also confirm the new key fingerprint is present:
1gpg --no-default-keyring --keyring /etc/apt/keyrings/githubcli-archive-keyring.gpg --list-keys
Look for a key fingerprint ending in ...462313325 (the new key) alongside or instead of the old ...5716059 fingerprint.
Best practices
- Don't pin or vendor the keyring file in golden images, Docker base images, or infra-as-code without a refresh mechanism โ this exact failure mode (a baked-in keyring going stale) is why this bit so many systems at once. If you bake
ghinto a container image, re-pull the keyring on every image rebuild rather than caching it indefinitely. - Automate the check. If you manage fleets of Linux hosts with
ghinstalled, add a periodic check (cron, Ansible fact, or a CI job) that runsapt update/dnf check-updateand alerts on signature errors โ you don't want to find out about the next rotation from a broken deploy pipeline. - Prefer the official repo over manual
.debdownloads for anything long-lived โ repo-based installs get key rotations automatically once you're current, whereas a one-off downloaded.debhas no ongoing verification story at all.
Common mistakes to avoid
- Deleting the keyring file instead of replacing it. Removing
githubcli-archive-keyring.gpgwithout adding a new one just changes the error to "public key not available" โ you still need to fetch the current file. - Editing
sources.listby hand to disable signature checking ([trusted=yes]or--nogpgcheck) as a "fix." This silences the error but disables package integrity verification entirely โ never do this as a permanent workaround, only ever as a five-minute diagnostic step you immediately revert. - Assuming a
ghreinstall alone fixes it. If yourghbinary itself came from a.debyou downloaded once, reinstalling it doesn't touch the repository's keyring โ theapt updatefailures on the repo entry persist until the keyring file itself is refreshed.
Troubleshooting
apt update still fails after refreshing the keyring. Double check the signed-by path in /etc/apt/sources.list.d/github-cli.list actually matches the file you just wrote. A mismatch (e.g. the source list points at /usr/share/keyrings/... but you refreshed /etc/apt/keyrings/...) leaves the old, now-unverifiable reference in place.
dnf update gh reports "repository not found" after re-adding. Run sudo dnf repolist to confirm gh-cli is enabled, and check /etc/yum.repos.d/gh-cli.repo was actually overwritten with a recent timestamp.
Corporate proxy or mirror in front of cli.github.com. If your organization mirrors GitHub's package repos internally, the mirror needs to sync the updated keyring/repo files too โ this fix only works directly against cli.github.com.
FAQ
Does this affect GitHub Actions runners?
Only self-hosted Linux runners where gh was installed via apt/dnf/yum before April 2026 and never updated. GitHub-hosted runner images are maintained by GitHub and already carry the current key.
Do I need to reinstall gh itself, or just refresh the keyring?
Usually just the keyring/repo refresh โ gh itself isn't broken, only the trust chain used to verify its packages. Running the update command afterward will pick up the latest gh release as a side effect, which is good practice anyway.
Will this happen again with future key rotations? Yes โ GitHub rotates this key periodically (a similar rotation happened in 2024), and each time, systems that installed once and never updated their keyring are affected. There's no way to make a repo-based install permanently immune; the mitigation is keeping systems current, not a one-time fix.
I'm on Homebrew/macOS/Windows โ do I need to do anything? No. This issue is specific to the Linux apt/rpm package repositories; Homebrew, the Windows installer, and direct binary downloads use different distribution and verification mechanisms unaffected by this rotation.
What if I can't identify which package manager broke?
Run command -v apt dnf yum zypper to see which are present, then check cat /etc/apt/sources.list.d/*.list 2>/dev/null or cat /etc/yum.repos.d/*.repo 2>/dev/null for a cli.github.com or gh-cli entry โ that tells you which fix above applies.
Key takeaways
| Situation | Action |
|---|---|
Installed/updated gh via official repo after April 8, 2026 | No action needed |
apt update shows EXPKEYSIG/NO_PUBKEY for cli.github.com | Re-download the keyring file (see apt fix above) |
dnf/yum update gh shows expired-certificate or unknown-key errors | Re-add the repo via config-manager/yum-config-manager |
Managing a fleet with gh baked into images | Refresh the keyring in the image build, don't cache indefinitely |
Using Homebrew, Windows, macOS, or direct .deb/.rpm downloads | Not affected |
Further Reading
- GitHub Actions' New vulnerability-alerts Permission: Read Dependabot Alerts Without a PAT
- GitHub Apps and OAuth Apps Get Refresh Tokens: How to Migrate Off Long-Lived Access Tokens
- GitHub Actions Self-Hosted Runners: Fix Your Version Before the September 25 Enforcement
- Official GitHub CLI signing key rotation announcement (cli/cli#13118)
- GitHub Changelog: GitHub CLI Linux package signing key expires September 5