whiteweb.security / guides / Docker config.json exposed
.docker/config.json High severity ~6 min read

My Docker registry credentials got exposed. What should I do?

Docker stores registry authentication tokens in ~/.docker/config.json. These tokens are base64-encoded (not encrypted) and trivially decodable. An attacker with this file can pull private images from your registry, push malicious images to your repositories, and read any secrets baked into your container images.

The "auth" value in config.json is not encrypted — it decodes immediately.

The auth field in config.json is simply base64(username:password) or a token. Anyone who has the file can decode it in seconds with a single command. If the file was accessible, treat the credentials as fully exposed.

// the 60-second version

  • Decode the auth token from the file to understand exactly what was exposed.
  • Revoke the exposed token or change the password in the registry's account settings.
  • Review registry access logs for unauthorised pulls or pushes during the exposure window.
  • Switch to Docker credential helpers so tokens are never stored in plain text.

01Understand what .docker/config.json contains

When you run docker login, Docker stores the authentication credentials in ~/.docker/config.json. The file typically looks like this:

example config.json structure~/.docker/config.json
{ "auths": { "https://index.docker.io/v1/": { "auth": "dXNlcm5hbWU6cGFzc3dvcmQ=" }, "registry.example.com": { "auth": "ZGVwbG95OmFwaXRva2Vu" } } }

The auth value is trivially decodable:

decode the auth tokenbash
# base64 decode reveals username:password or username:token echo "dXNlcm5hbWU6cGFzc3dvcmQ=" | base64 --decode # output: username:password

The implications depend on what registries are listed and what permissions the authenticated account holds:

  • Docker Hub — can pull all private repositories, push to all repositories the account has write access to, delete repositories and tags.
  • Private corporate registry — can pull proprietary images that may contain source code, environment variables baked in at build time, SSH keys, or internal infrastructure details.
  • AWS ECR / GCR / Azure ACR — if the token is a registry password (rather than a short-lived ECR token), may allow access to all images across the registry.

Container images often contain secrets baked in during the build process. If an attacker can pull your private images, they may find additional credentials, SSH keys, API keys, or internal network configuration embedded in image layers.

02Revoke the exposed tokens

Go to each registry listed in the config file and revoke or rotate the credentials:

  • Docker Hub — go to Account Settings > Security > Access Tokens. If a personal access token was used, delete it and create a new one. If your account password was stored, change the password immediately and enable 2FA.
  • GitHub Container Registry (ghcr.io) — go to Settings > Developer Settings > Personal Access Tokens and revoke the token.
  • GitLab Registry — revoke the personal access token or deploy token used for authentication.
  • AWS ECR — ECR tokens are short-lived (12 hours) and generated by aws ecr get-login-password. If the underlying AWS credentials used to generate ECR tokens were exposed, revoke those via IAM.
  • Private registry with username/password — change the password for that registry account.

03Generate new credentials and reconfigure Docker

After revoking, generate new access tokens with the minimum scope needed:

log in to Docker Hub with a new access tokenbash
# log out to clear existing auth docker logout # log in with new credentials (creates new config.json entry) docker login -u yourusername # enter new access token when prompted # for a private registry docker login registry.example.com -u deploy -p new-token

For Docker Hub, prefer personal access tokens with limited scope (read-only where possible) over your account password. Tokens can be revoked individually without changing your account credentials.

04Review registry access logs

Check whether the exposed credentials were used to pull or push images during the exposure window:

  • Docker Hub — Docker Hub provides activity logs for organisations in the Docker Business plan. For personal accounts, review the Activity tab on each repository.
  • AWS ECR — enable CloudTrail logging and look for GetAuthorizationToken, BatchGetImage, and PutImage events from unexpected source IPs.
  • GitHub Packages — review the package's usage logs in the GitHub UI under the package's page.
  • Self-hosted registries — check the registry's access log file for pull and push events from IP addresses outside your normal range.

An attacker who pulls your images can study them for further secrets. If you find evidence of unauthorised pulls, audit your images for baked-in credentials and consider rotating any secrets that might be present in image layers.

05Use Docker credential helpers to stop storing tokens in plain text

The proper solution is to never store credentials in config.json at all, using a credential helper that stores tokens in the OS keychain:

configure a credential helper~/.docker/config.json
{ "credsStore": "secretservice" // Linux (libsecret) "credsStore": "osxkeychain" // macOS "credsStore": "wincred" // Windows }

With a credential helper configured, docker login stores tokens in the OS keychain instead of config.json. The auth key disappears from the file, and the credentials are only accessible to processes running as your user.

Never include ~/.docker/config.json in your deployment artefacts or Docker image build context. Add it to .dockerignore and .gitignore. For CI/CD pipelines, use short-lived registry tokens or OIDC-based authentication rather than persisting credentials in config files.

Was this guide useful?

These playbooks are free to read and share. If a heads-up ever saved you a bad week, you can say thanks — or jump into the other guides.