Summary
On OpenClaw 2026.5.5 (b1abf9d as reported by openclaw status), a sub-agent completion/announce failure path can queue or attempt to deliver raw child output to Telegram instead of a mediated, user-safe summary.
This appears distinct from the already-fixed updater/runtime-context leak: the remaining path is in sub-agent completion fallback / delivery recovery after the parent-agent mediated completion failed.
Related existing issues: #39032 and #25592.
Environment
- OpenClaw:
2026.5.5 (b1abf9d)
- Installed package:
openclaw@2026.5.5
- npm latest at time checked:
2026.5.5
- OS/runtime: macOS
26.4.1 arm64, Node 25.6.1
- Gateway: LaunchAgent,
/opt/homebrew/lib/node_modules/openclaw/dist/index.js gateway --port 18789
- Channel: Telegram direct message
Evidence observed locally (redacted)
A failed queued delivery existed at:
/Users/ethansk/.openclaw/delivery-queue/37bd4b88-388d-4270-8c5a-415f3e2e1b87.json
Metadata from that queued item:
id: 37bd4b88-388d-4270-8c5a-415f3e2e1b87
channel: telegram
to: telegram:6164541473
accountId: default
- session key:
agent:main:telegram:default:direct:6164541473
- queued payload text length:
15962
retryCount: 3
lastError: Message must be non-empty for Telegram sends
enqueuedAt: 2026-05-06T11:56:26.534Z
lastAttemptAt: 2026-05-06T15:01:51.471Z
The queued payload contained raw/internal indicators including:
sawTargetNormalizationGain
target-normalization-gain-not-applied
missing-in-memory-cache
BEGIN_UNTRUSTED_CHILD_RESULT
BEGIN_OPENCLAW_INTERNAL_CONTEXT
I am deliberately not pasting the raw payload here because it is exactly the material that should not be exposed to Telegram or GitHub.
Relevant log/run identifiers:
- Log:
/tmp/openclaw/openclaw-2026-05-06.log
- Run/event id:
announce:v1:agent:main:subagent:f5f3eaaf-58a2-4322-aa1b-06e588aed2a7:d1e6ffed-0974-41c8-839f-57b714fb7e88
- Provider failure seen near this path:
service_unavailable_error / server_is_overloaded
- Raw error hash:
sha256:115e5180d97d
- Raw error fingerprint:
sha256:21e6e417518f
Likely failure path
From inspecting the installed dist files, the dangerous path appears to be:
- A sub-agent completes and
subagent-announce-delivery tries to wake or mediate the requester session.
- The mediated parent-agent completion fails or is incomplete, e.g. due to provider overload.
- The completion fallback path uses task completion event content directly.
- The outbound delivery queue persists payloads before final Telegram/channel sanitization, so raw child/internal content can remain in the retry queue.
- Delivery recovery later retries that queued item. In this case it failed with
Message must be non-empty for Telegram sends, likely because a later sanitizer/renderer stripped enough content to empty it, but the unsafe payload was still persisted and retried.
Files inspected locally:
/opt/homebrew/lib/node_modules/openclaw/dist/subagent-announce-delivery-De-sCDmZ.js
/opt/homebrew/lib/node_modules/openclaw/dist/delivery-queue-CX8x6Ho_.js
/opt/homebrew/lib/node_modules/openclaw/dist/send-C3qlmCZc.js
/opt/homebrew/lib/node_modules/openclaw/dist/sanitize-text-IbfTPlxP.js
Local mitigation I applied
This was a local hotfix in the installed dist only, not an upstream PR.
1. Stop direct fallback from using raw child event.result
Patched:
/opt/homebrew/lib/node_modules/openclaw/dist/subagent-announce-delivery-De-sCDmZ.js
Changed extractTaskCompletionFallbackText(event) so it no longer returns event.result. It now emits only task/status metadata plus a safe notice:
The child result was withheld from direct delivery so it can be summarized safely in-session.
Verification after patch:
- safe notice present: yes
event.result referenced inside extractTaskCompletionFallbackText: no
- backup created:
subagent-announce-delivery-De-sCDmZ.js.bak-unsafe-child-fallback
2. Add outbound delimiter stripping for internal context / untrusted child result blocks
Patched:
/opt/homebrew/lib/node_modules/openclaw/dist/sanitize-text-IbfTPlxP.js
Added stripping for delimited blocks:
<<<BEGIN_OPENCLAW_INTERNAL_CONTEXT>>> ... <<<END_OPENCLAW_INTERNAL_CONTEXT>>>
<<<BEGIN_UNTRUSTED_CHILD_RESULT>>> ... <<<END_UNTRUSTED_CHILD_RESULT>>>
Verification after patch:
BEGIN_OPENCLAW_INTERNAL_CONTEXT guard present: yes
BEGIN_UNTRUSTED_CHILD_RESULT guard present: yes
- backup created:
sanitize-text-IbfTPlxP.js.bak-runtime-delimiters
3. Quarantine the unsafe queued item
Moved the unsafe pending queue entry out of active retry path:
/Users/ethansk/.openclaw/delivery-queue/failed/37bd4b88-388d-4270-8c5a-415f3e2e1b87.quarantined-unsafe-child-result-20260506T151901Z.json
Verification after quarantine:
- pending
/Users/ethansk/.openclaw/delivery-queue/*.json: empty
- matching quarantined file exists under
delivery-queue/failed/
Expected upstream fix
OpenClaw should make this impossible in more than one layer:
- Sub-agent completion fallback must never use raw child
event.result for external channel delivery.
- Outbound queue entries should store already-sanitized external-delivery payloads, or reject/quarantine entries that contain internal runtime context / untrusted child result delimiters.
- Delivery recovery should fail closed for unsafe payloads instead of retrying them to Telegram/other channels.
- Tests should cover provider-failure/incomplete-mediated-completion paths, not just successful mediated summaries.
- Telegram/direct channel rendering should never receive
BEGIN_OPENCLAW_INTERNAL_CONTEXT or BEGIN_UNTRUSTED_CHILD_RESULT blocks as sendable text.
Open question
The local queue item may or may not have been fully delivered before being sanitized/retried; logs confirmed retry failures for this queue id, but the original Telegram-visible message report came from a user-observed message (8995). Either way, raw/internal content reached a send/retry path and should be treated as a privacy/safety bug.
Summary
On OpenClaw
2026.5.5(b1abf9das reported byopenclaw status), a sub-agent completion/announce failure path can queue or attempt to deliver raw child output to Telegram instead of a mediated, user-safe summary.This appears distinct from the already-fixed updater/runtime-context leak: the remaining path is in sub-agent completion fallback / delivery recovery after the parent-agent mediated completion failed.
Related existing issues: #39032 and #25592.
Environment
2026.5.5(b1abf9d)openclaw@2026.5.52026.5.526.4.1arm64, Node25.6.1/opt/homebrew/lib/node_modules/openclaw/dist/index.js gateway --port 18789Evidence observed locally (redacted)
A failed queued delivery existed at:
/Users/ethansk/.openclaw/delivery-queue/37bd4b88-388d-4270-8c5a-415f3e2e1b87.jsonMetadata from that queued item:
id:37bd4b88-388d-4270-8c5a-415f3e2e1b87channel:telegramto:telegram:6164541473accountId:defaultagent:main:telegram:default:direct:616454147315962retryCount:3lastError:Message must be non-empty for Telegram sendsenqueuedAt:2026-05-06T11:56:26.534ZlastAttemptAt:2026-05-06T15:01:51.471ZThe queued payload contained raw/internal indicators including:
sawTargetNormalizationGaintarget-normalization-gain-not-appliedmissing-in-memory-cacheBEGIN_UNTRUSTED_CHILD_RESULTBEGIN_OPENCLAW_INTERNAL_CONTEXTI am deliberately not pasting the raw payload here because it is exactly the material that should not be exposed to Telegram or GitHub.
Relevant log/run identifiers:
/tmp/openclaw/openclaw-2026-05-06.logannounce:v1:agent:main:subagent:f5f3eaaf-58a2-4322-aa1b-06e588aed2a7:d1e6ffed-0974-41c8-839f-57b714fb7e88service_unavailable_error/server_is_overloadedsha256:115e5180d97dsha256:21e6e417518fLikely failure path
From inspecting the installed dist files, the dangerous path appears to be:
subagent-announce-deliverytries to wake or mediate the requester session.Message must be non-empty for Telegram sends, likely because a later sanitizer/renderer stripped enough content to empty it, but the unsafe payload was still persisted and retried.Files inspected locally:
/opt/homebrew/lib/node_modules/openclaw/dist/subagent-announce-delivery-De-sCDmZ.js/opt/homebrew/lib/node_modules/openclaw/dist/delivery-queue-CX8x6Ho_.js/opt/homebrew/lib/node_modules/openclaw/dist/send-C3qlmCZc.js/opt/homebrew/lib/node_modules/openclaw/dist/sanitize-text-IbfTPlxP.jsLocal mitigation I applied
This was a local hotfix in the installed dist only, not an upstream PR.
1. Stop direct fallback from using raw child
event.resultPatched:
/opt/homebrew/lib/node_modules/openclaw/dist/subagent-announce-delivery-De-sCDmZ.jsChanged
extractTaskCompletionFallbackText(event)so it no longer returnsevent.result. It now emits only task/status metadata plus a safe notice:Verification after patch:
event.resultreferenced insideextractTaskCompletionFallbackText: nosubagent-announce-delivery-De-sCDmZ.js.bak-unsafe-child-fallback2. Add outbound delimiter stripping for internal context / untrusted child result blocks
Patched:
/opt/homebrew/lib/node_modules/openclaw/dist/sanitize-text-IbfTPlxP.jsAdded stripping for delimited blocks:
<<<BEGIN_OPENCLAW_INTERNAL_CONTEXT>>>...<<<END_OPENCLAW_INTERNAL_CONTEXT>>><<<BEGIN_UNTRUSTED_CHILD_RESULT>>>...<<<END_UNTRUSTED_CHILD_RESULT>>>Verification after patch:
BEGIN_OPENCLAW_INTERNAL_CONTEXTguard present: yesBEGIN_UNTRUSTED_CHILD_RESULTguard present: yessanitize-text-IbfTPlxP.js.bak-runtime-delimiters3. Quarantine the unsafe queued item
Moved the unsafe pending queue entry out of active retry path:
/Users/ethansk/.openclaw/delivery-queue/failed/37bd4b88-388d-4270-8c5a-415f3e2e1b87.quarantined-unsafe-child-result-20260506T151901Z.jsonVerification after quarantine:
/Users/ethansk/.openclaw/delivery-queue/*.json: emptydelivery-queue/failed/Expected upstream fix
OpenClaw should make this impossible in more than one layer:
event.resultfor external channel delivery.BEGIN_OPENCLAW_INTERNAL_CONTEXTorBEGIN_UNTRUSTED_CHILD_RESULTblocks as sendable text.Open question
The local queue item may or may not have been fully delivered before being sanitized/retried; logs confirmed retry failures for this queue id, but the original Telegram-visible message report came from a user-observed message (
8995). Either way, raw/internal content reached a send/retry path and should be treated as a privacy/safety bug.