Git, CI/CD & GitOpsXXVI · Git ConfigurationGitConfig
Credential helpers and secure storage — what each one stores, where, and at what risk
What you'll learn
- Explain how credential.helper delegates password retrieval to an external program
- Compare the security properties of cache, store, osxkeychain, wincred, manager, and libsecret
- Recognise the security trade-off between plaintext storage and OS-provided secure storage
- Choose the right helper for a workstation, a shared runner, and a CI job
Prerequisites
Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x
credential.helper names a program Git invokes to fetch, store,
or erase credentials for an HTTP or HTTPS remote. Git ships with
several helpers and supports third-party ones; each helper
implements the same protocol but stores the credential in a
different place. The choice of helper is the choice of where the
credential lives, and where the credential lives is the choice
of who can read it.
The credential-helper protocol
A credential helper is a program. Git invokes it with a verb
(get, store, erase) on the command line and writes a list
of key-value lines to the helper’s stdin:
protocol=https
host=github.com
username=alice
The helper reads the lines, looks up (or stores, or erases) a matching credential, and writes the result to stdout in the same format. Git then uses the returned credential to authenticate the next HTTPS request. This protocol is what every helper implements; the difference between helpers is the backend.
flowchart LR
A["git push"] --> B{"need credential?"}
B -->|no| C["push proceeds"]
B -->|yes| D["git invokes helper 'get'"]
D --> E{"helper backend"}
E -->|cache| F["in-memory for N seconds"]
E -->|store| G["plaintext file on disk"]
E -->|osxkeychain| H["macOS Keychain"]
E -->|wincred| I["Windows Credential Manager"]
E -->|manager| J["cross-platform secure store"]
E -->|libsecret| K["Linux Secret Service (GNOME Keyring)"]
F --> L["credential returned"]
G --> L
H --> L
I --> L
J --> L
K --> L
L --> M["git uses credential"]
The built-in helpers
Git’s source tree includes several helpers, each with a different backend and a different threat model:
cachekeeps credentials in memory for a configurable timeout (default 900 seconds). The credential never touches disk. The risk is that the memory is the process’s memory; a core dump or a debugger attach can read it. Use cache on a developer workstation where the threat is “the credential sits in~/.git-credentialsfor years” and the gain is “the credential disappears when I reboot”.storewrites credentials to a plaintext file (typically~/.git-credentials). The file is the credential. The risk is the file: any process running as the user can read it, any backup copies it, any disk image contains it. Store is the helper that produces “credentials on a USB stick” incidents.osxkeychain(macOS) stores credentials in the user’s login keychain. The keychain is encrypted at rest with the user’s login password and is unlocked when the user logs in. The risk is the keychain’s threat model: any process running as the user can request the credential without re-authenticating.wincred(Windows) stores credentials in the Windows Credential Manager. The Credential Manager is encrypted with the user’s profile keys. The risk is similar to macOS Keychain.manageris Git Credential Manager (GCM), a Microsoft- maintained cross-platform helper. It uses the platform’s secure store (Keychain on macOS, Credential Manager on Windows, Secret Service on Linux) and adds features like multi-factor authentication prompts and Azure DevOps integration.libsecret(Linux) stores credentials in the GNOME Keyring or KDE Wallet via the Secret Service D-Bus API. The keyring is encrypted with the user’s login password. The risk is that the keyring must be unlocked for the helper to read, which on some Linux distributions means the keyring is not unlocked at all for headless sessions.
git config --global credential.helper cache --timeout=3600
git config --global credential.helper osxkeychain
git config --global credential.helper manager
git config --global credential.helper libsecret
git config --global credential.helper store
The first three are workstation-appropriate. The fourth is the Linux headless fallback and often fails silently. The fifth is plaintext and should be treated as a credential leak waiting to happen.
Choosing a helper
The right helper depends on the deployment:
- Developer workstation (macOS, Windows, modern Linux): use
manager(GCM) or the platform-native helper. The credential is encrypted at rest, the user gets prompts for new hosts, and the helper handles MFA correctly. - Headless Linux server with a logged-in user: use
libsecretif a keyring is configured and unlocked, orcache --timeout=...if the threat model is “the credential is short-lived”. Never usestore. - CI runner: use short-lived tokens injected by the runner
(
GITHUB_TOKEN,GITLAB_TOKEN, deployment keys) and a helper likecachethat holds them for the duration of the job. Never persist a credential to disk on a shared runner. - Production deploy host: use SSH keys with
~/.ssh/configand the SSH agent, not HTTPS credentials at all. SSH keys with a passphrase and an agent are the most operationally simple secure option for machine-to-machine Git access.
The wrong helper is whichever one writes the credential to a
file that outlives the credential’s lifetime. For most
deployments that means avoiding store and avoiding any helper
whose backend is a plaintext file.
Multiple helpers
credential.helper accepts multiple values; Git tries them in
order. The pattern is to put the most-secure helper first and
fall back to a less-secure one:
git config --global credential.helper manager
git config --global credential.helper cache --timeout=3600
GCM handles the credentials it knows about; anything GCM cannot
resolve falls through to cache, which holds the credential for
one hour. The fallback is the explicit acknowledgement that no
helper covers every case, and that an in-memory fallback is
better than an interactive password prompt for the duration of
a deploy.
Production discipline
- Use a secure-store helper on every workstation.
osxkeychain,wincred,manager, orlibsecret- neverstore. - Use short-lived tokens on every CI runner. A token that expires in 60 minutes is a token that does not need to be persisted; the runner configures the helper for the duration of the job and lets the helper forget.
- Treat
~/.git-credentialsas a credential leak. If a machine has ever runstore, the file should be deleted and every credential it ever contained should be considered compromised. - Use SSH keys for machine-to-machine Git. The SSH agent with passphrase-protected keys is the most operationally simple secure option for production deploy hosts and shared runners.
- Audit the helper list. A surprising helper on a shared
runner is a surprising security posture;
git config --list --show-origin | grep credentialis the right diagnostic.
Quiz
Knowledge check · 4 questions
Q1. An engineer runs `git config --global credential.helper store` on a workstation. Where does the credential live after the engineer authenticates once?
Q2. Multiple credential helpers can be configured at the same scope; Git tries them in the order they were declared and falls through to the next helper if the current one returns no credential.
Q3. Name the four production-grade credential helpers and the platform or situation each one is the right choice for.
Q4. Diagnose a credential leak on a shared runner that has been using the `store` helper, and recommend a remediation that does not require a runner rebuild.
A shared CI runner has been using `credential.helper=store` for two years. A backup of the runner's home directory was exfiltrated by a separate incident and contains `~/.git-credentials` with the runner's deploy token for the production remote. The team needs to contain the leak, switch the helper, and prevent recurrence without rebuilding the runner from scratch.
Passing score: 75%. Answers are checked in this browser.