Expand description
SerializedJsonField — typed guard for JSON-envelope construction.
Issue #178, enforcing ADR 0010 §3.
§The boundary
Every JSON envelope this server emits — HelloAck (issue #166), gRPC
PayloadReply (crates/reddb-server/src/grpc/service_impl.rs), and
HTTP response bodies (crates/reddb-server/src/server/handlers_*.rs)
— is a structured serialization format whose delimiter (",
control bytes, {/}, :) the untrusted caller can attempt to
inject. The Whiz / Babeld pattern is serialize(trusted ++ untrusted) without escape: the producer emits attacker-controlled
bytes verbatim and the downstream parser sees a forged field.
SerializedJsonField is the typed point of crossing for that
boundary on the producer side. Caller-influenced data does not get
formatted into a JSON envelope as raw bytes; it round-trips through
crate::serde_json::Value first, picking up the canonical
RFC-8259-compliant escape contract from
crate::serde_json::Value::to_string_compact (the F-01 hotfix
shipped in #181).
§Public surface
SerializedJsonField::tainted— wrap an untrusted, caller- influenced string. Returns acrate::serde_json::Value::Stringthat, when serialized, will have every control byte and JSON delimiter escaped per RFC 8259 §7. Use this for error messages, user-supplied identifiers, free-form text, and anything reaching the envelope from a parser, header, or request body.SerializedJsonField::typed— wrap a known-typed value that implementscrate::serde_json::JsonEncode(the in-house counterpart toserde::Serialize). Returns the value’s canonicalcrate::serde_json::Valuerepresentation. Use this for structs and enums whose schema is owned by the server; it guarantees the round-trip even for nested string fields.
Both forms produce a crate::serde_json::Value that the rest of
the envelope assembly (Map::insert, to_string_compact)
consumes uniformly. A caller never hands raw bytes to the JSON
emitter; everything goes through Value.
§F-05 — SQL parser error message routing
Audit finding F-05 (see
docs/security/serialization-boundary-audit-2026-05-06.md)
observes that SQL parser errors interpolate user-supplied SQL
fragments into their Display strings via bare format!. When
such an error message reaches an HTTP response body via
[crate::server::transport::json_error], the F-05 fix on the JSON
wire side is to route the message through
SerializedJsonField::tainted before embedding it. That fix
lands in this slice via the
[crate::server::transport::json_error] retrofit, which now wraps
every error message with the guard regardless of upstream origin.
The parser-side F-05 cleanup (avoiding format! for the offending
fragment in the first place) is a separate concern tracked under
Lane AG / issue #184.
§Why tainted does not return an error
Unlike crate::server::header_escape_guard::HeaderEscapeGuard,
which rejects CR/LF/NUL/tab outright, SerializedJsonField cannot
reject anything: every Unicode string is a legal JSON string under
RFC 8259 §7 once escaped. The contract is “round-trip”, not
“validate”. The result is always emittable.
Structs§
- Serialized
Json Field - Typed guard for JSON-envelope field construction. See module docs.