Is MindStudio safe?
MindStudio is high risk. When the MindStudio side panel requests launch variables, the content script reads page URL, selected content, cleaned HTML, page text, and metadata, then messages it to an app.mindstudio.ai frame. One run failed to capture the HTTP body.
Who publishes itGoMeta, Inc. - no other listings under this identity
GoMeta, Inc. - no other listings under this identity
What this publisher told the store about itself, and the other listings that told it the same thing.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
MindStudio forwards page DOM and metadata to its iframe
When the MindStudio side panel requests launch variables, the content script reads page URL, selected content, cleaned HTML, page text, and metadata, then messages it to an app.mindstudio.ai frame.
One run failed to capture the HTTP body.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
You use the MindStudio side panel on a web page.
The side panel asks the content script for launch variables tied to the active tab.
The extension reads page content and forwards the bundle to the MindStudio app iframe.
The bundle includes the current URL, selected content, cleaned HTML, full text, metadata, and optional PDF rehosting path.
- Page URLhttps://intranet.example.com/projects/q3-roadmap?view=private
This identifies the exact page where you used the side panel.
- Selected contentRenewal quote: ACME-2026-07
If you selected text or form content, that selected fragment can be included in the bundle.
- Cleaned page HTML<main><h1>Q3 roadmap</h1><p>Launch date: July 31</p></main>
This can reveal the structure and visible contents of the page you are viewing.
- Full page textQ3 roadmap Launch date: July 31 Owner: Product Operations
This captures the visible text from the page, not just the part you typed into MindStudio.
- Page metadata{"title":"Q3 Roadmap","description":"Internal planning page"}
Titles, descriptions, Open Graph tags, icons, colors, and fonts add context about the page and site.
- app.mindstudio.ai
Embedded MindStudio app iframe that receives launchVariables from the extension side panel.
The side panel requests launch variables and forwards them to the app iframe
Readable side-panel request and forward path from deobfuscated sidepanel.js
sidepanel.jsn.listen("remote/request_launch_variables", (async () => { console.info("[MindStudio][Sidepanel] Sidepanel frame requested launch variables for current page"), chrome.tabs.query({ active: !0, currentWindow: !0 }, (async e => { if (e.length > 0 && e[0].id) { console.info(`[MindStudio][Sidepanel] Sending launch variable request to content script on tab: ${e[0].id}`); try { await chrome.tabs.sendMessage(e[0].id, { type: "@@mindstudio/remote/request_launch_variables", _MindStudioEvent: "@@mindstudio/remote/request_launch_variables" }) } catch (e) { console.info("[MindStudio][Sidepanel] Failed to get launch variables from tab, sending default", e), n.send(u.ElementId.FRAME, "remote/resolved_launch_variables", { launchVariables: { url: "", rawHtml: "", fullText: "", metadata: "", userSelection: null } }) } } }))})), t.listen("launcher/resolved_launch_variables", (e => { console.info("[MindStudio][Sidepanel] Received launch variables for current page, sending to history frame"); const { launchVariables: t } = e; n.send(u.ElementId.FRAME, "remote/resolved_launch_variables", { launchVariables: t })}))Readable iframe creation from deobfuscated sidepanel.js
sidepanel.jssuper({ id: u.ElementId.FRAME, src: `${e}${i}?__displayContext=extension&__controlledAuth=1`, container: t}), this.tabId = n, this.element.style.cssText = "\n width: 100%;\n height: 100%;\n border: none;\n overflow: hidden;\n ", this.setupEventListeners()The content script collects URL, DOM, text, and metadata
Readable launch-variable handler from deobfuscated content.js
content.jsh.listen("remote/request_launch_variables", (async () => { console.info("[MindStudio][Launcher] Side panel requested launch variables"); const t = S.getSelectedContent(), e = S.cleanDOM(), n = S.getCleanTextContent(), i = S.getMetadataBundle(); let s; (window.location.href.endsWith(".pdf") || document.querySelector("embed")?.type.includes("pdf")) && (console.info("Rehosting PDF for extraction"), s = await S.getRehostedPdfSecurePath()); const a = { url: window.location.href, userSelection: t, rawHtml: e, fullText: n, metadata: i, _rehostedPdfPath: s }; console.info("[MindStudio][Launcher] Sending launch variables to side panel", a), h.send("launcher/resolved_launch_variables", { launchVariables: a })}))Readable extractor object from deobfuscated content.js
content.js const S = { async getRehostedPdfSecurePath() { const t = await fetch(""), e = await t.blob(), { fields: n, path: i, url: s } = await w.getSignedUploadUrl(), a = new FormData; return Object.keys(n).forEach((t => { a.append(t, n[t]) })), a.append("file", e), await w.uploadFile(s, a), i }, getSelectedContent() { try { const t = window.getSelection(); if (!t || !t.rangeCount) return null; const e = document.activeElement; if (e && ("TEXTAREA" === e.tagName || "INPUT" === e.tagName)) { const { selectionStart: t, selectionEnd: n, value: i } = e; return i.substring(t ?? 0, n ?? 0) } const n = t.getRangeAt(0), i = document.createElement("div"); return i.appendChild(n.cloneContents()), i.innerHTML } catch { return null } }, cleanDOM() { const t = document.body.cloneNode(!0); return b(t), t.innerHTML }, getCleanTextContent() { const t = window.getSelection(); if (t) { const e = document.createRange(); e.selectNode(document.body), t.removeAllRanges(), t.addRange(e); const n = t.toString(); return t.removeAllRanges(), n } const e = document.body.cloneNode(!0); return b(e), e.innerText }, getMetadataBundle() { const t = (t, e = "property") => { const n = [...document.getElementsByTagName("meta")].find((n => n.getAttribute(e) === t)); return n ? n.content : null }, e = { title: t("og:title") || document.title, description: t("og:description") || t("description", "name") || "", openGraphImage: t("og:image") || "", openGraphTags: [...document.getElementsByTagName("meta")].filter((t => t.getAttribute("property")?.startsWith("og:"))).reduce(((t, e) => { const n = e.getAttribute("property"); return n && (t[n] = e.content), t }), {}), favicon: (() => { const t = [...document.getElementsByTagName("link")].filter((t => t.getAttribute("rel") && t.getAttribute("rel")?.includes("icon"))); return t.sort(((t, e) => { const n = parseInt(t.getAttribute("sizes")?.split("x")[0] || "0"); return parseInt(e.getAttribute("sizes")?.split("x")[0] || "0") - n })), t.length > 0 ? t[0].href : null })(), brand: this.getBrandBundle() }; return JSON.stringify(e, null, 2) }, getBrandBundle() { const t = t => { const e = {}; return document.querySelectorAll("*").forEach((n => { let i = getComputedStyle(n)[t]; i && "rgba(0, 0, 0, 0)" !== i && "transparent" !== i && ("color" !== t && "backgroundColor" !== t || (i = (t => { const e = t.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/); if (!e) return t; const n = parseInt(e[1], 10), i = parseInt(e[2], 10), s = parseInt(e[3], 10), a = void 0 !== e[4] ? parseFloat(e[4]) : 1, o = t => t.toString(16).padStart(2, "0"), r = `#${o(n)}${o(i)}${o(s)}`; return a < 1 ? `${r}${o(Math.round(255*a))}` : r })(i)), e[i] = (e[i] || 0) + 1) })), Object.entries(e).map((([t, e]) => ({ value: t, count: e }))).sort(((t, e) => e.count - t.count)) }; return { fonts: t("fontFamily").slice(0, 5), textColors: t("color").slice(0, 5), backgroundColors: t("backgroundColor").slice(0, 5) } } };What it can do
Permissions this extension asks for, as declared in version 0.7.16. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.
Store data in your browser
storage
Act on the current tab, but only after you click the extension
activeTab
Show a panel beside the page
sidePanel
Show you desktop notifications
notifications