Skip to main content

Module json

Module json 

Source
Expand description

Canonical serde_json::Value -> Ipld conversion for untrusted input.

Three surfaces feed untrusted JSON into mnem: the CLI (mnem ... --prop key=value), mnem-http (request bodies on /v1/*), and mnem-mcp (tool-call arguments objects). Before json_to_ipld lived here, each of those crates carried its own near-identical implementation, each with its own copy of IPLD_MAX_DEPTH, its own u64 > i64::MAX rejection path, and its own error type (anyhow::Result, Result<_, String>, anyhow::Result). Every future hardening change had to be replicated across three files, and the three were already out-of-sync in subtle ways (error message wording drift, different comment wording).

This module is the canonical implementation. All three callers re-export json_to_ipld and adapt JsonIpldError to their local error boundary:

  • mnem-cli: ? through anyhow::Error (the library Display impl threads directly).
  • mnem-http: map_err to mnem_http::error::Error::BadRequest so a malformed JSON body returns HTTP 400 with a specific reason.
  • mnem-mcp: map_err to an MCP error.invalid_params response carrying the same Display string as a structured field.

§Hardening

Two concrete attacker-controlled inputs motivate this module’s shape:

  1. Deeply-nested arrays/objects. A stock recursive-descent converter stack-overflows on [[[[[[[...]]]]]]] with a few thousand levels of nesting. IPLD_MAX_DEPTH caps the traversal at 64 levels, matching crate::codec::dagcbor::WALK_IPLD_MAX_DEPTH so a payload cannot pass this check and then fail further down the pipeline.
  2. Unsigned ids above i64::MAX. Silently demoting such a value to Ipld::Float loses precision above 2^53 (a 19-digit id becomes a rounded double). Reject instead: callers that really need a 64-bit unsigned id must send it as a string.

Enums§

JsonIpldError
Failure modes for json_to_ipld.

Constants§

IPLD_MAX_DEPTH
Maximum depth of nested JSON objects / arrays json_to_ipld will walk. Beyond this, the conversion returns an error rather than recursing. Picked at 64 because legitimate agent-memory props rarely nest past ~6, while a malicious payload can cheaply ship arbitrary depth and stack-overflow the process.

Functions§

json_to_ipld
Convert a serde_json::Value into an Ipld value, rejecting deeply-nested or precision-losing inputs.