Skip to content

receive-pack: empty-pack push skips the connectivity check, refs can end up pointing at objects that don't exist #37

Description

@czk-aa

Pushing a valid but empty pack (32 bytes: PACK header, object count 0, checksum) together with a ref update to a nonexistent oid gets accepted. The server answers ok, the ref is published to the WAL, and from that point on every clone/fetch that walks the ref dies with missing object.

Found this while reading the receive-pack handler, then confirmed against a local server.

Repro (raw HTTP, any write credential):

  1. POST /{o}/{r}.git/git-receive-pack, command area: <40 zero bytes> <any 40-hex oid> refs/heads/ghost\0report-status, then flush
  2. body: a minimal empty pack, 32 bytes total (PACK + version + count=0 + sha1 trailer)
  3. server reports ok refs/heads/ghost; git ls-remote lists it, git clone fails on it

Two things combine here.

First, the connectivity check only runs when a pack was actually ingested:

if let Ok(Some(_)) = &ingest {   // Ok(None) (zero-object pack) skips the whole block

https://github.com/tobi/walgit/blob/6d8fa54/crates/walgit-server/src/smart.rs#L1192-L1218

ingest_pack legitimately returns Ok(None) for an empty pack and git index-pack accepts it happily, so check_connectivity_async never runs for these pushes.

Second, verify_txn on the publish side only compares old_oid for the optimistic lock and never checks that new_oid exists anywhere:

https://github.com/tobi/walgit/blob/6d8fa54/crates/walgit-wal/src/publish.rs#L329-L363

So there is no backstop either.

Fix direction: run the existence/connectivity check whenever any update has a non-zero new_oid, not only when a pack was ingested. For Ok(None) pushes the objects are supposed to be local already, so it's a handful of index lookups and the malicious case fails fast. Alternatively (or additionally) a has_object check on non-zero new_oid inside verify_txn as a last-line defense.

Happy to put up a patch with a regression test if this sounds right — something like push_with_empty_pack_cannot_create_ref_to_missing_object in tests/e2e.rs.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions