.forge/issues/50c21acd-1a7e-4e98-84e9-f1d07e647641/issue.md 2.0 KiB 36 lines Raw

id: 50c21acd-1a7e-4e98-84e9-f1d07e647641 title: repo.git leaks unreachable objects (not an exact snapshot) state: closed labels:


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:

view raw