You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
uuid::Uuid::parse_str, which also takes simple (32 hex, no hyphens), braced, urn:uuid: and uppercase forms
recognizing uv grant URL path segments
Drift that already exists:
An uppercase UUID passes the API client but fails every vendored path.
ABC_1 is a valid archive stem, but fetch_diff rejects it as an "Invalid patch UUID".
The uv grant matcher accepts URL segments that no other site would treat as a UUID.
The manifest loader validates none of these, so which rule applies to a committed uuid depends on which subsystem reads it first.
Impact
The risk is low today, because the API emits canonical lowercase UUIDs. But each new subsystem picks one of the five rules, and the security-relevant path checks (is_canonical_uuid, is_safe_archive_uuid) differ the most.
Proposed change
Add utils::uuid with two functions:
is_patch_uuid(&str) -> bool, the canonical lowercase grammar, moved from path_safety;
looks_like_uuid(&str) -> bool, either case, for user input only (the argv shortcut and get identifier detection).
Delete:
the CLI lib.rs copy (re-export core's);
api::client::is_valid_uuid, replaced by is_patch_uuid;
apply::is_safe_archive_uuid, replaced by is_patch_uuid. This is a tightening, and the matching diff fetch already refuses such UUIDs;
the three Uuid::parse_str calls in python_script.rs, replaced by is_patch_uuid.
path_safety::is_canonical_uuid becomes a re-export, or its callers move to the new name.
Lowercase user input before the API call where get <UUID> accepts uppercase. Keep that in the same PR with a test, or leave it out explicitly.
Size and scope
About 80 production lines removed and 40 added across lib.rs, client.rs, path_safety.rs, apply.rs, python_script.rs and the new utils/uuid.rs. Out of scope: validating uuid at manifest load, which is a contract question.
Acceptance criteria
grep -rn "fn .*uuid.*-> bool" crates/*/src finds only utils/uuid.rs.
One table-driven test covers lowercase, uppercase, no hyphens, braced, urn:uuid:, _ and path separators against both functions.
The existing tests stay green: looks_like_uuid/parse_with_uuid_fallback (CLI), test_is_valid_uuid_* (client, moved), path_safety tests, the archive-stem refusal tests in apply.rs, and the uv python_script grant tests.
A regression test shows that an archive stem ABC_1 is no longer opened.
Dependencies
None. This is independent of C17 (digest helpers), which is filed separately.
[agent] Filed by the scheduled architecture audit routine (CLI and core). Register: discussion #560 register.
Kind: refactor. Source: review 7.3 ("four UUID grammars"); register C18. A fifth grammar has turned up since the review.
Problem (main @
045d7ec)A patch UUID is checked by five independent grammars, and they disagree on case and shape:
looks_like_uuid<UUID>→getrewrite;getidentifier type; rollback hintapi::client::is_valid_uuidfetch_diff, view fetch, and filtering batch results (L1012, L1147, L1246)path_safety::is_canonical_uuid.socket/vendor/<eco>/<uuid>/paths, cargo tags, vlt, go.mod, JVM and the hosted redirectapply::is_safe_archive_uuid[A-Za-z0-9_-]<uuid>.tar.gzarchive stempython_scriptgrant checkuuid::Uuid::parse_str, which also takes simple (32 hex, no hyphens), braced,urn:uuid:and uppercase formsDrift that already exists:
ABC_1is a valid archive stem, butfetch_diffrejects it as an "Invalid patch UUID".The manifest loader validates none of these, so which rule applies to a committed
uuiddepends on which subsystem reads it first.Impact
The risk is low today, because the API emits canonical lowercase UUIDs. But each new subsystem picks one of the five rules, and the security-relevant path checks (
is_canonical_uuid,is_safe_archive_uuid) differ the most.Proposed change
utils::uuidwith two functions:is_patch_uuid(&str) -> bool, the canonical lowercase grammar, moved frompath_safety;looks_like_uuid(&str) -> bool, either case, for user input only (the argv shortcut andgetidentifier detection).lib.rscopy (re-export core's);api::client::is_valid_uuid, replaced byis_patch_uuid;apply::is_safe_archive_uuid, replaced byis_patch_uuid. This is a tightening, and the matching diff fetch already refuses such UUIDs;Uuid::parse_strcalls inpython_script.rs, replaced byis_patch_uuid.path_safety::is_canonical_uuidbecomes a re-export, or its callers move to the new name.get <UUID>accepts uppercase. Keep that in the same PR with a test, or leave it out explicitly.Size and scope
About 80 production lines removed and 40 added across
lib.rs,client.rs,path_safety.rs,apply.rs,python_script.rsand the newutils/uuid.rs. Out of scope: validatinguuidat manifest load, which is a contract question.Acceptance criteria
grep -rn "fn .*uuid.*-> bool" crates/*/srcfinds onlyutils/uuid.rs.urn:uuid:,_and path separators against both functions.looks_like_uuid/parse_with_uuid_fallback(CLI),test_is_valid_uuid_*(client, moved),path_safetytests, the archive-stem refusal tests inapply.rs, and the uvpython_scriptgrant tests.ABC_1is no longer opened.Dependencies
None. This is independent of C17 (digest helpers), which is filed separately.