Is Song Identifier safe?
Song Identifier captures a 5-second audio fingerprint from active tab media and sends it to ACRCloud, using hardcoded API credentials.
When a user clicks the extension's browser action button, it injects a script into the active tab that captures audio from any playing media element for 5 seconds using the browser's media stream API. The captured audio is base64-encoded and POSTed to identify-eu-west-1.acrcloud.com to identify the song. The extension bundles hardcoded ACRCloud API credentials (host, key, and secret) in plaintext in secret.js, meaning those credentials are visible to anyone who inspects the extension.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Bundled ACRCloud keys sign recognition requests
The extension bundle contains fallback ACRCloud API credentials.
Song recognition without your own credentials makes the extension sign a POST to ACRCloud's identify endpoint with the recorded audio sample, using those bundled values.
You start song recognition from the extension.
The extension signs the recognition upload with bundled ACRCloud fallback credentials when no saved credentials are set.
| Field | Value | Why it matters | |
|---|---|---|---|
Recognition host | identify-eu-west-1.acrcloud.com | Shows where the extension sends the audio recognition request after you start identification. | |
Bundled access key | access_key=<redacted> | This value identifies the bundled ACRCloud account used when you have not saved your own credentials. | |
Bundled signing credential | signing_credential=<redacted> | This value is used to calculate the request signature for the recognition upload. | |
Audio sample field | sample=UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAIA+AAACABAAZGF0YQAAAAA= | The recognition request includes a base64-encoded sample from the audio you asked the extension to identify. | |
Request signature | signature=Jm8x1rj4wVZlGqfGgsXj3sBeP9Y= | The extension adds a signature calculated from the endpoint, access key, data type, version, and timestamp. |
Bundled credentials, signing, and fallback selection
var secret = {
host: "identify-eu-west-1.acrcloud.com",
key: "<redacted>",
secret: "<redacted>"
}
export default secret
function create_sign(data, secret_key) {
return _crypto.default.createHmac('sha1', secret_key).update(data).digest().toString('base64');
}
function recognize(host, access_key, secret_key, query_data, query_type) {
return new Promise(function (resolve, reject) {
var http_method = "POST";
var http_uri = "/v1/identify";
var data_type = query_type;
var signature_version = "1";
var current_date = new Date();
var minutes = current_date.getTimezoneOffset();
var timestamp = parseInt(current_date.getTime() / 1000) + minutes * 60 + '';
var sample_bytes = query_data.length + '';
var string_to_sign = http_method + "\n" + http_uri + "\n" + access_key + "\n" + data_type + "\n" + signature_version + "\n" + timestamp;
var sign = create_sign(string_to_sign, secret_key);
var post_data = {
'access_key': access_key,
'sample_bytes': sample_bytes,
'sample': query_data.toString('base64'),
'timestamp': timestamp,
'signature': sign,
'data_type': data_type,
'signature_version': signature_version
};
var content = _querystring.default.stringify(post_data);
var req = _axios.default.post("https://" + host + http_uri, content).then(function (res) {
console.log('statusCode:', res.status);
console.log('headers:', res.headers);
resolve(res.data);
}).catch(function (err) {
console.log('SONG IDENTIFIER: problem with request: ' + err);
reject(err);
});
});
}
var host = _secret.default.host;
var your_access_key = _secret.default.key;
var your_access_secret = _secret.default.secret;
var data_type = 'audio';function save(e) {
// uhh whatever
let v = len.value
v = v > 15 ? 15 : v
// local vs sync probs no big deal in performance - hoping it is cached somewhere.
browser.storage.sync.set({
len: v,
host: host.value,
key: key.value,
secret: secret.value
})
}
function restore() {
browser.storage.sync.get()
.then(values => {
len.value = values.len || ''
host.value = values.host || ''
key.value = values.key || ''
secret.value = values.secret || ''
})
}
len.addEventListener('change', save)
host.addEventListener('change', save)
key.addEventListener('change', save)
secret.addEventListener('change', save)
document.addEventListener('DOMContentLoaded', restore)
- identify-eu-west-1.acrcloud.com
ACRCloud identify API receives the signed recognition request and audio sample when song recognition runs.