OpenClaw Fixes a Restart Path That Could Undo Outbound Redaction
Merged main fixes preserve cancellation and rewrites across restart while waking persisted channel retries after their backoff without duplicate delivery.
OpenClaw has merged a P1 fix for a restart-recovery path that could reverse an outbound policy decision. A durable message prepared before a Gateway restart could run reply_payload_sending and message_sending again during recovery. That second pass could expose content previously cancelled or redacted, apply a different rewrite, or repeat a plugin side effect.
This is a main-branch correction, not proof that an installed release contains it. Operators who use outbound hooks as a confidentiality or compliance boundary should identify a containing package or exact revision and revalidate restart behaviour before closing the risk.
Why rerunning a safety hook is not harmless
The earlier routed-reply fix made outbound modifiers part of ordinary channel delivery. The new failure sat later in the lifecycle: durable recovery did not preserve the final post-policy result as the authority for the eventual send.
A modifying hook is not necessarily deterministic. It may inspect current policy, consume a one-time approval, call an external classifier, record an audit event, replace sensitive text or cancel delivery completely. Running it twice can therefore produce a different answer from the one already accepted before the crash.
The dangerous case is cancellation. If the first pass says “do not send” but restart recovery reconstructs work from an earlier payload and runs the policy again, the recovered path can cross the exact boundary the hook was meant to enforce.
Interpretation: durable delivery must preserve both message intent and the last authoritative policy outcome. Recovering an older representation is not resilience when it discards a security decision made later in the pipeline.
What changed
PR #116632 introduces a versioned, post-policy outbound batch before canonical queue admission. The prepared result is persisted under durable custody, and restart recovery delivers that result instead of rerunning the modifying hooks.
That changes the recovery contract in three useful ways:
- a cancelled batch remains cancelled;
- a rewritten batch retains the exact prepared content; and
- hook side effects are not repeated merely because the Gateway restarted.
Upstream also reports hardening around durable preparation custody and aligned restart fixtures. The supplied record labels the merge as both a compatibility and security-boundary risk, which is appropriate: changing queue ownership can affect delivery behaviour even though the goal is to make policy outcomes stable.
Who needs to act
Prioritise review if any channel plugin uses reply_payload_sending or message_sending to:
- redact secrets or personal information;
- suppress messages under policy;
- add mandatory legal or compliance text;
- rewrite destinations, links or identifiers;
- spend a one-time token or approval; or
- emit an external side effect that must occur exactly once.
A deployment that does not use modifying hooks still benefits from deterministic recovery, but the immediate confidentiality risk is lower.
Do not infer safety from a normal send test. The affected boundary requires a restart between preparation and provider delivery.
Safe acceptance test
Use a disposable Gateway, a test channel and harmless marker text. Never test redaction with a real credential.
- Install a build proven to contain PR
#116632. - Configure a deterministic rewrite marker and a deterministic cancellation marker.
- Confirm ordinary delivery runs each modifier once.
- Pause the test path after policy preparation but before provider acceptance using a supported fixture or test harness.
- Restart the Gateway and allow durable recovery to continue.
- Prove the rewrite is delivered exactly once with the exact prepared content.
- Prove the cancelled item never becomes provider-visible.
- Confirm no second modifier invocation or duplicate external side effect occurred.
- Repeat for every provider-owned delivery path, preview mode and media mode on which policy depends.
If an older deployment may have hit this fault, preserve Gateway logs, durable queue records, plugin audit records and provider-visible messages. Reconcile by stable message identity. Do not bulk-replay uncertain records: the original work may already have produced an external side effect even when the final message was not visible.
Relationship to the earlier routed-reply fix
This does not make the July routed-hook advisory obsolete. The two changes repair different gaps:
- PR
#113448made normal routed replies pass through modifying hooks; and - PR
#116632makes durable restart recovery preserve the resulting decision without executing those hooks again.
Both are required for a credible end-to-end boundary. A hook that is skipped on first delivery is unsafe; a hook whose result is forgotten during recovery is also unsafe.
A later retry fix removes restart as the queue’s alarm clock
PR #118694 fixes another gap in the generic durable queue. Recovery previously ran once at Gateway startup. A stored row whose backoff had not elapsed at that moment—or any new Slack, Discord, Signal or other generic transport failure after startup—could remain stranded until another process restart unless its channel happened to implement separate polling.
The Gateway runtime now owns a bounded timer aligned with the existing five-second first backoff. Each tick uses the canonical atomic claim, queue coordinator, current runtime configuration and existing retry policy; overlapping drains are not admitted, suspended Gateways are skipped, and the timer stops with the runtime lifecycle.
Current authorization is deliberately re-evaluated. A queued message for a channel account revoked after persistence must dead-letter without invoking the provider send callback. Durable custody preserves intent, not stale authority.
Interpretation: recovery now needs both stable policy output and a live wake-up owner. The earlier fix preserved exactly what may be sent; the newer fix ensures eligible work is reconsidered after backoff without requiring a restart.
Add three acceptance cases to the restart matrix:
- start with an empty queue, persist a harmless failed delivery later and prove it retries after backoff;
- start with a row whose backoff is still in the future and prove it wakes once when eligible; and
- revoke the destination account before eligibility and prove the row dead-letters without a provider send.
Evidence and limits
The official merged PR, closing issue and merge commit agree on the failure and correction. GitHub search independently surfaced the post-policy batch and no-rerun recovery design. Direct GitHub page extraction was unavailable during this run, so detailed implementation claims remain attributed to upstream.
We did not interrupt a live provider send or inspect a packaged release. The evidence establishes a merged source fix, not package inclusion or correctness across every third-party channel adapter.
Bottom line
Restart recovery must not reopen a message after policy has cancelled or rewritten it. OpenClaw now persists the post-policy outbound result and recovers that result rather than asking the modifiers again.
If outbound hooks are a real control in your environment, treat the containing upgrade as a security revalidation event: test the ordinary route, interrupt it at the durable boundary, and prove that recovery preserves cancellation, content and side-effect count exactly.
THE RECEIPTS
Claims should survive the click.
Primary links used for this article are listed openly. If the evidence changes, the verification date changes with it.THE OPERATOR BRIEF