Skip to content

config.patch persists a redaction-truncated array from config.get → silent data loss of bindings[] #90540

@aarcher4

Description

@aarcher4

Summary

A config.get whose response is redaction-truncated for a large array can be round-tripped into a destructive config.patch: the truncated array is persisted over the full one, silently destroying every element that the read omitted. We hit this on bindings[] and lost almost all routing bindings from a single innocuous edit.

Version: OpenClaw 2026.3.13 (61d171a)
Component: gateway config tool (gateway actions config.get / config.patch) + the config redaction layer.

What happens

  1. A client (in our case an agent with the gateway tool) calls config.get to add one entry to bindings[].
  2. The gateway's redaction layer truncates the bindings[] array in the returned config. Observed log line:
    [config/redaction] Redacted config array key bindings[] has been truncated
    
  3. The client appends its new entry to the truncated array it received and calls config.patch with changedPaths=bindings.
  4. The gateway persists that truncated array verbatim:
    [gateway] config.patch write actor=gateway-client changedPaths=bindings restartReason=config.patch
    Config overwrite: .../openclaw.json (sha256 A -> B, backup=.../openclaw.json.bak)
    
  5. Result: bindings[] collapsed from 82 entries to 2. 80 routing bindings were destroyed by an edit that intended to add one.

Impact

For multi-agent routing this is severe: with most bindings gone, unbound peers fall through to a single catch-all agent, so messages are answered by the wrong agent (a cross-tenant data exposure in our deployment). A redaction feature meant to protect a read became a silent write-side data-loss bug. The auto-backup (openclaw.json.bak) is what allowed recovery.

Expected

A redacted/truncated value must never be writable back over the full value. Any of:

  • config.get should not truncate arrays that callers may patch (or should return full data when the caller has write intent / for round-trip use); or
  • the redaction layer should tag a response as truncated, and config.patch should reject (or require an explicit override for) a write of a key whose source read was truncated; or
  • config.patch for array keys should be merge/diff-based rather than wholesale-replace, so a short array can't clobber a long one.

Repro sketch

  1. Have a config whose bindings[] (or any array) is long enough to trigger redaction truncation on config.get.
  2. gateway config.get, observe the bindings[] has been truncated log and the shortened array in the response.
  3. gateway config.patch with changedPaths=bindings, sending back the array from step 2 (plus one appended item).
  4. Inspect the on-disk config: the array is now the truncated set, not the original.

Happy to provide more detail or test a fix.

Metadata

Metadata

Assignees

Labels

P1High-priority user-facing bug, regression, or broken workflow.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:needs-security-reviewClawSweeper marked this issue as needing security-sensitive review.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:data-lossCan lose, corrupt, or silently drop user/session/config data.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.impact:securitySecurity boundary, credential, authz, sandbox, or sensitive-data risk.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions