Is ChatGPT Assistant - GPT Search safe?

Medium risk

ChatGPT Assistant - GPT Search sends everything you type into Google, Bing and other search engines to a third-party server, not to ChatGPT.

When you search on Google, Bing, DuckDuckGo, Yahoo, Baidu, Kagi, Yandex, Naver, Brave or Searx, the extension reads your typed query and sends it to search-chat.ai along with a hardcoded API key, then displays that response in a sidebar styled as a ChatGPT answer. The genuine call to OpenAI's ChatGPT backend is present in the code but never used; a 'Continue Chat Thread' link points to a fixed, fake conversation ID rather than a real OpenAI session.

Master Toolsv1.0.0Chrome Web Store
45Risk
Who publishes it

Master Tools - 1 other listing from the same operator, 1 of them carrying a finding

What this publisher told the store about itself, and the other listings that told it the same thing.

Publisher
Master Tools

Same store account

1 other listing published from this account, 100k+ users between them. 1 of them carries a finding.

Shared hosts - 1 hostname

Hostnames hardcoded in this extension that few other listings call. That can mean one operator behind both, and it can equally mean a small shared vendor, so it is context rather than a conclusion. Hosts that many listings call are left out: they are services, not connections.

search-chat.ai
Also called by 1 other listing: Search & Chat AI

AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.

Publishers can request a review.

Findings

SeverityHIGH
ClassUNWANTED
TypeUnexpected
CWECWE-200
SourceAI FOUND

ChatGPT search extension proxies queries through an undisclosed backend

Code analysis shows the extension reads your typed query on Google, Bing and eight other search engines, sends it to search-chat.ai with a hardcoded key, then shows that reply as a ChatGPT answer with a constant, non-real conversation ID.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You type a search on Google, Bing, DuckDuckGo, Yahoo, Baidu, Kagi, Yandex, Naver, Brave, or a Searx instance and the extension's inline answer panel activates.

The extension did this

content.js reads your typed query and bg.js sends it to search-chat.ai with a hardcoded key, then shows that reply as the ChatGPT answer.

The real request to chatgpt.com/backend-api/conversation is present in the code but is commented out and never runs.

02EvidenceFIELD TABLE
What the request to search-chat.ai carries
FieldValueWhy it matters
Your search query
best noise cancelling headphones under $200The exact text you typed into the search box is sent to search-chat.ai as plain text.
Vendor API key
key=VuCP8hvfZNh23ksGphx3CuLNA fixed key baked into the extension authenticates every request; the same key ships in every install.
Conversation ID shown to you
122hhbd-sjdhsgdThe reply always carries the same constant ID, not a real ChatGPT conversation, so the linked thread never opens an actual OpenAI session.
03EvidenceCODE COMPARE
The code that does this

The commented-out ChatGPT call next to the live search-chat.ai proxy

What it actually does
content.js, query capture, renamed and annotatedscripts/content.js (annotated)
function runSearchCapture() {
  // engineConfig (was Mu) is looked up earlier by matching location.hostname
  // against a table of ~10 search engines (google, bing, yahoo, duckduckgo,
  // baidu, kagi, yandex, naver, brave, searx).
  if (!engineConfig) return false;
  const searchInput = querySelectorFromList(engineConfig.inputQuery);
  searchInput && searchInput.value && (async (typedQuery, engineConfig) => {
    // Builds and mounts the sidebar DOM node into the search results page.
    const sidebarWrapper = document.createElement("section");
    const sidebarRoot = document.createElement("div");
    sidebarWrapper.appendChild(sidebarRoot);
    sidebarWrapper.className = "chat-gpt-container";

    const settings = await getUserSettings();
    sidebarWrapper.classList.add(
      (settings.theme === "auto" ? systemPrefersDark() : settings.theme) === "dark"
        ? "gpt-dark"
        : "gpt-light"
    );

    const sidebarContainer = querySelectorFromList(engineConfig.sidebarContainerQuery);
    if (sidebarContainer) {
      sidebarContainer.getElementsByClassName(sidebarWrapper.className)[0]?.remove();
      sidebarContainer.prepend(sidebarWrapper);
    } else {
      sidebarWrapper.classList.add("sidebar-free");
      const appendTarget = querySelectorFromList(engineConfig.appendContainerQuery);
      if (appendTarget) {
        appendTarget.getElementsByClassName(sidebarWrapper.className)[0]?.remove();
        appendTarget.appendChild(sidebarWrapper);
      }
    }

    // Mounts the sidebar React component with the TYPED SEARCH QUERY as its
    // `question` prop. This is the value that ends up at search-chat.ai.
    mountComponent(SidebarApp, {
      question: typedQuery,
      triggerMode: settings.triggerMode || "always"
    }, sidebarWrapper);
  })(searchInput.value, engineConfig);
}
bg.js, session token fetch and query proxy, renamed and annotatedscripts/bg.js (annotated)
async function fetchOpenAISessionToken() {
  // Fetches a REAL OpenAI access token from the user's own chat.openai.com
  // session cookie. This token is fetched but then never actually used to
  // call any OpenAI endpoint for the answer itself (see below).
  if (cachedToken.get(TOKEN_KEY)) return cachedToken.get(TOKEN_KEY);
  const sessionResp = await fetch("https://chat.openai.com/api/auth/session");
  if (sessionResp.status === 403) throw new Error("CLOUDFLARE");
  const sessionJson = await sessionResp.json().catch(() => ({}));
  if (!sessionJson.accessToken) throw new Error("UNAUTHORIZED");
  cachedToken.set(TOKEN_KEY, sessionJson.accessToken);
  return sessionJson.accessToken;
}

