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
{{ message }}
Repository navigation
id(world-manifest): an empty module_hash passes validation — parse accepts "" and plan/apply install it, contradicting validate's own '1 to 64 hex digits' rule #1517
WorldManifest::validate accepts an emptymodule_hash, even though its own error message says the hash "must be 1 to 64 hex digits". A manifest with module_hash = "" parses cleanly, plan() then emits an InstallModule step carrying the empty hash, and the pure apply() installs it into the state — the bad value is only ever caught (if at all) downstream at the server, far from the typo that caused it.
ifletSome(hash) = &self.module_hash{let valid = hash.len() <= MAX_NAME_BYTES && hash.bytes().all(|b| b.is_ascii_hexdigit());ensure!(valid,"module hash must be 1 to {MAX_NAME_BYTES} hex digits");}
"".len() <= 64 is true and all() on an empty iterator is true, so the lower bound in the message is never enforced. Every sibling validator in pkgs/id/src/world_caps.rs does enforce it — e.g. :248!spec.is_empty() && spec.len() <= MAX_NAME_BYTES, :274, :278 — the manifest hash check is the outlier.
Probe (crate on the laptop compiling the verbatimworld_manifest.rs sha256 234f1dfc… + world_caps.rs sha256 679a2c25…, identical sandbox↔laptop; log hidden_files/probe-2026-10-27-laneB-manifest/out.log):
control parse("module_hash = \"not-hex!\"") → Err("module hash must be 1 to 64 hex digits")
control parse("module_hash = \"abc123\"") → OK
plan() for the empty-hash manifest against a default state → [InstallModule { hash: Some(""), source: None, seed: 0 }], and apply() sets state.module_hash = Some("")
Why it matters
world.toml is the declarative admin interface for a world (id world apply / diff). Validation at parse() is the one place every bad manifest is supposed to die with a precise, field-naming error. An empty hash slipping through turns a one-character typo into a confusing downstream install failure (or a state whose module hash is the empty string), and the error text actively misleads: it claims a 1-digit minimum that the code does not check.
Acceptance criteria
parse("module_hash = \"\"") fails with the existing "module hash must be 1 to {MAX_NAME_BYTES} hex digits" error
Non-empty hex hashes (1..=64 digits) still parse; non-hex and >64-digit hashes still fail
A regression test joins validation_rejects_unknown_names_and_bad_hashes in world_manifest.rs covering the empty hash
cargo test for the world_manifest module passes; no other validation behaviour changes
Task: Guarded trivial self-solve (§4): add the missing empty-hash rejection to WorldManifest::validate plus a regression test, branch creator-b/1517-empty-module-hash, PR, merge when verified.
Expectation: effort xs; done = parse("module_hash = """) errors with the existing message, world_manifest tests green on the laptop, PR merged.
Task: Self-solve complete. PR fix(id): reject an empty module_hash in world manifests (#1517) #1527 merged (merge commit 357feb2; fix commit 8b5c4bc): WorldManifest::validate now rejects an empty module_hash with the existing "1 to 64 hex digits" message, plus a regression assertion in validation_rejects_unknown_names_and_bad_hashes.
Expectation: met — verified on the laptop: probe crate with the patched verbatim file flips CASE1 to Err with controls unchanged, and the real crate's cargo test --lib world_manifest passes 11/11; rustfmt clean. PR CI checks were still pending (not started) at merge time; merged under the standing directive on the strength of the local verification.
Activity
developing-today commentedon Oct 27, 2026
CODE-578
dezren39 commentedon Oct 27, 2026
🤖 Agent note · picked up
Merge pull request #1527 from developing-today/creator-b/1517-empty-m…
dezren39 commentedon Oct 27, 2026
🤖 Agent note · done
WorldManifest::validatenow rejects an emptymodule_hashwith the existing "1 to 64 hex digits" message, plus a regression assertion invalidation_rejects_unknown_names_and_bad_hashes.cargo test --lib world_manifestpasses 11/11; rustfmt clean. PR CI checks were still pending (not started) at merge time; merged under the standing directive on the strength of the local verification.