Skip to content
zit Erratum — draft-fossil-sync-protocol-00 §7.3
Login

Erratum — draft-fossil-sync-protocol-00 §7.3

Document draft-fossil-sync-protocol-00
Section 7.3 — Unversioned Files (server handling of uvgimme); cross-references §3.3 and §9.2
Type Technical (the requirement changes: a permission condition is added)
Status Proposed — tracks a fossil change adding the same Read check to page_xfer()
Reported 2026-10-11
Submitter Dan Mestas
Found via go-libfossil's sync conformance suite; reproduced on fossil 2.28 [52445a27f1] and 2.29 trunk [b0fad57ecb]

1. Summary

§7.3 tells a server to answer every syntactically valid uvgimme NAME with the file, and says the request "has no received-write-capability requirement". It sets no Read condition either. That copies the reference implementation, whose uvgimme handler is the only way to read unversioned content that does not check Read: the /uv and /uvlist pages, the unversioned catalog (§9.2 already says "with Read permission"), and gimme for ordinary artifacts all do. As written, a server that follows the draft sends any unversioned file to a requester with no capabilities at all, on a repository that denies anonymous read, provided the requester knows or guesses the file's name.

The correction adds the Read condition, and specifies the refusal the way §3.3 already specifies it for gimme: emit neither content nor error.

2. Location

For comparison, unchanged:

3. The hazard

A legitimate client only sends uvgimme for names it learned from the catalog, and §9.2 already withholds the catalog from a requester without Read. So the missing condition never shows up in an ordinary exchange: a stock client without Read gets no catalog and never asks. It shows up only when a request names a file directly. On fossil 2.28 and on 2.29 trunk, with every capability removed from nobody, anonymous, reader and developer, this request

pragma client-version 22800 20260311 113146
uvgimme secret.txt

is answered with the full uvfile secret.txt ... 33 0 card and the file's content, while pragma uv-hash, a gimme for the same content, and GET /uv/secret.txt all refuse the same requester.

4. Impact

Wire-visible, and a confidentiality issue. A server implementing §7.3 as written discloses unversioned content (release files, download pages, anything stored with fossil uv add) of a private repository to anyone who can reach its sync URL. Public repositories are unaffected: what uvgimme returns there, /uv/ already serves.

5. Correction

In §7.3, replace the first sentence about server-received uvgimme and the paragraph's last sentence:

-   changes invalidate cached catalog hash.  On a syntactically valid
-   server-received uvgimme NAME, the server MUST look up NAME.  If NAME
-   is absent, it emits no card.
+   changes invalidate cached catalog hash.  On a syntactically valid
+   server-received uvgimme NAME from a requester with Read permission,
+   the server MUST look up NAME.  Without Read permission, the server
+   emits neither content nor error for the card, as for a gimme whose
+   direction forbids sending (Section 3.3); the catalog is withheld
+   from the same requester (Section 9.2).  For this check, Clone
+   permission implies Read.  If NAME is absent, it emits no card.
-   SIZE 0, and FLAGS 1.  This request reads server state and has no
-   received-write-capability requirement.
+   SIZE 0, and FLAGS 1.  This request reads server state: it requires
+   Read permission, as the catalog does, and has no UV write
+   requirement.

6. Rationale

7. Application and verification

The patch also applies cleanly to 2.28, where a Clone-only principal already receives no catalog.


Prepared against draft-fossil-sync-protocol-00. The section is faithful to the reference implementation as it stood; the correction follows the implementation's intended behavior once the matching fix lands. The RFC remains the oracle; the reference implementation is used only to confirm the observable behavior, per the interop-verification policy.