Is Summary Webpage - Summarize Youtube videos | AI - Assistant safe?
Summary Webpage extracts the full article text of the active page and sends it to Hugging Face AI servers using hardcoded API tokens.
When you click the toolbar button on any page, the extension reads the full readable article text via Mozilla Readability and forwards up to 14,000 characters to Hugging Face's inference router (cerebras provider, Qwen3-32B model) to generate a summary. Although the UI is labelled 'Summary with ChatGPT' and offers an OpenAI login, the active summarisation path always routes page content to Hugging Face and ignores any OpenAI key you enter. The requests are authenticated with one of 13 Hugging Face API tokens embedded in the shipped code, which rotate when rate-limited.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Page content sent to HuggingFace for summaries
Summarizing a page sends its readable text to HuggingFace's router for a Cerebras chat completion.
The worker embeds HuggingFace tokens, adds the stored/default prompt, truncates text past 14,000 characters, sends it to Qwen/Qwen3-32B.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-522
- Source
- Dynamic sandbox
You ask the extension to summarize the page you are reading.
The extension forwards the page text to an external AI inference service.
- Page textSummarise the following article in bullet points: The city council approved a new transit budget after a three-hour meeting. (illustrative page text)
Text from the page you chose to summarize: article text, transcript text, internal pages, or other readable content on that page.
- Summary promptSummarise the following article in bullet points:
The instruction that shapes the answer is sent with the page text.
- Embedded API tokenhf_<redacted>
The request uses a token bundled inside the extension rather than a token you provide.
- Model selectionQwen/Qwen3-32B via provider cerebras
The request names the external AI model that receives the prompt.
- Content-Type
- application/json
- Authorization
- Bearer hf_<redacted>
The shipped worker sends page text through HuggingFace chat completion
Readable content-script equivalent
deobfuscated/javascripts/script.jsfunction summarizeReadableText(readableText) { let finalSummary; const port = chrome.runtime.connect(); port.onMessage.addListener((message) => { if (message.event === "DONE") { stopLoading(); showSummaryHeader(); showFooter(); document.getElementById("readergpt__shadowRoot").shadowRoot.getElementById("copyBtn").addEventListener("click", () => { navigator.clipboard.writeText(finalSummary); }); return; } if (message.text) { showSummaryText(message.text); finalSummary = message.text; return; } if (message.error) { stopLoading(); showError(message.error); } }); hideLoginAndHeader(); showLoadingState(); port.postMessage({ pageContent: readableText });}if (readabilityResult && readabilityResult.textContent) { summarizeReadableText(readabilityResult.textContent);} else { showWarning("No readable text found on the page.");}Readable worker equivalent
deobfuscated/javascripts/worker.jschrome.runtime.onConnect.addListener((port) => { port.onMessage.addListener(async (message) => { const promptAndPageText = await buildPrompt(message.pageContent); try { let accumulatedText = ""; for await (const chunk of summarizeWithHuggingFace(promptAndPageText)) { accumulatedText += chunk; await port.postMessage({ text: accumulatedText, messageId: crypto.randomUUID(), conversationId: crypto.randomUUID() }); } await port.postMessage({ event: "DONE" }); } catch (error) { port.postMessage({ error: error.message }); } });});async function buildPrompt(pageContent) { if (pageContent.length > 14000) { pageContent = pageContent.slice(0, 14000); } const prompt = await chrome.storage.local.get("summary_prompt").then((stored) => { return stored && stored.summary_prompt ? stored.summary_prompt : "Summarise the following article in bullet points:"; }); return `${prompt} ${pageContent}`;}Readable HuggingFace completion equivalent
deobfuscated/javascripts/worker.jsconst HUGGINGFACE_TOKENS = [ "hf_<redacted>", "hf_<redacted>", "hf_<redacted>", "hf_<redacted>", "hf_<redacted>", "hf_<redacted>", "hf_<redacted>", "hf_<redacted>", "hf_<redacted>", "hf_<redacted>", "hf_<redacted>", "hf_<redacted>", "hf_<redacted>"];async function* summarizeWithHuggingFace(promptAndPageText, triedTokens = []) { const availableTokens = HUGGINGFACE_TOKENS.filter((token) => !triedTokens.includes(token)); if (!availableTokens.length) { throw new Error("Rate limit reached. You reached free usage limit"); } const token = availableTokens[Math.floor(Math.random() * availableTokens.length)]; try { const client = new InferenceClient(token); const response = await client.chatCompletion({ provider: "cerebras", model: "Qwen/Qwen3-32B", messages: [ { role: "user", content: promptAndPageText } ] }); if (response && response.choices[0]) { yield response.choices[0].message.content.replace(/<think>[\s\S]*<\/think>/g, "").slice(1, -1).slice(1, -1); } } catch (error) { yield* summarizeWithHuggingFace(promptAndPageText, triedTokens.concat(token)); }}- router.huggingface.co
Receives the POST request from the bundled HuggingFace client and routes it to the selected inference provider.
Page text is sent to AI services for summaries
Clicking summarize sends the page's text from the content script to the service worker, which prepends the summary prompt, keeps up to 14,000 characters, forwards it to an AI endpoint.
A traffic run never triggered this; no body captured.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
You click the extension's summary action on a web page.
The extension extracts the page's readable text and sends it to an external AI service for summarization.
- Page textThe tower is 324 metres tall and was the tallest structure in Paris (illustrative)
This is the readable copy from the page you are viewing, including article text, headings, and other visible page content.
- Summary promptSummarise the following article in bullet points:
This tells the AI service what to do with the page text you requested to summarize.
- Character limit14000
The extension can send a substantial portion of the page in one request rather than just the title or URL.
The HuggingFace inference client returns a chat completion; the extension streams the returned text back into the page overlay.
- Content-Type
- application/json
- Authorization
- Bearer <redacted>
The content script extracts page text and sends it to the service worker
Same shipped content script after deobfuscation
javascripts/script.jsvar e = i(107);i.n(e);let t = "readergpt__shadowRoot";var a = new e.Readability(document.cloneNode(!0)).parse();a && a.textContent ? function(e) { let t, i = chrome.runtime.connect(); i.onMessage.addListener((e => { if (e.text) { t = e.text; } })); i.postMessage({ pageContent: e });}(a.textContent) : r("No readable text found on the page.");The service worker builds the AI prompt and calls HuggingFace/Cerebras
Request construction in the bundled HuggingFace client
javascripts/worker.jsfunction En(e, t, n, a, i) { const {accessToken: o, endpointUrl: r, provider: s, model: l, ...c} = n, p = t.provider, {includeCredentials: d, task: u, signal: m, billTo: f} = i ?? {}, h = (() => { if (t.clientSideRoutingOnly) { if (o && o.startsWith("hf_")) throw new Error(`Provider ${p} is closed-source and does not support HF tokens.`); return "provider-key"; } return o ? o.startsWith("hf_") ? "hf-token" : "provider-key" : "include" === d ? "credentials-include" : "none"; })(), g = r ?? e, y = t.makeUrl({ authMethod: h, model: g, task: u }), b = t.prepareHeaders({ accessToken: o, authMethod: h }, "data" in n && !!n.data); f && (b["X-HF-Bill-To"] = f); const w = [ "@huggingface/inference/3.13.1", "undefined" != typeof navigator ? navigator.userAgent : void 0 ].filter((e => void 0 !== e)).join(" " ); b["User-Agent"] = w; const v = t.makeBody({ args: c, model: e, task: u, mapping: a }); let x; return "string" == typeof d ? x = d : !0 === d && (x = "include"), { url: y, info: { headers: b, method: "POST", body: v, ...x ? { credentials: x } : void 0, signal: m } };}- router.huggingface.co
Receives the chat-completion request routed to the Cerebras provider for page summarization.
- chat.openai.com
Used by the extension for ChatGPT session access and feedback requests when the ChatGPT login path is used.
Where it sends data
Destinations our analysis observed Summary Webpage contacting. Sending data somewhere is not a finding on its own - an extension that syncs your settings has to talk to its own server - but it is where your data can go, and who else it goes to.
- router.huggingface.co
Summary Webpage sends data to router.huggingface.co. No other extension we have analysed sends data here.