Skip to content

CX2 [CRIT]: repo rename was clobbering unrelated CWD origins#2

Merged
mfwolffe merged 2 commits into
trunkfrom
cx2/rename-origin-guard
May 17, 2026
Merged

CX2 [CRIT]: repo rename was clobbering unrelated CWD origins#2
mfwolffe merged 2 commits into
trunkfrom
cx2/rename-origin-guard

Conversation

@espadonne
Copy link
Copy Markdown
Contributor

Summary

Data-loss-adjacent CRIT bug. Running shithub repo rename foo -R owner/bar from inside any git working tree with an origin remote silently overwrote that origin to point at owner/bar, regardless of whether the CWD's origin had anything to do with the repo being renamed.

Discovered by the C-audit subagent: its scratch-repo flow mutated ~/GithubOrgs/.../shithub-cli/.git/config while it ran, pointing my local origin from git@github.com:tenseleyFlow/shithub-cli.git to https://shithub.sh/mfwolffe/cli-audit-1779046542-a.git. The auditor's findings doc (C7) recorded the symptom on its scratch end (Updated origin -> <old name> after a server-side no-op rename) but didn't connect it to host-side state corruption.

Reproducer (pre-fix, clobbers origin):

mkdir /tmp/repro && cd /tmp/repro && git init -q -b trunk
git remote add origin git@example.com:other/unrelated.git
shithub repo create my-scratch --public --add-readme
shithub repo rename anything -R mfwolffe/my-scratch --yes
git remote get-url origin
# → https://shithub.sh/mfwolffe/my-scratch.git   ← CLOBBERED

Post-fix output:

note: origin not updated; this directory's origin points at other/unrelated, not mfwolffe/my-scratch

Fix

In pkg/cmd/repo/rename/rename.go, before calling SetRemoteURL, resolve the CWD's current origin and verify it points at the same owner/name we just renamed (case-insensitive). On mismatch, print a note: line explaining we skipped the rotation. Existing "origin matches → rotate" path is preserved.

Test plan

  • TestRenameDoesNotClobberUnrelatedOrigin — regression test: real git tree with git@example.com:other/unrelated.git origin survives o/old → o/newname rename, stderr explains.
  • TestRenameRotatesMatchingOrigin — happy path: tree with origin matching o/old correctly rotates to o/newname.
  • Existing TestRenamePatchesName + TestRenameRejectsSameName still pass.
  • make ci green locally.
  • End-to-end re-repro against live shithub.sh confirms unrelated origin survives (see above).

Notes for follow-up

This PR fixes the bug; it does NOT add the broader protection that should also exist:

  • pr checkout adds a remote named after the fork owner in the CWD (line 213) — safer because it doesn't clobber origin, but still mutates .git/config of whatever tree the user ran the command in. Worth a separate audit.
  • Server-side C7 (repo rename returning 200 unchanged on invalid names) is still open in the D1 server-side sub-sprint.

@mfwolffe mfwolffe merged commit e677ef2 into trunk May 17, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants