Skip to content

id(web): clearing the world seed field silently installs with seed 0 — empty input passes the Number() guard in both install and compile flows #707

Closed

Description

@dezren39

Problem

In the id web world page, clearing the World seed field silently installs/compiles the module with seed 0 instead of reporting an error — in both the install and the compile flows.

Evidence (verified on main f7dfea3)

  • The seed input is rendered with a preset value (pkgs/id/src/web/templates.rs:793):
    <input data-world-seed ... type="number" value="1" aria-label="World seed">

  • Both handlers parse it the same way (pkgs/id/web/src/world.ts:342-346 for install, pkgs/id/web/src/world.ts:464-468 for compile):

    const seed = Number(moduleSeed.value);
    if (!Number.isSafeInteger(seed) || seed < 0) {
      setStatus("Seed must be a non-negative safe integer", "error");
      return;
    }
  • Number("") === 0 and Number(" ") === 0 (verified with node), and Number.isSafeInteger(0) is true — so an emptied (or whitespace-only) field passes the guard and the request goes out with seed: 0.

  • The seed is not cosmetic: the host starts the program from init(seed) (pkgs/id/src/world.rs:583), and the install seed is sensitive enough that join projections deliberately zero it (Install seed is readable by every joiner #240, pkgs/id/src/world.rs:820-837). Silently falling back to the predictable seed 0 when the user cleared the field (intending the preset 1, or no seed decision at all) installs a world whose hidden state derives from a seed the admin never chose.

No existing issue covers this: search for seed-related issues returns #240 (seed redaction, closed), #556/#543/#534 (unrelated world features).

Why it matters

  • Silent wrong-value bug: the UI appears to validate the seed (it rejects negatives, fractions and unsafe integers) but misses the most common invalid state — an empty field.
  • The same defect exists in both flows (install and compile), consistent with the duplicated parsing.

Acceptance criteria

  • Clearing the seed field and clicking Install shows "Seed must be a non-negative safe integer" (or an equivalent explicit empty-seed error) and sends no install_begin message.
  • Same for the Compile flow: no compile message is sent with an empty seed.
  • Valid seeds (including an explicit 0 typed by the user) still work in both flows.
  • A regression test covers the empty-seed case (e.g. by extracting the parse into a shared, testable helper used by both handlers — which also removes the duplication).

Suggested fix

Parse from the raw string and reject empty input before conversion, in one shared helper used by both handlers:

function parseSeed(raw: string): number | null {
  const trimmed = raw.trim();
  if (trimmed === "") return null;
  const seed = Number(trimmed);
  return Number.isSafeInteger(seed) && seed >= 0 ? seed : null;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions