git: ssh and ssh-only mode are ignored by six credential-bearing git legs #535
Labels
No labels
breaking
bug
documentation
enhancement
epic
good first issue
help wanted
refactoring
resolution/duplicate
resolution/invalid
resolution/wontfix
security
severity/critical
severity/high
severity/low
severity/medium
status/abandoned
status/blocked
status/needs-decision
status/needs-info
status/needs-verification
testing
upstream
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Blocks
#527 git: replace the 17 Run* variants with one call that takes options
sixfold-space/madtea
Reference
sixfold-space/madtea#535
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What happens
--git-protocoloffers three modes:https(token plus HTTPS git, the default),ssh(token plus SSH git), andssh-only(SSH git, no token stored or required).Six git legs that contact a remote do not honour
sshorssh-only:internal/service/prune/run.go:345fetch --pruneinternal/cmd/pr/checkout.go:46fetch origininternal/cmd/pr/conflicts.go:67fetch origininternal/cmd/git/tag.go:194push origin <tag>internal/service/issue/develop.go:116push -u origin <branch>internal/mcp/tools_prs_content.go:218fetch originIn
sshmode these use the token over HTTPS, against the mode the user chose. Inssh-only, where no token is stored, they try to resolve credentials and fail, so those six commands do not work in that mode.pull,fetch, and the legsfinishdrives do honour the mode. So whether the user's transport choice is respected depends on which command they run.This is read from the source. I have not yet reproduced it against a live forge.
Where the inconsistency lives
internal/githas five places that build a credential-bearing command throughsetupAuthCmd. Three of them check the transport first, two do not:internal/git/auth.go:224RunGitAuthDirWithCredentials:254RunGitAuthPassthrough:240:295RunGitAuthDirCaptureStderr:287:323RunGitAuthDirCaptureStderrOnly:375RunGitAuthDirWithStderr:359RunGitAuthdelegates to:224, so every caller ofRunGitAuthinherits the miss.cloneis a separate case worth noting: the dispatch resolves the SSH remote by readingremote get-url origin, and during a clone no origin exists yet.This is the third occurrence
The header of
internal/git/auth_ssh_dispatch_test.gorecords the earlier two rounds. The dispatch first covered only the push chokepoint andRunGitAuthDirWithStderr. Two further legs thatfinishdrives were later found on the HTTPS path and fixed. Each round fixed the cases someone noticed at the time.No decision record covers this
There is no ADR for git transport selection.
0013covers credential storage, secure backend against plaintext.0025covers forge resolution and host-keyed credentials. Nothing indocs/decisions/mentionsgit-protocol,ssh-only, or #294.So the three modes exist in the code, in a CLI flag, in
docs/CLAIMS.mdclaim 26, and inCOMPAT.md, with no record stating what they guarantee. Claim 26 covers API surfaces only; its test does not reach the git transport legs. Each past fix was therefore made against no written contract, which is worth weighing when deciding how to close this.Acceptance
Stated as behaviour, so the shape of the fix stays open:
sshandssh-only, each of the six legs above reaches the remote over the SSH remote form, with noGIT_ASKPASSand no token on the wire.ssh-onlythose six commands work rather than failing on missing credentials.httpsand unset mode are unchanged: askpass injected, no URL override.cloneends up doing is deliberate and commented, not a side effect.Related: #294 (the original SSH transport work) and #527 (collapsing the
Run*variants), which touches the same code.