VYPR
Medium severity6.5GHSA Advisory· Published May 5, 2026· Updated May 7, 2026

CVE-2026-43568

CVE-2026-43568

Description

OpenClaw versions 2026.4.5 before 2026.4.10 contain a privilege escalation vulnerability allowing write-scoped operators to modify persistent memory dreaming settings. Attackers with write-scoped gateway access can toggle admin-class configuration mutations through the /dreaming endpoint to escalate privileges.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
openclawnpm
>= 2026.4.5, < 2026.4.102026.4.10

Affected products

2
  • OpenClaw/Openclaw2 versions
    cpe:2.3:a:openclaw:openclaw:*:*:*:*:*:node.js:*:*+ 1 more
    • cpe:2.3:a:openclaw:openclaw:*:*:*:*:*:node.js:*:*range: >=2026.4.5,<2026.4.10
    • (no CPE)range: >= 2026.4.5, < 2026.4.10

Patches

1
6af17b39e11f

fix(dreaming): require admin for persistent gateway toggle (#63872)

https://github.com/openclaw/openclawMarianoApr 9, 2026via ghsa
5 files changed · +76 3
  • CHANGELOG.md+1 0 modified
    @@ -31,6 +31,7 @@ Docs: https://docs.openclaw.ai
     - Gateway/startup: keep WebSocket RPC available while channels and plugin sidecars start, hold `chat.history` unavailable until startup sidecars finish so synchronous history reads cannot stall startup (reported in #63450), refresh advertised gateway methods after deferred plugin reloads, and enforce the pre-auth WebSocket upgrade budget before the no-handler 503 path so upgrade floods cannot bypass connection limits during that window. (#63480) Thanks @neeravmakwana.
     - Gateway/tailscale: start Tailscale exposure and the gateway update check before awaiting channel and plugin sidecar startup so remote operators are not locked out when startup sidecars stall.
     - QQBot/streaming: make block streaming configurable per QQ bot account via `streaming.mode` (`"partial"` | `"off"`, default `"partial"`) instead of hardcoding it off, so responses can be delivered incrementally. (#63746)
    +- Dreaming/gateway: require `operator.admin` for persistent `/dreaming on|off` changes and treat missing gateway client scopes as unprivileged instead of silently allowing config writes. (#63872) Thanks @mbelinky.
     
     ## 2026.4.9
     
    
  • extensions/memory-core/src/dreaming-command.test.ts+47 1 modified
    @@ -52,13 +52,17 @@ function createHarness(initialConfig: OpenClawConfig = {}) {
       };
     }
     
    -function createCommandContext(args?: string): PluginCommandContext {
    +function createCommandContext(
    +  args?: string,
    +  overrides?: Partial<Pick<PluginCommandContext, "gatewayClientScopes">>,
    +): PluginCommandContext {
       return {
         channel: "webchat",
         isAuthorizedSender: true,
         commandBody: args ? `/dreaming ${args}` : "/dreaming",
         args,
         config: {},
    +    gatewayClientScopes: overrides?.gatewayClientScopes,
         requestConversationBinding: async () => ({ status: "error", message: "unsupported" }),
         detachConversationBinding: async () => ({ removed: false }),
         getCurrentConversationBinding: async () => null,
    @@ -115,6 +119,48 @@ describe("memory-core /dreaming command", () => {
         expect(result.text).toContain("Dreaming disabled.");
       });
     
    +  it("blocks unscoped gateway callers from persisting dreaming config", async () => {
    +    const { command, runtime } = createHarness();
    +
    +    const result = await command.handler(
    +      createCommandContext("off", {
    +        gatewayClientScopes: [],
    +      }),
    +    );
    +
    +    expect(result.text).toContain("requires operator.admin");
    +    expect(runtime.config.writeConfigFile).not.toHaveBeenCalled();
    +  });
    +
    +  it("blocks write-scoped gateway callers from persisting dreaming config", async () => {
    +    const { command, runtime } = createHarness();
    +
    +    const result = await command.handler(
    +      createCommandContext("off", {
    +        gatewayClientScopes: ["operator.write"],
    +      }),
    +    );
    +
    +    expect(result.text).toContain("requires operator.admin");
    +    expect(runtime.config.writeConfigFile).not.toHaveBeenCalled();
    +  });
    +
    +  it("allows admin-scoped gateway callers to persist dreaming config", async () => {
    +    const { command, runtime, getRuntimeConfig } = createHarness();
    +
    +    const result = await command.handler(
    +      createCommandContext("on", {
    +        gatewayClientScopes: ["operator.admin"],
    +      }),
    +    );
    +
    +    expect(runtime.config.writeConfigFile).toHaveBeenCalledTimes(1);
    +    expect(resolveStoredDreaming(getRuntimeConfig())).toMatchObject({
    +      enabled: true,
    +    });
    +    expect(result.text).toContain("Dreaming enabled.");
    +  });
    +
       it("returns status without mutating config", async () => {
         const { command, runtime } = createHarness({
           plugins: {
    
  • extensions/memory-core/src/dreaming-command.ts+7 0 modified
    @@ -75,6 +75,10 @@ function formatUsage(includeStatus: string): string {
       ].join("\n");
     }
     
    +function requiresAdminToMutateDreaming(gatewayClientScopes?: readonly string[]): boolean {
    +  return Array.isArray(gatewayClientScopes) && !gatewayClientScopes.includes("operator.admin");
    +}
    +
     export function registerDreamingCommand(api: OpenClawPluginApi): void {
       api.registerCommand({
         name: "dreaming",
    @@ -102,6 +106,9 @@ export function registerDreamingCommand(api: OpenClawPluginApi): void {
           }
     
           if (firstToken === "on" || firstToken === "off") {
    +        if (requiresAdminToMutateDreaming(ctx.gatewayClientScopes)) {
    +          return { text: "⚠️ /dreaming on|off requires operator.admin for gateway clients." };
    +        }
             const enabled = firstToken === "on";
             const nextConfig = updateDreamingEnabledInConfig(currentConfig, enabled);
             await api.runtime.config.writeConfigFile(nextConfig);
    
  • src/gateway/server-methods/chat.directive-tags.test.ts+20 1 modified
    @@ -207,7 +207,7 @@ function extractFirstTextBlock(payload: unknown): string | undefined {
     }
     
     function createScopedCliClient(
    -  scopes: string[],
    +  scopes?: string[],
       client: Partial<{
         id: string;
         mode: string;
    @@ -1414,6 +1414,25 @@ describe("chat directive tag stripping for non-streaming final payloads", () =>
         expect(mockState.lastDispatchCtx?.CommandBody).toBe("/scopecheck");
       });
     
    +  it("normalizes missing gateway caller scopes to an empty array before dispatch", async () => {
    +    createTranscriptFixture("openclaw-chat-send-missing-gateway-client-scopes-");
    +    mockState.finalText = "ok";
    +    const respond = vi.fn();
    +    const context = createChatContext();
    +
    +    await runNonStreamingChatSend({
    +      context,
    +      respond,
    +      idempotencyKey: "idem-gateway-client-scopes-missing",
    +      message: "/scopecheck",
    +      client: createScopedCliClient(),
    +      expectBroadcast: false,
    +    });
    +
    +    expect(mockState.lastDispatchCtx?.GatewayClientScopes).toEqual([]);
    +    expect(mockState.lastDispatchCtx?.CommandBody).toBe("/scopecheck");
    +  });
    +
       it("injects ACP system provenance into the agent-visible body", async () => {
         createTranscriptFixture("openclaw-chat-send-system-provenance-acp-");
         mockState.finalText = "ok";
    
  • src/gateway/server-methods/chat.ts+1 1 modified
    @@ -1671,7 +1671,7 @@ export const chatHandlers: GatewayRequestHandlers = {
             SenderId: clientInfo?.id,
             SenderName: clientInfo?.displayName,
             SenderUsername: clientInfo?.displayName,
    -        GatewayClientScopes: client?.connect?.scopes,
    +        GatewayClientScopes: client?.connect?.scopes ?? [],
           };
     
           const agentId = resolveSessionAgentId({
    

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

News mentions

0

No linked articles in our index yet.