Skip to content

id(list/find): blob-name TSV output renders names raw — a newline in a remote node's blob name forges extra rows in id list and id find, and a tab forges columns #1742

Closed

Description

@dezren39

Problem

The blob-name plain-text renderers in pkgs/id print stored names raw in a tab-separated, one-row-per-item format. A blob name containing a newline forges extra rows, and a tab forges extra columns — the same row-forgery class fixed for claim/doc/group in #1611 (merged in #1703) and filed separately for peers (#1613) and meta-tags (#1735), but never filed for the blob list/find renderers.

Evidence (verified this run on main 0e245370)

  • Name storage accepts the characters: src/fileops.rs:170-178 — FileOps::put rejects only a name that is empty after trim; a name containing \n or \t is stored as the blob's tag verbatim.
  • Server pass-through: src/protocol.rs:556-562 — the MetaRequest::List handler copies each tag name with String::from_utf8_lossy into MetaResponse::List items with no escaping or validation.
  • id list renders raw in all three modes:
    • src/commands/list.rs:91 (via local serve): println!("{hash}\t{name}")
    • src/commands/list.rs:110 (direct store): println!("{}\t{}", item.hash, name)
    • src/commands/list.rs:157 (remote node): println!("{hash}\t{name}") — this is the attacker-controlled case: listing a remote node's store prints that node's names.
  • REPL list renders raw the same way: src/commands/repl.rs:439 (serve) and src/commands/repl.rs:452 (local).
  • id find renders raw: src/helpers.rs:158-166 (print_match_cli), src/helpers.rs:190-220 (print_matches_cli, including the [query] group header), and src/helpers.rs:246-257 (print_match_repl) interpolate m.name (and the query) with \t separators and no quoting. Find matches against a remote node carry that node's names.

So a node that stores a blob under the name x\n<64-hex>\tfake.txt makes every client that runs id list <that-node> or a remote id find print a forged row that is indistinguishable from a real <hash>\t<name> row — a script parsing the output (the documented format, src/commands/list.rs:8-15) reads a hash/name pair the listing node never had.

Why it matters

id list / id find output is the machine-readable surface other tools and scripts parse. Row forgery by a remote (or merely careless) naming node corrupts inventories, can point a downstream id get at a name/hash pairing that does not exist on the listing node, and breaks the one-row-per-item invariant the rest of the fleet's plain-text output now guarantees after #1611/#1703.

Acceptance criteria

Dedup

Searched open + recently closed issues for list/find/helpers TSV, newline and forgery terms. #1611/#1703 covered only the shared tokens() renderer in claim/doc/group; #1613 is peers/gossip; #1735 is commands/tag.rs meta-tag rows. The blob-name renderers in commands/list.rs, commands/repl.rs, and helpers.rs are not covered by any of them.

Activity

  1. developing-today commented on Oct 28, 2026

    @developing-today
    Contributor
  2. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    task/triageQueue packet kind: verify, reproduce, and route this item
    source/creatorFiled by the new-issue-creator job
    priority/normalOrdinary priority (the default)
    queue/queuedHas a queued task in the Supabase agent queue
    app/idPackage/app: id (pkgs/ or apps/ in this repo)
    effort/sSmall: expected under 2 hours of work
    on Oct 28, 2026
  3. dezren39 commented on Oct 28, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

    • Agent: new-issue-creator (new-issue-creator-code-a)
    • Session / ID: cron job new-issue-creator-code-a, run 2026-10-28T17:11:57Z
    • Found via: filed this run
    • Task: Filed this issue — blob-name TSV renderers in commands/list.rs, commands/repl.rs and helpers.rs print stored/remote names raw; quoting fix queued for triage.
    • Expectation: effort/s — done when the acceptance criteria in the issue body hold (one physical line per row, no forged columns, byte-identical rendering for plain names).
    • Links: queue packet repo-health-code-pilot (repo-task/v1, dedupe key repo-health:v1:triage:developing-today/code:issue:1742)
  4. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 1, 2026
  5. 18 remaining items

  6. added
    queue/claimedQueue worker lifecycle state
    and removed
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 1, 2026
  7. dezren39 commented on Nov 1, 2026

    @dezren39
    MemberAuthor

    Picked up by lane E worker shift — resuming task 4792. Branch queue/4792-1742-quote-blob-rendering at b46c0d536 is pushed; no PR yet. Previous shift parked because targeted cargo tests failed to compile on pre-existing errors in pkgs/id/src/repl/runner.rs (a file this branch does not modify). This shift revalidates that baseline blocker against current main, then runs the focused tests and opens the PR.

  8. added 2 commits that reference this issue on Nov 1, 2026
  9. dezren39 commented on Nov 1, 2026

    @dezren39
    MemberAuthor

    Done — task 4792 complete. PR #3763 merged (dee3cb93d); issue #1742 closed.

    Verification: pkgs/id lib suite 1674 passed. The new CLI quoting test initially failed on its own setup — a lone path:name put argument is auto-detected as a stdin blob name, so parse_put_spec never ran — fixed the test to take the multi-item put path; it now passes and genuinely covers the quoting. One unrelated failure recorded: serve_tests::test_world_module_shared_over_iroh_and_web_presentations times out on server startup (30s) under current laptop load; it does not touch this diff's surface (list/find output quoting).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/idPackage/app: id (pkgs/ or apps/ in this repo)effort/sSmall: expected under 2 hours of workkind/bugSomething isn't working (prefixed form of the classic bug label)priority/normalOrdinary priority (the default)source/creatorFiled by the new-issue-creator jobstatus:done

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions