ADR-044: Supply git credentials through a credential helper rather than persisting them¶
git asks bb for Bitbucket credentials at the moment it needs them, through git's credential helper protocol in bb auth git-credential, and bb never writes a credential into a repository's configuration. bb auth setup-git configures the helper for one host. It resets that host's helper list so bb is the only helper asked, refuses to replace another helper without --force, and writes bb's absolute path and the configuration file it answers from into the helper line, so git authenticates as the login it was set up with. The helper answers only for the host git asks about (ADR-021). It answers with a token as Bearer when git offers the authtype capability, and otherwise beside the username Bitbucket accepts it with over Basic auth: a personal access token's owner's login name, which bb auth login stores, or x-token-auth for a project or repository token. When bb runs git with a credential itself, for a clone or a fetch, the credential is scoped to the host being contacted and passed in the child's environment, which only the owner of the process can read; a command line is readable by every local account. A git too old to read configuration from its environment takes it as an argument instead.
Do not set http.extraHeader, credential.helper store, or a remote URL holding a username and password to make a repository authenticate later. Scope every credential configuration to a host: a bare credential.helper or an unscoped http.extraHeader applies to every host git contacts, and offers a Bitbucket credential to unrelated remotes. When the helper cannot help, it writes nothing to stdout and exits 0, because a non-zero exit makes git treat the lookup as failed rather than fall through to another helper or a prompt; a configuration file it cannot read is said on stderr, which git shows. Write nothing but protocol fields to stdout. Keep store and erase as accepted no-ops, so git cannot write into or clear bb's keyring.
A credential in .git/config is plaintext on disk beside the keyring meant to hold it, travels with every copy and archive of the repository, and never rotates, so revoking the token breaks every clone with an error that reads like a bad token. A helper inverts the arrangement: nothing is stored, the keyring stays the one source, and revoking a token takes effect at once.
Not chosen¶
- Keep persisting http.extraHeader but scope it to the Bitbucket host: Stops the credential reaching other hosts, but it is still a credential in
.git/config. - Embed credentials in the remote URL: Worse than a config entry: the credential appears in .git/config, in the output of git remote -v, and in any error message or log line that echoes the remote.
- Let git store credentials through the helper's store verb: Creates a second writer that silently diverges from what bb auth login recorded, so revoking or replacing a token in the keyring no longer changes what git uses.
- Add bb as a helper without resetting the host's helper list first: credential.
.helper is multi-valued and git consults every configured helper in order. A helper inherited from a broader scope, such as a system credential manager, would still answer first and could return a stale credential. Setting the key to an empty value before adding bb resets the list for that host, as gh auth setup-git does for the same reason.