Medium severity6.5NVD Advisory· Published Apr 10, 2026· Updated Apr 13, 2026
CVE-2026-35649
CVE-2026-35649
Description
OpenClaw before 2026.3.22 contains a settings reconciliation vulnerability that allows attackers to bypass intended deny-all revocations by exploiting empty allowlist handling. The vulnerability treats explicit empty allowlists as unset during reconciliation, silently undoing intended access control denials and restoring previously revoked permissions.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
openclawnpm | < 2026.3.22 | 2026.3.22 |
Affected products
1Patches
23cbf932413e4Tlon: honor explicit empty allowlists and defer cite expansion (#46788)
1 file changed · +19 −22
extensions/tlon/src/monitor/index.ts+19 −22 modified@@ -301,7 +301,7 @@ export async function monitorTlonProvider(opts: MonitorTlonOpts = {}): Promise<v `[tlon] Using autoDiscoverChannels from settings store: ${effectiveAutoDiscoverChannels}`, ); } - if (currentSettings.dmAllowlist?.length) { + if (currentSettings.dmAllowlist !== undefined) { effectiveDmAllowlist = currentSettings.dmAllowlist; runtime.log?.( `[tlon] Using dmAllowlist from settings store: ${effectiveDmAllowlist.join(", ")}`, @@ -322,7 +322,7 @@ export async function monitorTlonProvider(opts: MonitorTlonOpts = {}): Promise<v `[tlon] Using autoAcceptGroupInvites from settings store: ${effectiveAutoAcceptGroupInvites}`, ); } - if (currentSettings.groupInviteAllowlist?.length) { + if (currentSettings.groupInviteAllowlist !== undefined) { effectiveGroupInviteAllowlist = currentSettings.groupInviteAllowlist; runtime.log?.( `[tlon] Using groupInviteAllowlist from settings store: ${effectiveGroupInviteAllowlist.join(", ")}`, @@ -1176,17 +1176,14 @@ export async function monitorTlonProvider(opts: MonitorTlonOpts = {}): Promise<v return; } - // Resolve any cited/quoted messages first - const citedContent = await resolveAllCites(content.content); const rawText = extractMessageText(content.content); - const messageText = citedContent + rawText; - if (!messageText.trim()) { + if (!rawText.trim()) { return; } cacheMessage(nest, { author: senderShip, - content: messageText, + content: rawText, timestamp: content.sent || Date.now(), id: messageId, }); @@ -1200,7 +1197,7 @@ export async function monitorTlonProvider(opts: MonitorTlonOpts = {}): Promise<v // Check if we should respond: // 1. Direct mention always triggers response // 2. Thread replies where we've participated - respond if relevant (let agent decide) - const mentioned = isBotMentioned(messageText, botShipName, botNickname ?? undefined); + const mentioned = isBotMentioned(rawText, botShipName, botNickname ?? undefined); const inParticipatedThread = isThreadReply && parentId && participatedThreads.has(String(parentId)); @@ -1227,10 +1224,10 @@ export async function monitorTlonProvider(opts: MonitorTlonOpts = {}): Promise<v type: "channel", requestingShip: senderShip, channelNest: nest, - messagePreview: messageText.substring(0, 100), + messagePreview: rawText.substring(0, 100), originalMessage: { messageId: messageId ?? "", - messageText, + messageText: rawText, messageContent: content.content, timestamp: content.sent || Date.now(), parentId: parentId ?? undefined, @@ -1248,6 +1245,10 @@ export async function monitorTlonProvider(opts: MonitorTlonOpts = {}): Promise<v } } + // Resolve quoted content only after the sender passed channel authorization. + const citedContent = await resolveAllCites(content.content); + const messageText = citedContent + rawText; + const parsed = parseChannelNest(nest); await processMessage({ messageId: messageId ?? "", @@ -1365,15 +1366,15 @@ export async function monitorTlonProvider(opts: MonitorTlonOpts = {}): Promise<v ); } - // Resolve any cited/quoted messages first - const citedContent = await resolveAllCites(essay.content); const rawText = extractMessageText(essay.content); - const messageText = citedContent + rawText; - if (!messageText.trim()) { + if (!rawText.trim()) { return; } + const citedContent = await resolveAllCites(essay.content); + const resolvedMessageText = citedContent + rawText; // Check if this is the owner sending an approval response + const messageText = rawText; if (isOwner(senderShip) && isApprovalResponse(messageText)) { const handled = await handleApprovalResponse(messageText); if (handled) { @@ -1397,7 +1398,7 @@ export async function monitorTlonProvider(opts: MonitorTlonOpts = {}): Promise<v await processMessage({ messageId: messageId ?? "", senderShip, - messageText, + messageText: resolvedMessageText, messageContent: essay.content, isGroup: false, timestamp: essay.sent || Date.now(), @@ -1430,7 +1431,7 @@ export async function monitorTlonProvider(opts: MonitorTlonOpts = {}): Promise<v await processMessage({ messageId: messageId ?? "", senderShip, - messageText, + messageText: resolvedMessageText, messageContent: essay.content, // Pass raw content for media extraction isGroup: false, timestamp: essay.sent || Date.now(), @@ -1524,8 +1525,7 @@ export async function monitorTlonProvider(opts: MonitorTlonOpts = {}): Promise<v // Update DM allowlist if (newSettings.dmAllowlist !== undefined) { - effectiveDmAllowlist = - newSettings.dmAllowlist.length > 0 ? newSettings.dmAllowlist : account.dmAllowlist; + effectiveDmAllowlist = newSettings.dmAllowlist; runtime.log?.(`[tlon] Settings: dmAllowlist updated to ${effectiveDmAllowlist.join(", ")}`); } @@ -1551,10 +1551,7 @@ export async function monitorTlonProvider(opts: MonitorTlonOpts = {}): Promise<v // Update group invite allowlist if (newSettings.groupInviteAllowlist !== undefined) { - effectiveGroupInviteAllowlist = - newSettings.groupInviteAllowlist.length > 0 - ? newSettings.groupInviteAllowlist - : account.groupInviteAllowlist; + effectiveGroupInviteAllowlist = newSettings.groupInviteAllowlist; runtime.log?.( `[tlon] Settings: groupInviteAllowlist updated to ${effectiveGroupInviteAllowlist.join(", ")}`, );
630f1479c44fhttps://github.com/openclaw/openclawvia nvd-ref
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/openclaw/openclaw/commit/3cbf932413e41d1836cb91aed1541a28a3122f93nvdPatchWEB
- github.com/openclaw/openclaw/commit/630f1479c44f78484dfa21bb407cbe6f171dac87nvdPatch
- github.com/advisories/GHSA-pw7h-9g6p-c378ghsaADVISORY
- github.com/openclaw/openclaw/security/advisories/GHSA-pw7h-9g6p-c378nvdVendor AdvisoryWEB
- www.vulncheck.com/advisories/openclaw-settings-reconciliation-bypass-via-empty-allowlistnvdThird Party Advisory
News mentions
0No linked articles in our index yet.