MCP proxy blind-retries mutating calls and synthesizes replies when retries run out #118

Open
opened 2026-08-06 21:23:23 +00:00 by tim.lingo · 0 comments
Member

BUG-30 (P1, data integrity). Two defects in the same function, forward_with_retrymcp-proxy/src/main.el ~L38-58:

  1. Blind retry on mutating methods. An empty reply triggers a re-POST regardless of method, so a remember / forget that actually succeeded but answered slowly can be applied twice. Duplicate memories and double-deletes are both reachable.
  2. Synthesized success. When retries run out, the proxy manufactures a well-formed JSON-RPC reply. The transport invents an answer the brain never gave — a false receipt at the layer least able to be audited.

Fix known, no investigation needed:

  • Never blind-retry a mutating method — verify-then-retry (read back by id, retry only if genuinely absent), or don't retry at all.
  • Never synthesize a reply. Propagate the transport error; a caller that gets an error can recover, a caller that gets a fabricated success cannot.

Why it matters beyond the proxy: every MCP client (the CLI included) treats a well-formed reply as truth. This is the same class as the false-receipt bugs already fixed in #100 / #101, one layer lower.

Found by: source audit, confirmed by a verification pass (workflow wf_4c0be183). Not yet reproduced live — the source path is unambiguous, but a repro would strengthen it.


Filed from our local bug register (docs/BACKLOG.md) so it is pickup-able by anyone with time, not just its author. Unassigned on purpose — claim it if you want it.

**BUG-30 (P1, data integrity).** Two defects in the same function, `forward_with_retry` — `mcp-proxy/src/main.el` ~L38-58: 1. **Blind retry on mutating methods.** An empty reply triggers a re-POST regardless of method, so a `remember` / `forget` that actually succeeded but answered slowly can be applied **twice**. Duplicate memories and double-deletes are both reachable. 2. **Synthesized success.** When retries run out, the proxy **manufactures a well-formed JSON-RPC reply**. The transport invents an answer the brain never gave — a false receipt at the layer least able to be audited. **Fix known, no investigation needed:** - Never blind-retry a mutating method — verify-then-retry (read back by id, retry only if genuinely absent), or don't retry at all. - Never synthesize a reply. Propagate the transport error; a caller that gets an error can recover, a caller that gets a fabricated success cannot. **Why it matters beyond the proxy:** every MCP client (the CLI included) treats a well-formed reply as truth. This is the same class as the false-receipt bugs already fixed in #100 / #101, one layer lower. **Found by:** source audit, confirmed by a verification pass (workflow `wf_4c0be183`). Not yet reproduced live — the source path is unambiguous, but a repro would strengthen it. --- *Filed from our local bug register (`docs/BACKLOG.md`) so it is pickup-able by anyone with time, not just its author. Unassigned on purpose — claim it if you want it.*
tim.lingo added the ORTHOGONAL label 2026-08-06 21:23:23 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: neuron-technologies/neuron#118