Skip to content

Validate patch UUIDs through one utils::uuid grammar instead of five #705

Description

[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:

Site Accepts Used for
CLI looks_like_uuid 8-4-4-4-12 hex, either case argv <UUID> → get rewrite; get identifier type; rollback hint
core api::client::is_valid_uuid the same grammar, as a near byte-identical copy fetch_diff, view fetch, and filtering batch results (L1012, L1147, L1246)
path_safety::is_canonical_uuid 36 characters, lowercase only the vendored .socket/vendor/<eco>/<uuid>/ paths, cargo tags, vlt, go.mod, JVM and the hosted redirect
apply::is_safe_archive_uuid any non-empty run of [A-Za-z0-9_-] the agent-mode <uuid>.tar.gz archive stem
python_script grant check 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.

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

    agent:triagedarch-auditFiled by a scheduled architecture audit routine (see the architecture review discussion)priority:p3refactorStructural change: duplicated code or logic, missing abstraction, layering, dead code

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions