Is AudD® Music Recognition safe?
audd%C2%AE-music-recognition is medium risk. Starting music recognition sends api.audd.io the recorded audio plus tab/profile data: page URL/title, Google email/ID when available, a persistent device ID, version, and app ID. The live upload wasn't captured; fields come from source.
Who publishes itAudD, LLC - no other listings under this identity, 2 shared hostnames
AudD, LLC - no other listings under this identity, 2 shared hostnames
What this publisher told the store about itself, and the other listings that told it the same thing.
Shared hosts - 2 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
Music Recognition Uploads Profile and Tab Details
Starting music recognition sends api.audd.io the recorded audio plus tab/profile data: page URL/title, Google email/ID when available, a persistent device ID, version, and app ID.
The live upload wasn't captured; fields come from source.
What actually happens
You start music recognition from the extension popup.
The popup queries the active tab and asks the service worker to start recording when the popup logo is clicked.
The extension prepares an upload that combines the tab audio with profile and tab details.
The service worker passes tab URL, tab title, profile email, Google profile ID, and device ID into the popup before the popup posts the form.
Multipart form fields added to the recognition request
- Active page URLhttps://music.youtube.com/watch?v=9bZkp7q19f0 (illustrative)
Shows which page was open when you started recognition.
- Active page titleMusic video - YouTube (illustrative)
Adds a readable page name to the recognition request.
- Google profile emailalex.rivera@example.org (illustrative)
Can connect the recognition request to your signed-in Chrome profile when Chrome provides it.
- Google profile ID109876543210987654321 (illustrative)
Can connect multiple recognition requests to the same Chrome profile.
- Persistent device ID0.73482916558842461720567082391 (illustrative)
Lets the extension link recognition activity from the same browser over time.
- Recorded tab audiomultipart field named file containing a recorded audio Blob (illustrative)
Contains the audio sample you asked the extension to identify.
- Extension version and app IDversion=3.2.2; app_id=lhhohkfofnfbnildpdhhjeeenapeceei
Identifies which extension build and Chrome extension ID submitted the request.
Captured request
Upload body not captured during dynamic analysis; source code constructs this POST when recording completes.
The code that does this
The code path that collects profile and tab fields and posts them
Persistent device ID initialization
background.jschrome.storage.local.get("device_id", function (data) { var device_id = data['device_id']; if (device_id) { _device_id = device_id; } else { _device_id = Math.random() + "" + new Date().getTime(); chrome.storage.local.set({ "device_id": _device_id }, function () { console.log('storage set [device_id]'); }); } });background_start collects tab and profile fields
background.jscase "background_start": var tab = request.tab; if (request.tab == null) { console.error("no selected tab"); chrome.runtime.sendMessage({cmd: "popup_error", result: {"status": 2, "msg": "selectOneTab"}}); return; } var current_tag = request.tab; var tab_url = current_tag['url']; var tab_title = current_tag['title']; if (!current_tag['audible']) { chrome.runtime.sendMessage({cmd: "no_audio"}); return; } chrome.identity.getProfileUserInfo(function(user_info) { var email = ""; var google_id = ""; if (chrome.runtime.lastError) { console.log(chrome.runtime.lastError.message); //chrome.runtime.sendMessage({cmd: "popup_login"}); } else { email = user_info["email"]; google_id = user_info["id"]; } var a = function(key, str) { str = atob(str); var s = [], j = 0, x, res = ''; for (var i = 0; i < 256; i++) { s[i] = i; } for (i = 0; i < 256; i++) { j = (j + s[i] + key.charCodeAt(i % key.length)) % 256; x = s[i]; s[i] = s[j]; s[j] = x; } i = 0; j = 0; for (var y = 0; y < str.length; y++) { i = (i + 1) % 256; j = (j + s[i]) % 256; x = s[i]; s[i] = s[j]; s[j] = x; res += String.fromCharCode(str.charCodeAt(y) ^ s[(s[i] + s[j]) % 256]); } return btoa(res); }; var info = { "api_token": storageCache.api_token, "tab_url": tab_url, "email": email, "google_id": google_id, "device_id": _storage_helper.get_device_id(), "tab_title": tab_title}; info[a("Wx!h", "+aIQwBctPPfCsTJZSmoLmSlij2WSLPLV")] = a('Cd8l', 'JT9+DxOFvXJivXR6VYiYUhpUHCAR08wA'); on_paid_only = false; on_paid_only_without_trial = false; if(extensionConfig.paid_only) { for (website of extensionConfig.paid_only) { if(tab_url.includes(website)) { on_paid_only = true; } } } if(extensionConfig.paid_only_without_trial) { for (website of extensionConfig.paid_only_without_trial) { if(tab_url.includes(website)) { on_paid_only_without_trial = true; } } } if(on_paid_only_without_trial && !storageCache.api_token) { chrome.runtime.sendMessage({cmd: "popup_error", result: {"status": 2, "msg": "onlyPaidWorksHere"}}); return; } if(on_paid_only && !storageCache.api_token) { chrome.identity.getAuthToken({ 'interactive': true }, function(token) { if(token == undefined) { //console.log(chrome.runtime.lastError.message); chrome.runtime.sendMessage({cmd: "popup_error", result: {"status": 2, "msg": "needAuth"}}); return; } var CWS_LICENSE_API_URL = 'https://www.googleapis.com/chromewebstore/v1.1/userlicenses/'; try { var req = new XMtpRequest(); } catch(err) { chrome.runtime.sendMessage({cmd: "popup_error", result: {"status": 2, "msg": "trialEnded"}}); return; } req.open('GET', CWS_LICENSE_API_URL + chrome.runtime.id); req.setRequestHeader('Authorization', 'Bearer ' + token); req.onreadystatechange = function() { if (req.readyState == 4) { var license = JSON.parse(req.responseText); if(license.accessLevel == "FREE_TRIAL") { if((license.createdTime > 1521015562514) && (Date.now() - license.createdTime)/(1000*60*60*24) > 14) { chrome.runtime.sendMessage({cmd: "popup_error", result: {"status": 2, "msg": "trialEnded"}}); return; } } //if(license.accessLevel == "FULL") { info["chrome_token"] = token; g_recognizer_client.start(info, storageCache.record_length); //} } } req.send(); }); } else { g_recognizer_client.start(info, storageCache.record_length); } }); break;Popup posts every info key with the audio file
src/popup/popup.jsfunction post_request(audio_buffer) { var server_url = "https://api.audd.io/"; //var browser_version = navigator.userAgent; var post_data = new FormData(); if(_info.api_token) { post_data.append('api_token', _info.api_token); // post_data.append('tab_url', "api:client"); } for (var key in _info) { post_data.append(key, _info[key]); } var manifest = chrome.runtime.getManifest(); var app_id = chrome.runtime.id; console.log(app_id); post_data.append('file', audio_buffer); //post_data.append('browser_version', browser_version); //post_data.append('market', chrome.i18n.getMessage("countryCode")); post_data.append('version', manifest.version); post_data.append("app_id", app_id); post_data.append('return', 'lyrics'); $.ajax({ type: 'POST', url: server_url, data: post_data, timeout : 15000, dataType: 'json', processData: false, contentType: false, success: function(data) { console.log(data); chrome.runtime.sendMessage({cmd: "success_post", result: data, info: _info}); }, error: function(error, textStatus) { console.log(error); var msg = "HTTP Error (Code = " + textStatus + ")"; if (textStatus == 'timeout') { msg = "Network Timeout"; } chrome.runtime.sendMessage({cmd: "popup_error_relay", result: {"status": 2, "text": msg}}); } });}External services involved in this recognition flow
- api.audd.io
AudD recognition API receiving the audio sample and metadata form fields.
- www.googleapis.com
Chrome Web Store license API used only on paid-only sites when the extension requests a Chrome auth token.
What it can do
Permissions this extension asks for, as declared in version 3.2.2. 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 api.audd.io
https://api.audd.io/
Read and change your data on www.googleapis.com
https://www.googleapis.com/
Sign you in with your Google account
identity
See the email address of your Google account
identity.email
Store data in your browser
storage
Store an unlimited amount of data in your browser
unlimitedStorage
Keep running in the background while your browser is open
background
Act on the current tab, but only after you click the extension
activeTab
Capture the video and audio of a tab
tabCapture
Show you desktop notifications
notifications
