openclaw - 💡(How to fix) Fix allowUnsafeExternalContent flag ignored in /hooks/agent dispatch path [1 comments, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#60521Fetched 2026-04-08 02:50:03
View on GitHub
Comments
1
Participants
1
Timeline
1
Reactions
0
Author
Participants
Timeline (top)
commented ×1

When dispatching via POST /hooks/agent with allowUnsafeExternalContent: true in the request body, the flag is silently ignored and the message is still wrapped in the SECURITY NOTICE: The following content is from an EXTERNAL, UNTRUSTED source banner with <<<EXTERNAL_UNTRUSTED_CONTENT>>> markers.

Root Cause

In gateway-cli (line ~5003 in the minified dist), the wrapping decision reads allowUnsafeExternalContent from agentPayload:

const agentPayload = params.job.payload.kind === "agentTurn" ? params.job.payload : null;
// ...
const allowUnsafeExternalContent = agentPayload?.allowUnsafeExternalContent === true
    || isGmailHook && params.cfg.hooks?.gmail?.allowUnsafeExternalContent === true;

When the /hooks/agent HTTP request is normalized into an internal job, the payload.kind is not "agentTurn", so agentPayload is null, and the flag from the original POST body is never read.

The flag IS correctly accepted in the Zod schema (allowUnsafeExternalContent: z.boolean().optional()) and flows through copyTopLevelAgentTurnFields / stripLegacyTopLevelFields, but it's lost before reaching the wrapping decision.

Fix Action

Fix / Workaround

When dispatching via POST /hooks/agent with allowUnsafeExternalContent: true in the request body, the flag is silently ignored and the message is still wrapped in the SECURITY NOTICE: The following content is from an EXTERNAL, UNTRUSTED source banner with <<<EXTERNAL_UNTRUSTED_CONTENT>>> markers.

Atlas HQ uses /hooks/agent to dispatch trusted, system-generated task assignments to agents. The external content warning makes agents treat their own task instructions as untrusted, breaking lifecycle callbacks and causing agents to refuse tool execution on their assigned work.

Code Example

{
  "message": "Execute task #123...",
  "agentId": "my-agent",
  "sessionKey": "hook:atlas:jobrun:123",
  "timeoutSeconds": 900,
  "deliver": false,
  "allowUnsafeExternalContent": true
}

---

SECURITY NOTICE: The following content is from an EXTERNAL, UNTRUSTED source (e.g., email, webhook).
...
<<<EXTERNAL_UNTRUSTED_CONTENT id="...">
Source: Webhook
---
[original message]
<<<END_EXTERNAL_UNTRUSTED_CONTENT ...>>>

---

const agentPayload = params.job.payload.kind === "agentTurn" ? params.job.payload : null;
// ...
const allowUnsafeExternalContent = agentPayload?.allowUnsafeExternalContent === true
    || isGmailHook && params.cfg.hooks?.gmail?.allowUnsafeExternalContent === true;

---

const allowUnsafeExternalContent = 
    agentPayload?.allowUnsafeExternalContent === true
    || params.job?.allowUnsafeExternalContent === true   // ← check top-level
    || (isGmailHook && params.cfg.hooks?.gmail?.allowUnsafeExternalContent === true);
RAW_BUFFERClick to expand / collapse

Summary

When dispatching via POST /hooks/agent with allowUnsafeExternalContent: true in the request body, the flag is silently ignored and the message is still wrapped in the SECURITY NOTICE: The following content is from an EXTERNAL, UNTRUSTED source banner with <<<EXTERNAL_UNTRUSTED_CONTENT>>> markers.

Reproduction

  1. Send a POST to /hooks/agent with:
{
  "message": "Execute task #123...",
  "agentId": "my-agent",
  "sessionKey": "hook:atlas:jobrun:123",
  "timeoutSeconds": 900,
  "deliver": false,
  "allowUnsafeExternalContent": true
}
  1. The agent receives the prompt wrapped in:
SECURITY NOTICE: The following content is from an EXTERNAL, UNTRUSTED source (e.g., email, webhook).
...
<<<EXTERNAL_UNTRUSTED_CONTENT id="...">
Source: Webhook
---
[original message]
<<<END_EXTERNAL_UNTRUSTED_CONTENT ...>>>
  1. Expected: the message should arrive unwrapped because allowUnsafeExternalContent: true was set.

Root cause

In gateway-cli (line ~5003 in the minified dist), the wrapping decision reads allowUnsafeExternalContent from agentPayload:

const agentPayload = params.job.payload.kind === "agentTurn" ? params.job.payload : null;
// ...
const allowUnsafeExternalContent = agentPayload?.allowUnsafeExternalContent === true
    || isGmailHook && params.cfg.hooks?.gmail?.allowUnsafeExternalContent === true;

When the /hooks/agent HTTP request is normalized into an internal job, the payload.kind is not "agentTurn", so agentPayload is null, and the flag from the original POST body is never read.

The flag IS correctly accepted in the Zod schema (allowUnsafeExternalContent: z.boolean().optional()) and flows through copyTopLevelAgentTurnFields / stripLegacyTopLevelFields, but it's lost before reaching the wrapping decision.

Versions affected

  • 2026.3.13 (confirmed)
  • 2026.4.2 (confirmed, same code path)

Suggested fix

Read allowUnsafeExternalContent from the top-level job fields or from the normalized payload, not only from agentPayload (which is gated on kind === "agentTurn"):

const allowUnsafeExternalContent = 
    agentPayload?.allowUnsafeExternalContent === true
    || params.job?.allowUnsafeExternalContent === true   // ← check top-level
    || (isGmailHook && params.cfg.hooks?.gmail?.allowUnsafeExternalContent === true);

Context

Atlas HQ uses /hooks/agent to dispatch trusted, system-generated task assignments to agents. The external content warning makes agents treat their own task instructions as untrusted, breaking lifecycle callbacks and causing agents to refuse tool execution on their assigned work.

extent analysis

TL;DR

The fix involves modifying the wrapping decision logic to read allowUnsafeExternalContent from the top-level job fields in addition to agentPayload.

Guidance

  • Verify that the allowUnsafeExternalContent flag is being set correctly in the request body when sending a POST to /hooks/agent.
  • Check the gateway-cli code to ensure that the suggested fix is applied, specifically the line where allowUnsafeExternalContent is read from agentPayload and the top-level job fields.
  • Test the fix by sending a POST request with allowUnsafeExternalContent: true and verify that the message is not wrapped in the security notice banner.
  • Consider updating the code to handle cases where agentPayload is null to avoid potential issues.

Example

const allowUnsafeExternalContent = 
    agentPayload?.allowUnsafeExternalContent === true
    || params.job?.allowUnsafeExternalContent === true
    || (isGmailHook && params.cfg.hooks?.gmail?.allowUnsafeExternalContent === true);

Notes

The suggested fix assumes that the allowUnsafeExternalContent flag is being set correctly in the request body and that the issue is solely due to the wrapping decision logic. If the issue persists after applying the fix, further debugging may be necessary.

Recommendation

Apply the suggested workaround by modifying the gateway-cli code to read allowUnsafeExternalContent from the top-level job fields, as this should resolve the issue without requiring an upgrade to a fixed version.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix allowUnsafeExternalContent flag ignored in /hooks/agent dispatch path [1 comments, 1 participants]