async function handleSidebarQuery(port, request) {
  // request.question is the raw text the user typed into the search box.
  const typedQuery = request.question;
  let openaiToken;
  try {
    openaiToken = await fetchOpenAISessionToken();
  } catch (err) {
    port.postMessage({ error: err.message });
    openaiToken = "";
  }

  // ... builds a full, realistic ChatGPT-shaped request body (model, message
  // history, timezone, client_contextual_info, etc) that is never sent ...

  // DEAD CODE: this is the real ChatGPT call. It is commented out in the
  // shipped extension and never executes.
  //
  //   const requirementsResp = await fetch(
  //     "https://chatgpt.com/backend-api/sentinel/chat-requirements",
  //     { method: "POST", headers: { Authorization: `Bearer ${openaiToken}`, ... } }
  //   );
  //   const requirementsToken = (await requirementsResp.json()).token;
  //   await streamFetch("https://chatgpt.com/backend-api/conversation", {
  //     method: "POST",
  //     headers: { Authorization: `Bearer ${openaiToken}`, ... },
  //     body: JSON.stringify(chatGptRequestBody),
  //     onMessage(streamChunk) { /* forwards real ChatGPT tokens to the sidebar */ }
  //   });

  // LIVE CODE: instead of the block above, every query is proxied through a
  // third-party endpoint with a key hardcoded into every install.
  const response = await fetch(
    "https://search-chat.ai/api/search.php?" +
      new URLSearchParams({
        q: typedQuery,
        key: "VuCP8hvfZNh23ksGphx3CuLN"
      })
  );
  const result = await response.json();

  // The sidebar is told this came from a ChatGPT conversation, but the id is
  // a hardcoded constant, not a real OpenAI conversation id.
  port.postMessage({
    text: result.text,
    messageId: 12,
    conversationId: "122hhbd-sjdhsgd"
  });
  port.postMessage({ event: "DONE" });
}
04EvidenceARTIFACT
Reproduce it yourself

Sends a search query to the same search-chat.ai endpoint and hardcoded key the extension uses, so you can see the raw third-party reply independent of any real ChatGPT session.

RequiresNode.js 18+ (built-in fetch)
search-chat-proxy-check.js · js
#!/usr/bin/env node
// search-chat-proxy-check.js
//
// Sends a search query to the same endpoint and hardcoded key that
// gjfkjdaeefjopkbbdbbbmjkmopjpkakn's background service worker uses in
// place of a real ChatGPT call, so you can see the raw third-party
// response independent of any OpenAI account or session.
//
// Usage: node search-chat-proxy-check.js "your test query"

const HARDCODED_KEY = "VuCP8hvfZNh23ksGphx3CuLN"; // read from the extension's bg.js
const query = process.argv[2] || "test query for verification";

const url =
  "https://search-chat.ai/api/search.php?" +
  new URLSearchParams({ q: query, key: HARDCODED_KEY }).toString();

(async () => {
  console.log("Requesting:", url);
  const res = await fetch(url);
  console.log("HTTP status:", res.status);
  const body = await res.json().catch(() => null);
  console.log("Response body:", JSON.stringify(body, null, 2));
  console.log(
    "\nThe extension shows this response as a ChatGPT answer. It never " +
      "sends this query to https://chatgpt.com/backend-api/conversation; " +
      "that call exists in bg.js only as commented-out, unused code."
  );
})();
How to run it
  1. 1
    node search-chat-proxy-check.js "your test query"
05EvidencePLAIN NOTE
Observation

Static analysis finding. This behaviour was identified by reading the shipped extension code and has not yet been reproduced in a live run. The trigger conditions and the exact data sent are read from the code, not from an observed capture.

What it can do

Permissions this extension asks for, as declared in version 1.0.0. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.

  • Read and change your data on every site you visit

    <all_urls>

  • Store data in your browser

    storage

  • Add items to the right-click menu

    contextMenus

  • Block and redirect the requests your browser makes

    declarativeNetRequest

  • Act on the current tab, but only after you click the extension

    activeTab

Where it sends data

Destinations our analysis observed ChatGPT Assistant - GPT Search 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.

  • search-chat.ai

    ChatGPT Assistant - GPT Search sends data to search-chat.ai. One other extension we have analysed sends data here.

Updated 30 September 2026gjfkjdaeefjopkbbdbbbmjkmopjpkakn