Skip to content

gl quickstart reports "Registered successfully / UCAN saved" on a non-JSON 200, and over a stale token from another node #355

Description

@beardthelion

quickstart.rs:100-115 parses lossily and then prints success unconditionally:

let payload: Value = resp.json().await.unwrap_or_default();   // :100  non-JSON -> Value::Null
let ucan = payload["ucan"].as_str().unwrap_or("");            // :101
if !ucan.is_empty() { ... std::fs::write(&ucan_path, ...)?; } // :102-111  write is guarded
println!("  ✓  Registered successfully");
println!("     UCAN saved to {}", ucan_path.display());       // :115  print is not

The write is inside the guard and the message is outside it. unwrap_or_default() at line 100 is what
makes this reachable in practice: quickstart cannot tell "a node answered JSON without a UCAN" from
"this 200 was not JSON at all".

Three variants, all driven against local stubs:

200, "ucan" omitted    ->  ✓ Registered successfully / UCAN saved to <path>   no file written
200, text/html body    ->  ✓ Registered successfully / UCAN saved to <path>   no file written
pre-existing ucan.json for node "https://other.example", then quickstart:
                       ->  ✓ Registered successfully / UCAN saved to <path>
   cat ucan.json after ->  {"ucan":"OLD.TOKEN.forOtherNode","node":"https://other.example",...}

The third is the one that leaves bad state rather than merely misinforming. quickstart.rs:79-88
computes already_registered as false when an existing ucan.json names a different node, so control
falls into the register branch, writes nothing, and announces a save over a file still holding the
other node's token. gl doctor then reports the user registered with https://other.example, and
later commands pick up the wrong token.

This is the first-run wizard, which is the worst place for a false success: registration failure is
deliberately non-fatal (:125 "Non-fatal, continue"), so the run proceeds to create a repo and ends
on "You're set up on gitlawb."

Sibling site

register.rs:70-103 has the same guard/print split. It is milder and I would fold it into the same
fix rather than file it separately: the write is guarded identically, but register.rs bails on a
non-JSON 200 (invalid JSON response, exit 1, verified), so only the JSON-shaped variant applies, and
a genuine node cannot produce it. api/register.rs types ucan as a non-optional String always
populated on the 201 path, with an encode failure becoming a 500.

Smaller inaccuracy on the same line: register.rs:102 hardcodes ~/.gitlawb/ucan.json in the message
even when --dir was passed.

Reachability

Not a correct gitlawb node. It needs --node or GITLAWB_NODE pointing at something else that
answers 200: an older or newer node version, a reverse proxy or API gateway, a captive portal, or a
plain misconfiguration. The non-JSON case is the realistic one and is quickstart-only.

Relationship to PR #186

Worth flagging for that PR rather than just this issue: quickstart.rs is absent from #186's file list
entirely (gh pr diff 186 --name-only, 18 gl files plus one test). So the unwrap_or_default() at
line 100 is a gap in that PR's own no-parse-before-status sweep, not merely an unrelated bug. #186
does touch register.rs, but only swaps the status check for crate::http::read_json; the
unwrap_or(""), the if !ucan.is_empty() guard, and the print at :102 all survive its patch
verbatim.

Fix direction

Move the print inside the guard, print the actual path rather than a hardcoded one, and warn when a
2xx carries no UCAN. Separately, replace unwrap_or_default() at quickstart.rs:100 so a non-JSON
body is an error rather than an empty object, which is the same change #186 is making elsewhere.

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

    crate:glgl — the contributor CLIkind:bugDefect fix — wrong or unsafe behaviorsev:lowCosmetic, cleanup, or nice-to-havesubsystem:apiNode REST API request/response surfacesubsystem:identityDID/UCAN, http-sig auth, push authorization

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions