Private submodule authentication (token or ssh-key) in CI
By Kaveh Alemi·Latchkey
A private submodule needs its own credential. actions/checkout can fetch submodules only if the token (for HTTPS) or ssh-key (for SSH) it holds can read that submodule repository. The default GITHUB_TOKEN cannot read a different private repo.
What this error means
Submodule update fails with an auth error ("could not read Username" for HTTPS, or "Permission denied (publickey)" for SSH) even though the parent repo cloned successfully.
git
Submodule 'vendor/shared' (https://github.com/acme/shared.git) registered for path 'vendor/shared'
fatal: could not read Username for 'https://github.com': terminal prompts disabled
fatal: clone of 'https://github.com/acme/shared.git' into submodule path 'vendor/shared' failed
Diagnose it: depth, refs, or credentials?
Terminal
git rev-parse --is-shallow-repository
git rev-parse --abbrev-ref HEAD # prints HEAD when detached
git log --oneline -3
git remote -v
Common causes
The default token is scoped to the parent repo only
GITHUB_TOKEN authenticates the current repository. A submodule in a different private repo is outside its scope, so the fetch is unauthenticated.
The submodule URL style does not match the credential
An HTTPS submodule needs a token; an SSH submodule needs a key. Providing the wrong one leaves the fetch unauthenticated.
How to fix it
Give checkout a credential that covers the submodule (HTTPS token)
Provision a token or deploy key that can read every private submodule.
Keep all submodule URLs one style so a single credential covers them.
Use submodules: recursive to fetch nested submodules in one pass.
Frequently asked questions
What causes Private submodule authentication (token or ssh-key) in CI?
There are 2 common causes: the default token is scoped to the parent repo only and the submodule url style does not match the credential. GITHUB_TOKEN authenticates the current repository.
How do I fix Private submodule authentication (token or ssh-key) in CI?
There are 2 fixes depending on which cause you have: give checkout a credential that covers the submodule (https token) and or use a deploy key and url rewrite for ssh submodules. Work through them in order, since the first is the most common.
What does Private submodule authentication (token or ssh-key) in CI actually mean?
Submodule update fails with an auth error ("could not read Username" for HTTPS, or "Permission denied (publickey)" for SSH) even though the parent repo cloned successfully.
How do I stop Private submodule authentication (token or ssh-key) in CI happening again?
Provision a token or deploy key that can read every private submodule. The prevention section lists 3 changes that keep it from recurring.