Repository navigation
Description
Problem
SignedArtifact::parsed() (pkgs/id/src/artifact.rs) validates every field of every known kind against an explicit bound — except HomeServer.world_id in a home_declared body. The HOME_DECLARED arm (artifact.rs:334-355) checks the account key, that the author is the account, that there are at most MAX_HOME_SERVERS (8) servers, and that each endpoint parses via check_target (an endpoint ticket or a bare node ID — a tightly bounded format). For world_id it checks only !is_empty() (artifact.rs:350-352).
So a signed home_declared artifact carrying a world_id that is:
- 100,000 bytes long,
- whitespace-only (
" "— non-empty, so it passes), - bearing control characters or a newline,
- or bearing a bidi format character (U+202E),
is accepted by parsed(), stored in the author's artifact chain, and returned verbatim by ArtifactLog::declared() (artifact.rs:519-525) to every consumer. Duplicate servers are accepted too: the same endpoint listed twice, even with two different world_ids, passes — there is no duplicate check.
Every sibling field has a named bound: Document.media_type 1–128 bytes and content ≤ MAX_DOCUMENT_BYTES (artifact.rs:358-368), Tag.name 1–64 bytes and Tag.value ≤ 256 bytes (artifact.rs:376-380), FriendRemove keys checked as canonical account keys (artifact.rs:322-324). world_id is the odd one out in this arm. (The overall 1 MiB frame cap in ArtifactLog::store bounds the total artifact, not this field: a 100 KB world_id fits comfortably inside one frame.)
Evidence (verified this run, main 99ae033)
- Code read:
pkgs/id/src/artifact.rs:346-353— the onlyworld_idcheck isif server.world_id.is_empty().pkgs/id/src/artifact.rs:150-156—HomeServer { endpoint: String, world_id: String }, no other validation anywhere (grep world_idacrosspkgs/id/src: no consumer sanitises it either). - Laptop probe (
probe-2026-10-31-laneA-homeworld/on the laptop under~/git/fleet/, path-dep onpkgs/id,artifact.rssha256bdc11bbe…identical on both clones) driving the realSignedArtifact::sign+parsed():- control
"home"→ ACCEPTED ""→ REFUSED (the one existing check)"home\nFORGED"→ ACCEPTED- control characters (
\u{1},\u{7f}) → ACCEPTED - U+202E bidi → ACCEPTED
" "whitespace-only → ACCEPTED- 100,000-byte
world_id→ ACCEPTED - same endpoint three times (twice with different
world_ids) → ACCEPTED, 3 servers
- control
Why it matters
A home declaration is how an account tells the network where its artifacts live; declared() feeds directory views and home-server selection. An unbounded, unsanitised world_id is stored and propagated exactly as signed — oversized values bloat every chain page that carries the declaration, and control/bidi-bearing values reach any present or future rendering of the declaration unchecked, the same stored-payload class the neighbouring fields' bounds exist to prevent. The duplicate-endpoint case makes the declaration ambiguous: two entries claim the same endpoint holds the account in two different worlds, and nothing downstream disambiguates.
Acceptance criteria
-
parsed()refuses ahome_declaredwhose anyworld_idexceeds a named bound (in line with the sibling fields, e.g. 64 bytes), is whitespace-only, or contains control/format characters — with tests pinning each refusal at theparsed()level. -
parsed()refuses a declaration that names the same endpoint twice (or the triage pins, with a test, why duplicates are harmless and which entry wins). - Ordinary declarations (the existing tests'
"home"/"lobby"world IDs, ≤ 8 distinct endpoints) parse exactly as today. - The bound is named alongside the existing constants in
artifact.rs(MAX_HOME_SERVERS,MAX_DOCUMENT_BYTES, …), not a magic number at the check site.
Triage note: sibling gap, not a duplicate — #3146 covers friend_remove.requests in the same function; this is the home_declared arm's field. Whether the fix also belongs in the design contract of #3068 (parsed-shape contract) is for triage to link.
Activity
dezren39 commentedon Oct 31, 2026
🤖 Agent note · filed
home_declared'sworld_idis the least-checked field inSignedArtifact::parsed()(artifact.rs:350-352, onlyis_empty); verified on main 99ae033 with a laptop probe (probe-2026-10-31-laneA-homeworld, real sign+parsed(), artifact.rs sha256 bdc11bbe on both clones): newline/control/U+202E/whitespace-only and a 100,000-byte world_id all ACCEPTED, empty REFUSED, same endpoint listed 3× ACCEPTED. Sibling of id(artifact): friend_removerequestsis the one known-kind body parsed() never validates — any count, any shape, any length passes, and every string lands permanently in the directory's removed_requests void guard #3146 (friend_remove arm), distinct field. Enqueued as a repo-task/v1 packet on repo-health-code-pilot.dezren39 commentedon Oct 31, 2026
🤖 Design-architect pass 28 (2026-10-31) — agent note: this issue is ADOPTED as a phase of design #3231 ("a signed artifact is validated as strictly as it is built", design doc: files/designs/code-id-artifact-receipt-validation.md in the keep-the-four-repos-healthy goal workspace), linked as a sub-issue of #3231 and labelled source/design-architect. Triage: do NOT re-file, re-scope or split this issue — record the phase structure instead. Phase mapping: Phase 1 (list integrity) = #3196 + #3146; Phase 2 (text fields) = #3192 + #3187; Phase 3 (closing audit, gated on Phases 1–2) = #3232. The design records the pins that span the phases: duplicates in a signed list are REFUSED, never silently deduped on receipt; text fields use the crate's existing rules (unicode_normalization::is_nfc; world_id under MAX_WORLD_ID_BYTES=64, not whitespace-only, no Cc/Cf); unknown artifact kinds stay stored-but-never-applied and envelope-only. Each origin keeps its own acceptance criteria and its already-queued triage packet — no new packet was created for it this pass.
166 remaining items
dezren39 commentedon Nov 4, 2026
🤖 Agent note · picked up
dezren39 commentedon Nov 4, 2026
🤖 Agent note · parked
Merge pull request #4432 from developing-today/queue/5758-3187-home-d…