#55 repo.git leaks unreachable objects (not an exact snapshot)
Adversarial review of #54 found a real information leak: dist/repo.git is not the snapshot it claims to be.
export_dumb_repo runs git clone --bare <repo>, which for a local path uses the local transport: git copies/hardlinks the entire source object database instead of transferring only objects reachable from the selected branch. --single-branch limits refs, not objects.
Verified on this repo:
$ git clone -q -b master http://127.0.0.1:39313/repo.git /tmp/httpclone
$ git -C /tmp/httpclone cat-file -e 0f20352a1fab8155e35e67b32602b90c93dd9d3a && echo PRESENT
PRESENT
$ git -C /tmp/httpclone fsck --no-progress | grep -c dangling
6
git fsck on the published artifact reports 61 dangling objects; a plain HTTP clone inherits 6 unreachable commits, e.g. merge 3c5c330e-… (2026-09-10) which is not on master.
Impact: force-pushed-away commits, deleted branches, amended commits and any blob ever committed become public to anyone who clones and runs git fsck/git cat-file. That includes dropped .forge/ internals. The clone block simultaneously claims "exact snapshot of <branch> @ <sha>", which is false.
Fix: derive repo.git from the bundle snapshot() already writes, i.e. git clone --bare --single-branch --branch <b> <out>/repo.bundle <out>/repo.git (bundle transport negotiates reachable objects only), then update-server-info. Verified on this repo: 0 dangling, 1 pack, 24 files.
Acceptance:
-
exporting a repo that contains unreachable objects yields a clone with
git fsckreporting no dangling objects - malicious-ish fixture: commit a tree, amend it, export -> old commit is NOT in the export
-
tip sha in
repo.gitequals the sha advertised in the clone block (short sharevon index) -
test asserts
git -C <out>/repo.git fsckhas nodanglinglines
Uunknown ·
Fixed in e2792258-fd01-4be6-83ca-c68ef435cfed: export now clones from repo.bundle (one pack, no loose/dangling objects), remote.origin removed, sample hooks removed, single run_git_opt runner with OsStr paths + 120s export budget, content-type anchored to .git/HEAD+info/, docs updated. tests/clone_export.rs asserts all of it.