CVE-2026-45244
Description
Summarize prior to 0.15.1 contains a missing authorization vulnerability that allows attackers to execute browser automation actions without per-call user approval when the extension automation feature is enabled. Attackers can influence the agent through malicious page or summary content to invoke enabled extension automation tools such as navigation or debugger-backed actions, bypassing the final user approval step when a user interacts with attacker-controlled content.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Summarize extension prior to 0.15.1 missing per-call authorization for browser automation tools, allowing attacker-controlled content to trigger privileged actions without user approval.
Vulnerability
The Summarize Chrome extension prior to version 0.15.1 contains a missing authorization vulnerability (CWE-862) in its browser automation feature. When automation is enabled, the chat agent loop directly executes tool calls returned by the model without requiring per-call user confirmation. This allows attacker-controlled page or summary content to influence the agent into invoking enabled automation tools such as navigation or debugger-backed actions. Affected versions are all releases before 0.15.1 [1][2][4].
Exploitation
An attacker must craft malicious page or summary content that is included in the extension's chat context. The user must have the extension automation feature enabled and interact with the attacker-controlled content (e.g., by visiting a malicious page or using a manipulated summary). The attacker does not need authentication or network position beyond serving the malicious content. The sequence involves the model returning a tool call based on the influenced context, and the extension executing it without a final user approval step [1][4].
Impact
Successful exploitation allows the attacker to execute browser automation actions, such as navigation or debugger-backed operations (e.g., eval), bypassing the intended per-call user approval. This can lead to information disclosure, privilege escalation within the browser/extension context, or further compromise of the user's browsing session [1][4].
Mitigation
The vulnerability is fixed in version 0.15.2, released on 2026-05-17. The fix introduces an explicit user confirmation prompt for every automation tool call via a confirmToolCall hook in the chat agent loop [1][3]. Users should update to 0.15.2 or later. If updating is not possible, disabling the extension automation feature mitigates the risk, as the vulnerable code path is only reachable when automation is enabled [4].
- [security] fix(extension): confirm automation tool calls by Hinotoi-agent · Pull Request #219 · steipete/summarize
- [security] fix(extension): confirm automation tool calls (#219) · steipete/summarize@e64fe3e
- Release v0.15.2 · steipete/summarize
- Summarize < 0.15.1 Unapproved Browser Automation Execution
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2Patches
1e64fe3ecd1bb[security] fix(extension): confirm automation tool calls (#219)
3 files changed · +178 −1
apps/chrome-extension/src/entrypoints/sidepanel/chat-agent-loop.ts+25 −0 modified@@ -8,6 +8,7 @@ export async function runChatAgentLoop({ chatController, chatSession, createStreamingAssistantMessage, + confirmToolCall, executeToolCall, getAutomationToolNames, hasDebuggerPermission, @@ -37,6 +38,7 @@ export async function runChatAgentLoop({ ) => Promise<{ ok: boolean; assistant?: Message; error?: string }>; }; createStreamingAssistantMessage: () => ChatMessage; + confirmToolCall?: (call: ToolCall) => boolean | Promise<boolean>; executeToolCall: (call: ToolCall) => Promise<ToolResultMessage>; getAutomationToolNames: () => string[]; hasDebuggerPermission: () => Promise<boolean>; @@ -96,6 +98,29 @@ export async function runChatAgentLoop({ for (const call of toolCalls) { if (chatSession.isAbortRequested()) return; + if (confirmToolCall) { + const confirmed = await confirmToolCall(call); + if (!confirmed) { + const toolCallId = + (call as { toolCallId?: string; id?: string }).toolCallId ?? + (call as { id?: string }).id ?? + `${call.name}-${Date.now()}`; + chatController.addMessage( + wrapMessage({ + role: "toolResult", + toolCallId, + toolName: call.name, + content: [ + { type: "text", text: `Tool call ${call.name} was cancelled by the user.` }, + ], + isError: true, + timestamp: Date.now(), + }), + ); + scrollToBottom(true); + continue; + } + } if (call.name === "navigate") { const args = call.arguments as { url?: string }; markAgentNavigationIntent(args?.url);
apps/chrome-extension/src/entrypoints/sidepanel/main.ts+18 −1 modified@@ -1,4 +1,4 @@ -import type { Message, ToolCall } from "@mariozechner/pi-ai"; +import type { Message, ToolCall, ToolResultMessage } from "@mariozechner/pi-ai"; import { extractYouTubeVideoId } from "@steipete/summarize-core/content/url"; import MarkdownIt from "markdown-it"; import { executeToolCall, getAutomationToolNames } from "../../automation/tools"; @@ -1530,11 +1530,28 @@ function seedPlannedSlidesForRun(run: RunStart) { return true; } +function describeAutomationToolCall(call: ToolCall): string { + const args = call.arguments ? JSON.stringify(call.arguments, null, 2) : "{}"; + return `${call.name}\n\n${args}`; +} + +async function confirmAutomationToolCall(call: ToolCall): Promise<boolean> { + return window.confirm( + [ + "Summarize agent wants to run an automation tool.", + "Only approve this if you expected the current task to control the browser or extension automation.", + "", + describeAutomationToolCall(call), + ].join("\n"), + ); +} + async function runAgentLoop() { await runChatAgentLoop({ automationEnabled: automationEnabledValue, chatController, chatSession, + confirmToolCall: confirmAutomationToolCall, createStreamingAssistantMessage: buildStreamingAssistantMessage, executeToolCall: async (call) => (await executeToolCall(call)) as ToolResultMessage, getAutomationToolNames,
tests/sidepanel.chat-agent-loop-security.test.ts+135 −0 added@@ -0,0 +1,135 @@ +import { describe, expect, it, vi } from "vitest"; +import { runChatAgentLoop } from "../apps/chrome-extension/src/entrypoints/sidepanel/chat-agent-loop.js"; + +function buildHarness({ + confirmToolCall, + toolCall = { + type: "toolCall", + id: "call-1", + name: "debugger", + arguments: { action: "eval", expression: "document.body.innerText" }, + }, +}: { + confirmToolCall?: () => Promise<boolean> | boolean; + toolCall?: { + type: "toolCall"; + id: string; + name: string; + arguments: Record<string, unknown>; + }; +} = {}) { + const executeToolCall = vi.fn(async (call) => ({ + role: "toolResult" as const, + toolCallId: call.id, + toolName: call.name, + content: [{ type: "text" as const, text: "executed" }], + isError: false, + timestamp: Date.now(), + })); + + const chatController = { + addMessage: vi.fn(), + buildRequestMessages: vi.fn(() => [ + { + role: "user", + content: "Summarize this page with attacker-controlled content.", + timestamp: Date.now(), + }, + ]), + finishStreamingMessage: vi.fn(), + removeMessage: vi.fn(), + replaceMessage: vi.fn(), + updateStreamingMessage: vi.fn(), + }; + + let calls = 0; + const chatSession = { + isAbortRequested: () => false, + requestAgent: vi.fn(async () => { + calls += 1; + if (calls === 1) { + return { + ok: true, + assistant: { + role: "assistant", + content: [toolCall], + timestamp: Date.now(), + }, + }; + } + return { + ok: true, + assistant: { role: "assistant", content: "done", timestamp: Date.now() }, + }; + }), + }; + + return { + executeToolCall, + chatController, + chatSession, + args: { + automationEnabled: true, + summaryMarkdown: "Attacker-controlled page content can be included here.", + chatController, + chatSession, + createStreamingAssistantMessage: () => ({ + id: "streaming", + role: "assistant" as const, + content: "", + timestamp: Date.now(), + }), + executeToolCall, + getAutomationToolNames: () => [toolCall.name], + hasDebuggerPermission: async () => true, + markAgentNavigationIntent: vi.fn(), + markAgentNavigationResult: vi.fn(), + scrollToBottom: vi.fn(), + wrapMessage: (message: unknown) => ({ id: "wrapped", ...(message as object) }), + confirmToolCall, + }, + }; +} + +describe("chat agent automation tool confirmation", () => { + it("does not execute a dangerous tool call when confirmation is denied", async () => { + const confirmToolCall = vi.fn(async () => false); + const harness = buildHarness({ confirmToolCall }); + + await runChatAgentLoop(harness.args as never); + + expect(confirmToolCall).toHaveBeenCalledWith( + expect.objectContaining({ + name: "debugger", + arguments: { action: "eval", expression: "document.body.innerText" }, + }), + ); + expect(harness.executeToolCall).not.toHaveBeenCalled(); + expect(harness.chatController.addMessage).toHaveBeenCalledWith( + expect.objectContaining({ + role: "toolResult", + toolName: "debugger", + isError: true, + }), + ); + }); + + it("does not mark navigation intent before a denied navigate call", async () => { + const confirmToolCall = vi.fn(async () => false); + const harness = buildHarness({ + confirmToolCall, + toolCall: { + type: "toolCall", + id: "call-1", + name: "navigate", + arguments: { url: "https://example.com/phishing" }, + }, + }); + + await runChatAgentLoop(harness.args as never); + + expect(harness.args.markAgentNavigationIntent).not.toHaveBeenCalled(); + expect(harness.args.markAgentNavigationResult).not.toHaveBeenCalled(); + expect(harness.executeToolCall).not.toHaveBeenCalled(); + }); +});
Vulnerability mechanics
Root cause
"Missing authorization check before executing automation tool calls in the Chrome extension side-panel agent loop allows attacker-influenced tool calls to bypass per-call user approval."
Attack vector
An attacker crafts a malicious web page or summary content that, when processed by the Summarize extension's agent, causes the agent to invoke enabled automation tools (e.g., navigation, debugger-backed actions). The vulnerability is triggered when a user with the extension automation feature enabled interacts with this attacker-controlled content. Because the agent loop previously lacked a confirmation step [patch_id=424360], the tool call executes without the user's per-call approval, allowing the attacker to influence browser automation actions such as navigating to a phishing URL or executing arbitrary JavaScript via the debugger.
Affected code
The vulnerability exists in `apps/chrome-extension/src/entrypoints/sidepanel/chat-agent-loop.ts` where the `runChatAgentLoop` function iterates over tool calls without a confirmation gate. The entry point `apps/chrome-extension/src/entrypoints/sidepanel/main.ts` also lacked a confirmation mechanism when invoking `runChatAgentLoop`. The patch adds a `confirmToolCall` parameter and wires it to a `window.confirm` dialog in `main.ts`.
What the fix does
The patch introduces a `confirmToolCall` callback parameter in `chat-agent-loop.ts` [patch_id=424360]. Before any automation tool call is executed, the loop now awaits the result of `confirmToolCall(call)`. If the user denies confirmation, a cancelled-by-user tool result is recorded and the tool call is skipped. In `main.ts` [patch_id=424360], the `confirmAutomationToolCall` function is wired to `window.confirm()`, displaying the tool name and arguments to the user. This ensures that every automation tool invocation requires explicit per-call user consent, closing the missing authorization gap [CWE-862].
Preconditions
- configThe extension's automation feature must be enabled (automationEnabled: true).
- inputThe user must interact with attacker-controlled page content or summary content that the agent processes.
- authNo authentication is required; the attacker can be remote and unauthenticated.
Reproduction
The public PoC reference at https://github.com/steipete/summarize/pull/219 shows the fix but does not include standalone reproduction steps. To reproduce, enable the extension automation feature, visit an attacker-controlled page containing content that causes the agent to request an automation tool call (e.g., a debugger eval or navigate action), and observe that the tool call executes without a confirmation dialog.
Generated on May 19, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4- github.com/steipete/summarize/commit/e64fe3ecd1bb4fdc181dcfa88c96b9e1914ced0envdPatch
- github.com/steipete/summarize/pull/219nvdExploitIssue TrackingPatch
- www.vulncheck.com/advisories/summarize-unapproved-browser-automation-executionnvdThird Party Advisory
- github.com/steipete/summarize/releases/tag/v0.15.2nvdRelease Notes
News mentions
0No linked articles in our index yet.