Docker "403 Forbidden" from ECR/GHCR auth in CI
ECR and GHCR return 403 when the token is expired or the identity lacks permission. ECR auth tokens are short-lived, and GHCR needs the right package scope on the token.
What this error means
A pull or push to an ECR or GHCR repository fails with 403 Forbidden or denied. It often follows a stale login or a token without the right scope.
docker
error: failed to push 1234.dkr.ecr.us-east-1.amazonaws.com/app:latest:
unexpected status from PUT request to https://1234.dkr.ecr.us-east-1.amazonaws.com/v2/app/manifests/latest: 403 ForbiddenCommon causes
Expired ECR auth token
ECR login tokens last ~12 hours; a long job or a reused login can outlive the token.
Insufficient IAM or package permission
The IAM role lacks ecr:PutImage/BatchGetImage, or the GHCR token lacks write:packages.
Repository policy denies the principal
An ECR repository policy or GHCR package visibility blocks this identity.
How to fix it
Refresh ECR auth and check IAM
- Re-run ecr get-login-password right before the push.
- Ensure the role has the required ECR actions.
Terminal
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 1234.dkr.ecr.us-east-1.amazonaws.comScope the GHCR token correctly
- Grant packages: write (or a PAT with write:packages) and re-login.
.github/workflows/build.yml
permissions:
packages: writeHow to prevent it
- Refresh ECR tokens immediately before use, grant least-privilege ECR/GHCR permissions, and check repository policies. A 403 from auth is deterministic, so a retry alone will not fix credentials.
Related guides
Docker "unauthorized: authentication required" on pull in CIFix the Docker "unauthorized: authentication required" pull error in CI, caused by an expired token, a logged…
Docker "denied: requested access to the resource is denied" on push in CIFix the Docker "denied: requested access to the resource is denied" push error in CI, caused by missing push…
Docker "pull access denied" for a base image in CIFix the Docker "pull access denied ... repository does not exist" error in CI, caused by a private base image…