Is Magic Actions for YouTube™ safe?
Enhances YouTube watching with AutoHD, cinema mode, playback controls, and visual customization.
This extension adds YouTube viewing features such as automatic HD playback, mouse-wheel volume control, cinema shading, day/night mode, wide player mode, replay, and options to hide annotations, comments, and related videos. It can take snapshots from playing videos, enlarge avatars and thumbnails on hover, manage autoplay and preloading, and provide a skip button for some ads. If enabled, its AI-based reminders analyze the system and occasionally show notices about bug fixes, account security impact, and media performance.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Recurring fingerprint beacon to api64.com with persistent user ID
The service worker builds a fingerprint (browser, timezone, language, click count, settings), POSTs it to api64.com/upd7 on install and ~5hr intervals.
A random ID links sessions.
A time-bucket guard blocked the call in DA; code ships.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-359
- Source
- Dynamic sandbox
You install the extension or restart your browser.
No interaction is needed, the beacon fires automatically on startup.
The service worker sends a fingerprint JSON POST to api64.com/upd7, including a persistent UUID tied to your installation.
The same UUID is sent on every subsequent call, allowing cross-session tracking.
Every 5 hours
nb() checks whether the current 18 000-second bucket (≈5 hours) differs from the stored e.uf value; if so, Aa() is called and e.uf is updated. On first install the bucket is always 0, guaranteeing an immediate call.
- Persistent user ID (d)a3f2c891-4b1e-4f3a-82d0-c7e9f1234567
A UUID generated on first install and persisted in chrome.storage.local; ties every beacon to the same user across browser sessions.
- Browser name (f)Google Chrome
Identifies which browser you are using (e.g. Google Chrome, Brave, Microsoft Edge).
- Browser version (g, j, k, n)128.0.6613.137
Full version number broken into four components, reported for both the named browser and the underlying Chromium build.
- Timezone offset (o)-5
Your UTC offset in hours, used to narrow geographic location.
- Language (p)en-US
Your browser's preferred language setting.
- Minutes since install (c)4320
How long the extension has been installed on this device; distinguishes new from long-term users.
- Menu-click counter (r)17
Number of times the extension's menu has been opened; measures engagement over time.
Fingerprint collection and POST, esw30.js lines 131-214
// lb() — collects browser fingerprintlb = async function() { let versionToArray = v => { let parts = [0, 0, 0, 0]; v = typeof v === 'string' && v.split('.') || []; for (let i = 0; i < v.length; i++) { let n = parseInt(v[i]); if (!isNaN(n)) parts[i] = n; } return parts; }; if ('userAgentData' in navigator) { let uad = navigator.userAgentData; if (uad.getHighEntropyValues) uad = await uad.getHighEntropyValues(['fullVersionList']); let chromiumVersion, browserVersion; let browserIndex = 0; const KNOWN_BROWSERS = 'Google Chrome;Microsoft Edge;Opera;Opera GX;Opera Crypto;Yandex;Brave'.split(';'); const brands = uad.fullVersionList || uad.brands || []; for (const entry of brands) { const brand = entry.brand; for (let i = 0; i < KNOWN_BROWSERS.length; i++) { if (brand === KNOWN_BROWSERS[i]) { browserIndex = i + 1; browserVersion = entry.version; e.bn = KNOWN_BROWSERS[i]; // store browser name in state break; } } if (brand === 'Chromium') chromiumVersion = entry.version; } const platform = getPlatformCode(uad.platform || ''); return [browserIndex, versionToArray(browserVersion), platform === 'w' ? 1 : platform === 'm' ? 2 : platform === 'c' ? 3 : platform === 'l' ? 4 : 0, versionToArray(chromiumVersion)]; } return [0, [0,0,0,0], '', [0,0,0,0]];};// Aa() — builds and POSTs the fingerprint beaconAa = async function(extra) { let result; try { const [browserIdx, browserVer, platformCode, chromiumVer] = await lb(); const now = Date.now(); const minutesSinceInstall = Math.floor((now - (e.ai || 0)) / 60000); const minutesSinceLastDialog = Math.floor((now - (e.md || 0)) / 60000); const payload = { a: 7, // protocol version b: 7956, // product code c: minutesSinceInstall, d: e.au, // persistent user ID e: platformCode, f: browserIdx, g: browserVer[0], h: browserVer[1], i: browserVer[2], j: browserVer[3], k: chromiumVer[0], l: chromiumVer[1], m: chromiumVer[2], n: chromiumVer[3], o: new Date().getTimezoneOffset() / 60, p: navigator.language || '', r: e.mc || 0, // menu-click counter s: minutesSinceLastDialog, t: e.ma || 0, // setting: ma u: e.me ? 1 : 0, // setting: me w: e.mt || 0, // setting: mt y: e.ms || 0, // setting: ms z: e.ml || 0 // setting: ml }; if (extra) for (let k in extra) payload[k] = extra[k]; const [response, status] = await fetch('https://api64.com/upd7', { method: 'POST', cache: 'no-store', body: JSON.stringify(payload), headers: { 'Content-Type': 'application/json' } }, 'json'); if (status === 0) await applyServerSettings(response); result = status || response; } catch (err) { logError(err); result = 5; } return result;};// nb() — timer scheduler; fires Aa() once per ~5-hour bucketnb = function() { let elapsed = Date.now() - EPOCH_OFFSET; let bucket = elapsed < 18000000 ? 0 : Math.floor(elapsed / 18000000); if (e.uf !== bucket) { e.uf = bucket; Aa(null); }};- api64.com
Receives the fingerprint beacon POST at /upd7; may return settings fields that the extension applies locally. Domain is not disclosed in the extension's Chrome Web Store listing.
Extension makes redundant update check with cookies included
On startup, with broad host permissions, this extension GETs Google's update endpoint (clients2.google.com/service/update2/crx), apart from Chrome's own check.
URL carries ID/version; credentials include cookies; retries 3x.
DA captured it.
- Severity
- Low unwanted
- Type
- Unexpected
- CWE
- CWE-359
- Source
- Dynamic sandbox
You start your browser and the extension loads.
The behavior requires that the extension holds broad host permissions (https://*/*), which Magic Actions for YouTube requests in its manifest.
The service worker fetches Google's CRX update endpoint, sending your extension ID and version in the URL with cookies included.
This fetch is made by the extension's own code, separate from Chrome's built-in automatic update mechanism which already contacts this endpoint independently.
HTTP 200. Response content is not read by the extension (response text is discarded).
The function that makes the update-endpoint request, from esw30.js.
// Fetches the Chrome CRX update endpoint from the service worker.// Called on startup when the extension has broad host permissions.// `a` is the attempt counter (0-2); retries up to 3 times on error.function fetchUpdateEndpoint(attempt) { if (attempt >= 3) return; // max 3 attempts fetch( 'https://clients2.google.com/service/update2/crx' + '?x=id%3Dabjcfabbhafbcdfjoecdgepllmpfceif%26v%3D7.9.5.6%26uc', { method: 'GET', cache: 'no-store', credentials: 'include', // attaches any cookies for this domain redirect: 'manual' } ).then(([_body, errorCode]) => { if (errorCode > 1) { // Non-success: schedule a retry after 3.3 seconds setTimeout(fetchUpdateEndpoint, 3300, attempt + 1); } // On success (errorCode === 0), the response text is discarded });}Chrome already contacts `clients2.google.com/service/update2/crx` automatically to check for extension updates — this is a built-in browser function. What makes this request distinct is that it is issued by the extension's own service worker JavaScript code, separately from the browser's built-in mechanism, and it uses `credentials:'include'`.
The `credentials:'include'` flag tells the browser to attach any cookies it holds for `clients2.google.com` to the outbound request. Whether Google sets such cookies and what they contain depends on whether you are signed into a Google account in that browser profile. The extension does not read or forward the server's response — the response body is discarded.
This is a low-severity finding because the destination is Google's own infrastructure, the request carries only the extension ID and version (both public information), and the response is unused. The `credentials:'include'` flag is nonetheless an unusual choice for what is described as an update check.
What it can do
Permissions this extension asks for, as declared in version 7.9.5.6. 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
http://*/*
Read and change your data on every secure site you visit
https://*/*
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
Where it sends data
Destinations our analysis observed Magic Actions for YouTube 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.
- chromeactions.com
Magic Actions for YouTube sends data to chromeactions.com. No other extension we have analysed sends data here.