๐Ÿ” AI Security & Credentials
ยท 3 min read
Last updated on

Git Permission Denied (publickey): Fix SSH for Agents, CI and Deployments


git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

The Git server did not accept any SSH identity offered by the current process. On a developer laptop that may be a missing key. In a coding-agent container or CI runner, it is often the wrong identity, an unavailable agent socket, an untrusted host key or a deploy key without repository access.

Do not solve this by copying your personal private key into an agent or pipeline.

Diagnose before changing keys

git remote -v
ssh -T git@github.com
ssh -vT git@github.com

Verbose output shows which configuration and keys SSH considered. Look for Offering public key and the final failure. Then inspect the current environment:

ssh-add -l
ls -la ~/.ssh
git config --show-origin --get core.sshCommand
printf '%s\n' "$SSH_AUTH_SOCK"

In CI, verify whether checkout uses SSH at all. Many hosted runners use a temporary HTTPS token instead.

Local developer fix

Generate a modern Ed25519 key and protect it with a passphrase:

ssh-keygen -t ed25519 -C "developer@example.com"
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

Add only id_ed25519.pub to the Git provider. Never upload or paste the private key. Test again with ssh -T git@github.com.

If the repository remote uses HTTPS, keep that authentication flow or deliberately switch it:

git remote set-url origin git@github.com:ORG/REPOSITORY.git

Multiple Git identities

Map each identity to a distinct SSH alias:

Host github-personal
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_personal
  IdentitiesOnly yes

Host github-work
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_work
  IdentitiesOnly yes

Then use the alias:

git remote set-url origin git@github-work:company/repository.git

IdentitiesOnly yes prevents SSH from offering unrelated keys before the serverโ€™s authentication limit is reached.

Coding agents and remote workspaces

A coding agent may run in a container, worktree, VM or remote sandbox. Check whether it sees the same SSH configuration and agent socket as your interactive shell.

Choose one deliberate model:

  1. Forward a constrained agent socket only into a trusted environment.
  2. Use a dedicated bot or app identity scoped to specific repositories.
  3. Use the platformโ€™s short-lived HTTPS token for checkout and pull requests.
  4. Mount a read-only deploy key only when the task truly needs SSH.

Avoid mounting your entire ~/.ssh directory into agent containers. A compromised process may use keys even when it cannot print them.

CI runner fix

First decide whether SSH is necessary. A GitHub Actions workflow can normally use its temporary token with explicit permissions:

permissions:
  contents: read

If a private dependency or deployment target requires SSH, create a dedicated key for that purpose. Store the private half in the CI secret store, register the public half with minimum access, and create known_hosts from a verified source.

Do not disable host verification with StrictHostKeyChecking=no. That converts an authentication repair into a man-in-the-middle risk.

Common failure patterns

The key is accepted but repository access is denied

Authentication to the provider and authorization to a repository are separate. The account or deploy key may lack access to the repository, organization or submodule.

Key permissions are rejected

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub

It works interactively but fails in automation

The process may have a different home directory, no SSH_AUTH_SOCK, another known_hosts, or no secret access. Print paths and fingerprintsโ€”not secret valuesโ€”to diagnose it.

A host key changed

Do not automatically delete the old entry. Verify whether the provider or server legitimately rotated its key and compare the published fingerprint.

Safe access design

  • Give agents a separate, revocable identity.
  • Prefer pull-request creation over direct branch writes.
  • Scope repository and organization permissions narrowly.
  • Keep production SSH credentials separate from source-control credentials.
  • Rotate deploy keys when a runner or integration is retired.
  • Record which identity created each automated commit.

Place this within the Git foundation for coding agents, apply GitHub controls for coding agents, and compare governance in GitHub vs GitLab. For server access, see how SSH works for AI servers and AI Security & Credentials.

Primary documentation