Medium severity5.3NVD Advisory· Published May 6, 2026· Updated May 7, 2026
CVE-2026-43583
CVE-2026-43583
Description
OpenClaw versions 2026.4.10 before 2026.4.14 fail to persist session context during delivery queue recovery for media replay. Attackers can exploit recovered queued outbound media to bypass group tool policy enforcement and weaken channel media restrictions after service restart or recovery.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
openclawnpm | >= 2026.4.10, < 2026.4.14 | 2026.4.14 |
Affected products
2Patches
148aae82bbc19fix(outbound): replay queued session context (#66025)
6 files changed · +68 −0
CHANGELOG.md+1 −0 modified@@ -26,6 +26,7 @@ Docs: https://docs.openclaw.ai - Browser/CDP: let local attach-only `manual-cdp` profiles reuse the local loopback CDP control plane under strict default policy and remote-class probe timeouts, so tabs/snapshot stop falsely reporting a live local browser session as not running. (#65611, #66080) Thanks @mbelinky. - Cron/scheduler: stop inventing short retries when cron next-run calculation returns no valid future slot, and keep a maintenance wake armed so enabled unscheduled jobs recover without entering a refire loop. (#66019, #66083) Thanks @mbelinky. - Cron/scheduler: preserve the active error-backoff floor when maintenance repair recomputes a missing cron next-run, so recurring errored jobs do not resume early after a transient next-run resolution failure. (#66019, #66083, #66113) Thanks @mbelinky. +- Outbound/delivery-queue: persist the originating outbound `session` context on queued delivery entries and replay it during recovery, so write-ahead-queued sends keep their original outbound media policy context after restart instead of evaluating against a missing session. (#66025) Thanks @eleqtrizit. ## 2026.4.12
src/infra/outbound/deliver.ts+1 −0 modified@@ -507,6 +507,7 @@ export async function deliverOutboundPayloads( forceDocument: params.forceDocument, silent: params.silent, mirror: params.mirror, + session: params.session, gatewayClientScopes: params.gatewayClientScopes, }).catch(() => null); // Best-effort — don't block delivery if queue write fails.
src/infra/outbound/delivery-queue.recovery.test.ts+18 −0 modified@@ -165,6 +165,15 @@ describe("delivery-queue recovery", () => { text: "a", mediaUrls: ["https://example.com/a.png"], }, + session: { + key: "agent:main:main", + agentId: "agent-main", + requesterAccountId: "acct-1", + requesterSenderId: "sender-1", + requesterSenderName: "Sender One", + requesterSenderUsername: "sender.one", + requesterSenderE164: "+15551234567", + }, }, tmpDir(), ); @@ -183,6 +192,15 @@ describe("delivery-queue recovery", () => { text: "a", mediaUrls: ["https://example.com/a.png"], }, + session: { + key: "agent:main:main", + agentId: "agent-main", + requesterAccountId: "acct-1", + requesterSenderId: "sender-1", + requesterSenderName: "Sender One", + requesterSenderUsername: "sender.one", + requesterSenderE164: "+15551234567", + }, }), ); });
src/infra/outbound/delivery-queue-recovery.ts+1 −0 modified@@ -104,6 +104,7 @@ function buildRecoveryDeliverParams(entry: QueuedDelivery, cfg: OpenClawConfig) forceDocument: entry.forceDocument, silent: entry.silent, mirror: entry.mirror, + session: entry.session, gatewayClientScopes: entry.gatewayClientScopes, skipQueue: true, // Prevent re-enqueueing during recovery. } satisfies Parameters<DeliverFn>[0];
src/infra/outbound/delivery-queue.storage.test.ts+43 −0 modified@@ -33,6 +33,12 @@ describe("delivery-queue storage", () => { text: "hello", mediaUrls: ["https://example.com/file.png"], }, + session: { + key: "agent:main:main", + agentId: "agent-main", + requesterAccountId: "acct-1", + requesterSenderId: "sender-1", + }, }, tmpDir(), ); @@ -53,6 +59,12 @@ describe("delivery-queue storage", () => { text: "hello", mediaUrls: ["https://example.com/file.png"], }, + session: { + key: "agent:main:main", + agentId: "agent-main", + requesterAccountId: "acct-1", + requesterSenderId: "sender-1", + }, retryCount: 0, }); expect(entry.payloads).toEqual([{ text: "hello" }]); @@ -169,6 +181,37 @@ describe("delivery-queue storage", () => { expect(entry.gatewayClientScopes).toEqual(["operator.write"]); }); + it("persists session context for recovery replay", async () => { + const id = await enqueueTextDelivery( + { + channel: "telegram", + to: "2", + payloads: [{ text: "b" }], + session: { + key: "agent:main:main", + agentId: "agent-main", + requesterAccountId: "acct-1", + requesterSenderId: "sender-1", + requesterSenderName: "Sender One", + requesterSenderUsername: "sender.one", + requesterSenderE164: "+15551234567", + }, + }, + tmpDir(), + ); + + const entry = readQueuedEntry(tmpDir(), id); + expect(entry.session).toEqual({ + key: "agent:main:main", + agentId: "agent-main", + requesterAccountId: "acct-1", + requesterSenderId: "sender-1", + requesterSenderName: "Sender One", + requesterSenderUsername: "sender.one", + requesterSenderE164: "+15551234567", + }); + }); + it("backfills lastAttemptAt for legacy retry entries during load", async () => { const id = await enqueueTextDelivery({ channel: "whatsapp",
src/infra/outbound/delivery-queue-storage.ts+4 −0 modified@@ -4,6 +4,7 @@ import type { ReplyPayload } from "../../auto-reply/types.js"; import { resolveStateDir } from "../../config/paths.js"; import { generateSecureUuid } from "../secure-random.js"; import type { OutboundMirror } from "./mirror.js"; +import type { OutboundSessionContext } from "./session-context.js"; import type { OutboundChannel } from "./targets.js"; const QUEUE_DIRNAME = "delivery-queue"; @@ -26,6 +27,8 @@ export type QueuedDeliveryPayload = { forceDocument?: boolean; silent?: boolean; mirror?: OutboundMirror; + /** Session context needed to preserve outbound media policy on recovery. */ + session?: OutboundSessionContext; /** Gateway caller scopes at enqueue time, preserved for recovery replay. */ gatewayClientScopes?: readonly string[]; }; @@ -144,6 +147,7 @@ export async function enqueueDelivery( forceDocument: params.forceDocument, silent: params.silent, mirror: params.mirror, + session: params.session, gatewayClientScopes: params.gatewayClientScopes, retryCount: 0, });
Vulnerability mechanics
AI mechanics synthesis has not run for this CVE yet.
References
6- github.com/openclaw/openclaw/commit/48aae82bbc19ba8b0741e61a08063eb0d1df464envdPatchWEB
- github.com/advisories/GHSA-r77c-2cmr-7p47ghsaADVISORY
- github.com/openclaw/openclaw/security/advisories/GHSA-r77c-2cmr-7p47nvdMitigationVendor AdvisoryWEB
- nvd.nist.gov/vuln/detail/CVE-2026-43583ghsaADVISORY
- www.vulncheck.com/advisories/openclaw-loss-of-group-tool-policy-context-in-delivery-queue-recoverynvdThird Party AdvisoryWEB
- github.com/openclaw/openclaw/pull/66025ghsaWEB
News mentions
0No linked articles in our index yet.