Is QuestionAI Homework Powered AI Assistant safe?
QuestionAI is high risk. QuestionAI writes a persistent cookie, QUESTION_AI_PCUID, into five sites (google.com, baidu.com, facebook.com, youtube.com, instagram.com), same value each. Expires in ~100 years, not HttpOnly. Lands automatically, no visit needed.…
Who publishes itD3 DIMENSION TECHNOLOGY PTE. LTD. - no other listings under this identity, 1 shared hostname
D3 DIMENSION TECHNOLOGY PTE. LTD. - no other listings under this identity, 1 shared hostname
What this publisher told the store about itself, and the other listings that told it the same thing.
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.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Tracking Cookie Written to Google, Facebook, YouTube, Baidu, Instagram
QuestionAI writes a persistent cookie, QUESTION_AI_PCUID, into five sites (google.com, baidu.com, facebook.com, youtube.com, instagram.com), same value each.
Expires in ~100 years, not HttpOnly.
Lands automatically, no visit needed.
What actually happens
You install QuestionAI and use it once, so it can generate a client ID for itself.
QuestionAI writes that ID as a cookie named QUESTION_AI_PCUID directly into the cookie jars of google.com, baidu.com, facebook.com, youtube.com, and instagram.com.
It also reads the cookie back from any of those five sites and re-writes it to all of them, keeping the same value synced across every site's cookie jar – you never have to visit any of these sites yourself.
What's stored on your device
The same tracking ID was found on all five sites named here, confirming it was planted broadly, not scoped to the extension's own domain.
- Location
- chrome.cookies store, cookie name QUESTION_AI_PCUID
{ "www.baidu.com": "rkxhnj0cnutyu6wkual83vkl1jce87_1788084761", "www.google.com": "rkxhnj0cnutyu6wkual83vkl1jce87_1788084761", "www.youtube.com": "rkxhnj0cnutyu6wkual83vkl1jce87_1788084761", "www.facebook.com": "rkxhnj0cnutyu6wkual83vkl1jce87_1788084761", "www.instagram.com": "rkxhnj0cnutyu6wkual83vkl1jce87_1788084761"}The code that does this
The code that writes the persistent ID onto five third-party sites' cookie jars.
The tracked-site list and the fan-out write function
const TRACKED_SITES = [ "https://www.questionai.com", "https://passport.questionai.com", "https://www.google.com", "https://www.baidu.com", "https://www.facebook.com", "https://www.youtube.com", "https://www.instagram.com",];const PCUID_COOKIE_NAME = "QUESTION_AI_PCUID";// Called whenever the persistent client ID is generated or refreshedasync function persistIdEverywhere(cookieName, value) { await setLocalStorage(cookieName, value); for (const siteUrl of TRACKED_SITES) { await writeCookieOnSite(cookieName, value, siteUrl); }}The underlying chrome.cookies.set call
// Writes a cookie directly into the named site's cookie jar via the// privileged chrome.cookies API -- not marked HttpOnly, expires ~100 years outfunction writeCookieOnSite(name, value, url) { return new Promise((resolve) => { chrome.cookies.set({ url, name, value, expirationDate: Date.now() / 1000 + 3153600000, // ~100 years }, resolve); });}The ID-resolution flow that keeps the cookie synced across all five sites
// Resolves (or mints) the persistent client ID, then fans it out to// every tracked site's cookie jar -- including reading it back from// whichever site already has it, if anyasync function getPersistentClientId() { let pcuid = await getLocalStorage(PCUID_COOKIE_NAME); if (!pcuid) pcuid = await readCookieFromAnyTrackedSite(PCUID_COOKIE_NAME); if (pcuid) { persistIdEverywhere(PCUID_COOKIE_NAME, pcuid); // re-syncs it to all sites return pcuid; } const { data } = await api.fetchPost(APIKeys.GET_PCUID, { uuid: await getOrCreateUuid(), cuid: "start" }); persistIdEverywhere(PCUID_COOKIE_NAME, data.cuid); return data.cuid;}Sites this cookie is planted on, whether or not you've ever used QuestionAI there
- www.google.com
Receives the QUESTION_AI_PCUID cookie; readable by any script running on google.com pages since the cookie is not HttpOnly.
- www.baidu.com
Receives the QUESTION_AI_PCUID cookie; readable by any script running on baidu.com pages since the cookie is not HttpOnly.
- www.facebook.com
Receives the QUESTION_AI_PCUID cookie; readable by any script running on facebook.com pages since the cookie is not HttpOnly.
- www.youtube.com
Receives the QUESTION_AI_PCUID cookie; readable by any script running on youtube.com pages since the cookie is not HttpOnly.
- www.instagram.com
Receives the QUESTION_AI_PCUID cookie; readable by any script running on instagram.com pages since the cookie is not HttpOnly.
Check if you're affected
Checks whether the QUESTION_AI_PCUID tracking cookie is present on the current site. Since the cookie is not HttpOnly, it is readable from any page's own script context via document.cookie.
- Chrome with QuestionAI extension installed and enabled
- A visit to one of the five listed sites
- Developer Tools access (F12)
// questionai-pcuid-cookie-check.js// Run in the DevTools console on google.com, baidu.com, facebook.com,// youtube.com, or instagram.com while QuestionAI is installed.(function () { const match = document.cookie.split('; ').find((row) => row.startsWith('QUESTION_AI_PCUID=')); if (match) { console.log('[QAI_PCUID] Tracking cookie found on this site:'); console.log(' ' + match); console.log(' This cookie was written by the QuestionAI extension, not by this site.'); } else { console.log('[QAI_PCUID] No QUESTION_AI_PCUID cookie found on this domain right now.'); }})();- 1Install QuestionAI, let it fully load.
- 2Open google.com, baidu.com, facebook.com, youtube.com, or instagram.com.
- 3Press F12, open Console.
- 4Paste this script, press Enter.
- 5If present, the cookie prints.
Full List of Installed Extensions Sent to studyquicks.com
Every QuestionAI sidebar load asks for the installed-extension list (chrome.management.getAll) and sends it, names, IDs, versions, states, to autotrack.studyquicks.com.
Captured firing twice in one session, no consent prompt or opt-out.
What actually happens
You open the QuestionAI sidebar on any page.
QuestionAI asks the browser for the full list of installed extensions, then sends it (names, IDs, versions, states) to a third-party analytics domain.
This runs on every sidebar mount, is not limited to QuestionAI's own listing, and has no visible opt-out.
Captured request
Captured twice in the same session, identical payload (retried delivery by the analytics client). The test environment had only this one extension installed, so the array has a single entry – on a normal browser it would contain every installed extension.
name=H60_112&ets=%5B%7B%22name%22%3A%22QuestionAI+Homework+Powered+AI+Assistant%22%2C%22enabled%22%3Atrue%2C%22version%22%3A%222.8.26%22%2C%22id%22%3A%22hajphibbdloomfdkeoejchiikjggnaif%22%7D%5D&isDark=0One object like this is sent per extension you have installed
- Extension nameQuestionAI Homework Powered AI Assistant
The human-readable name of each extension installed in your browser, sent for every one of them.
- Extension IDhajphibbdloomfdkeoejchiikjggnaif
The Store ID of each installed extension, letting the analytics service profile your browser's exact extension toolset.
- Extension version2.8.26
The installed version number of each extension.
- Enabled statetrue
Whether each extension is currently turned on or off in your browser.
The code that does this
The code that retrieves and transmits your full extension inventory.
Sidebar mount handler – requests and forwards the full extension list
// sidebar.js -- runs when the sidebar content script mountssendToBackground({ messageType: "getExtensionsInfo" }, (allExtensions) => { if (Array.isArray(allExtensions) && allExtensions.length) { const inventory = allExtensions.map((ext) => ({ name: ext?.name, enabled: ext?.enabled, version: ext?.version, id: ext?.id, })); addZSEvent("H60_112", { ets: JSON.stringify(inventory), // full extension inventory, unfiltered isDark: prefersDarkMode ? 1 : 0, }); }});Background handler – answers with the browser's full extension/app inventory
// background.js -- service worker message handlercase "getExtensionsInfo": chrome.management.getAll((allExtensions) => { sendResponse(allExtensions); // every installed/enabled extension and app, not just this one }); return true;Where your extension inventory ends up
- autotrack.studyquicks.com
Analytics beacon endpoint (bundled third-party client, zpID 'OB-MATH-PCW') that receives the full list of your browser's installed extensions on every QuestionAI sidebar mount.
Check if you're affected
Hooks fetch() and XMLHttpRequest to detect and print the extension-inventory beacon QuestionAI sends to autotrack.studyquicks.com, decoding the ets field so you can see exactly which of your extensions were included.
- Chrome with QuestionAI extension installed and enabled
- At least one other extension installed to see the list is not QuestionAI-only
- Developer Tools access (F12)
// questionai-extlist-monitor.js// Run in the DevTools console on any page with QuestionAI active.(function () { function inspect(label, url, body) { if (!url || !url.includes('log/math_h5')) return; console.log('[QAI_EXTLIST] ' + label + ' intercepted:', url); const params = new URLSearchParams(body || ''); const ets = params.get('ets'); if (ets) { try { console.log(' extensions reported:', JSON.parse(decodeURIComponent(ets))); } catch (e) { console.log(' raw ets value:', ets); } } } const origFetch = window.fetch; window.fetch = function (input, init) { const url = typeof input === 'string' ? input : input instanceof Request ? input.url : String(input); inspect('fetch', url, init && init.body); return origFetch.apply(this, arguments); }; const origSend = XMLHttpRequest.prototype.send; const origOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function (method, url) { this._qaiUrl = url; return origOpen.apply(this, arguments); }; XMLHttpRequest.prototype.send = function (body) { inspect('XHR', this._qaiUrl, body); return origSend.apply(this, arguments); }; console.log('[QAI_EXTLIST_MONITOR] installed. Open or reopen the QuestionAI sidebar to trigger the beacon.');})();- 1Install QuestionAI with one other extension.
- 2Open a page, press F
- 31
- 4
- 5Console tab, paste this script, press Enter.
- 6Open (or reopen) the sidebar.
- 7Watch for a [QAI_EXTLIST] entry showing your list sent.
Every Page URL Sent to QuestionAI Servers on Navigation
Each new page navigated to, QuestionAI sends its full URL to www.questionai.com's classifyWebsite endpoint. 5 requests in 120 seconds, including facebook.com and google.com.
Each carries a persistent cuid linking browsing to your account.
What actually happens
You navigate to any web page, any site, anywhere.
QuestionAI transmits the full URL of that page to www.questionai.com, along with a persistent identifier tied to your account.
This happens automatically on every page load, not only on homework or educational sites, and requires no action from you.
Captured request
HTTP 200, returns JSON with isClassified, category, and alertSwitches fields that control whether the extension injects its button UI
What QuestionAI sends on every page you visit
- The URL you are visitinghttps://www.facebook.com/
The exact page address you are on, sent as a query parameter on every navigation.
- Your persistent user ID (cuid)lat3hl4nsq73ryv9m9tkyl16fq0437_1776251284
A unique identifier tied to your QuestionAI account that is included on every request, linking all your browsing activity across sites.
- App identifieraihomework
A hardcoded string identifying this client as the QuestionAI homework extension. The same value for all users.
- Client type2
A numeric code identifying the type of client making the request.
The code that does this
The code in the extension's sidebar that triggers this on every page load.
onMounted hook — runs when the sidebar content script mounts on any page
// Runs on every page load when sidebar is active (not in side-panel mode)onMounted(() => { if (!isSidePanelMode) { classifyCurrentPage(); // calls classifyWebsite with window.location.href }});classifyWebsite API call — sends the current page URL to QuestionAI servers
// Issues a GET request to https://www.questionai.com/questionai/common/classifyWebsite// with {url: currentPageUrl} as a query parameterasync function fetchClassification(url) { try { return await apiClient.get(APIKeys.CLASSIFY_WEBSITE, { url: url }); } catch (e) { console.log('Failed to get website classification', e); return null; }}classifyCurrentPage — reads window.location.href and dispatches the request
// Reads the current page URL and sends it to questionai.comasync function classifyCurrentPage() { const currentUrl = window.location.href; // the page you are visiting const [classificationResult, isClosePage] = await Promise.all([ fetchClassification(currentUrl), // → GET classifyWebsite?url=<currentUrl>&cuid=... isClosedPage(currentUrl) ]); if (!classificationResult?.data) return; // still sent the URL even if result is empty const { isClassified, category, alertSwitches } = classificationResult.data; if (!isClassified || category !== SiteCategory.SolutionWebsite) return; // Only shows the inject button if classified as a homework/solution site // but the URL was already transmitted regardless}Where your browsing data ends up
- www.questionai.com
QuestionAI's primary server; receives the URL of every page visited. classifyWebsite returns data used to decide whether to show the AI homework helper button.
Reproduce it yourself
Paste this into the Chrome DevTools console on any page with QuestionAI active. It intercepts XMLHttpRequest and fetch calls matching 'classifyWebsite' and logs the transmitted URL and cuid to the console, confirming what page data is being sent.
- Chrome with QuestionAI extension installed and enabled
- Developer Tools access (F12)
// questionai-classify-monitor.js// Intercepts outbound classifyWebsite requests from QuestionAI and logs them.// Run in Chrome DevTools console on any page with the extension active.(function() { // Hook fetch() const origFetch = window.fetch; window.fetch = function(input, init) { const url = (typeof input === 'string') ? input : (input instanceof Request ? input.url : String(input)); if (url.includes('classifyWebsite')) { const parsed = new URL(url); console.log('[QAI_CLASSIFY] fetch intercepted'); console.log(' page URL transmitted:', decodeURIComponent(parsed.searchParams.get('url') || '(none)')); console.log(' cuid:', parsed.searchParams.get('cuid') || '(none)'); console.log(' full request URL:', url); } return origFetch.apply(this, arguments); }; // Hook XMLHttpRequest.open() const origOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url) { if (url && url.includes('classifyWebsite')) { const parsed = new URL(url, window.location.href); console.log('[QAI_CLASSIFY] XHR intercepted'); console.log(' page URL transmitted:', decodeURIComponent(parsed.searchParams.get('url') || '(none)')); console.log(' cuid:', parsed.searchParams.get('cuid') || '(none)'); console.log(' full request URL:', url); } return origOpen.apply(this, arguments); }; console.log('[QAI_CLASSIFY_MONITOR] installed. Navigate to any page to see captured classifyWebsite requests.');})();- 1Install and enable QuestionAI.
- 2Open any page, press F
- 31
- 4
- 5Switch to Console.
- 6Paste this script, press Enter.
- 7Navigate to any page.
- 8Watch for [QAI_CLASSIFY] entries showing the URL and cuid sent.
What it can do
Permissions this extension asks for, as declared in version 2.8.26. 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 secure site you visit
https://*/*
Read and change your data on every site you visit
<all_urls>
Keep running in the background while your browser is open
background
Act on the current tab, but only after you click the extension
activeTab
Read and change cookies, including the ones that keep you signed in
cookies
See the address and title of every tab you have open
tabs
Add items to the right-click menu
contextMenus
Store data in your browser
storage
Run its own code inside the pages you visit
scripting
See, disable and uninstall your other extensions, including your security ones
management
Show a panel beside the page
sidePanel