@@ 249,7 249,7 @@ with parts in square brackets being optional, and where
Otherwise, `<VERSION>` may be the object name (hash) of a Git commit in the site's history, encoded as a string of hexadecimal digits (case-insensitive), in which case the URI refers to that commit. The name may be shortened by removing characters from its end, but this may cause content retrieval to fail if the client's Git clone of the site contains several commits with that same shortened name.
- `<VERSION>` may also be the name of a Git tag or branch in the client's Git clone of the site, percent-encoded if it contains reserved characters (as per Sections 2.1 and 2.2 of RFC3986). In that case the URI refers to the commit pointed by the tag or the branch head in the client's clone of the site.
+ `<VERSION>` may also be the name of a Git tag or branch in the client's Git clone of the site, percent-encoded if it contains reserved characters (as per Sections 2.1 and 2.2 of RFC3986). In that case the URI refers to the commit pointed by the tag or the branch head in the client's clone of the site. For security reasons (see further below), such tag or branch names MUST NOT consist only of hexadecimal digits (lower or upper case).
A tag signed by the site key may be used to succinctly convey a relevant point in the history of a site (like a release name). In contrast, branches and unsigned tags cannot be authenticated and their names may vary between clients, thus URIs using them SHOULD NOT be published in the general case, though gwit clients MAY support them as they can be useful for local debugging or internal site authoring.
- `<PATH>` is the absolute path of a file or directory in the site version referenced by the previous parts of the URI. The root of the path is the site's root directory (as per site configuration) in the Git commit corresponding to the desired site version, so the path maps to a Git blob object or tree object reachable from it.
@@ 328,7 328,7 @@ The client MUST then establish which Git commit `<COMMIT>` to use, according to
2. Else, if `<VERSION>` matches the format of a SHA-1 or SHA-256 hash (40 or 64 hexadecimal digits, lower or upper case), use it as `<COMMIT>`. This is the case for a permanent link.
3. Else, if `<VERSION>` consists only of hexadecimal digits (lower or upper case), check that there is neither tag nor branch with that name (e.g. `git show-ref --tags --heads <VERSION>` reports nothing), then check that it is the prefix of a single commit object, and use its complete name as `<COMMIT>` (e.g. `git rev-parse --verify <VERSION>^{commit}` only reports the `<COMMIT>`).
- **Note:** The check for tags or branches named after `<VERSION>` prevents an attacker from using such a named reference in their public clone to confuse other gwit clients which try to access a URI with a certain abbreviated commit name version, and tricking them into accessing a different commit. Shall the check fail, the client SHOULD report the situation as a potential attack (e.g. to help neutralize the problematic references or remotes). As a side effect of this check, tag and branch names which are to be used in gwit URIs MUST NOT consist only of hexadecimal digits (lower or upper case).
+ **Note:** The check for tags or branches named after `<VERSION>` prevents an attacker from using such a named reference in their public clone to confuse other gwit clients which try to access a URI with a certain abbreviated commit name version, and tricking them into accessing a different commit. Shall the check fail, the client SHOULD report the situation as a potential attack (e.g. to help neutralize the problematic references or remotes). This security check is the reason why tag and branch names which are to be used in gwit URIs MUST NOT consist only of hexadecimal digits (lower or upper case).
4. Else, if `<VERSION>` names a signed tag (e.g. `git cat-file -t <VERSION>` reports `tag`), check that the name in the tag object matches `<VERSION>`, that it does refer to a commit, and get the name of that commit as `<COMMIT>` (e.g. `git tag -l --format='%(objecttype) %(tag) %(*objecttype) %(*objectname)' <VERSION>` reports `tag <VERSION> commit <COMMIT>`), then check that the tag itself has a valid signature by the key that matches `<SITE-ID>` (case-insensitively), or by a subkey of it (e.g. `git verify-tag --raw <VERSION> 2>&1 | sed -nE 's/^\[GNUPG:\] VALIDSIG .*\b(\S+)$/\1/p'` reports `<SITE-ID>`).
**Note:** The check for the name in the tag prevents an attacker from using a reference in their public clone with a name that tricks another gwit client into believing that it is accessing that signed tag, when in fact a different one (though still existing and valid) is being accessed (e.g. by making `v1.0` refer to a valid signed tag object containing the name `v0.9`). Shall the check fail, the client SHOULD report the situation as a potential attack (e.g. to help neutralize the problematic references or remotes).