--- id: SMH-ISSUE-JSONKEYS type: issue title: "Secret substitution overwrites colliding object keys" specs: [SMH-SPEC-SPEC0001] status: open --- # Secret substitution overwrites colliding object keys ## Boundary Secret substitution across nested object keys. Shared string transformation inherits existing last-key-wins behavior. ## Evidence `smith/src/structured.rs` inserts transformed keys into one map. `smith-core/src/agent.rs` uses this transformation for masking and authorized local unmasking. Distinct input keys can map to one output key; later insertion replaces earlier value. ```rust let data = smith::ToolArguments::from_json( r#"{"secret-value":1,"{{secret:token}}":2}"#, )?; let masked = data.transform_strings( &|text| text.replace("secret-value", "{{secret:token}}"), 64, )?; // Serialized result: {"{{secret:token}}":2}; first value disappeared. ``` ## Impact Argument members disappear during secret substitution. Recorded and authorized effect inputs can lose information. No proof of filesystem escape or secret disclosure. ## Resolution candidate Reject transformed-key collisions explicitly before any effect. Diagnostic must not expose original keys or secret values. Pin nested masking and unmasking collisions with regression tests. Existing behavior changes; resolve separately from representation-only migration.