Is Unblocker for YouTube safe?

Medium risk

Unblocker for YouTube is medium risk. During popup login, the shipped code logs analytics events including the email entered or stored for the account, plus a persistent device ID, timestamp, and app version, sent to Amplitude's API, which was seen carrying this identifier.

Wacheev4.1.4Chrome Web Store
45Risk
Who publishes it

Routeme LLC. - no other listings under this identity, 1 shared hostname

What this publisher told the store about itself, and the other listings that told it the same thing.

Publisher
Wachee
Declared legal entity
Routeme LLC.
Registered address
427 N TATNALL ST, #23732, Wilmington, DELAWARE 19801, United States
Registered contact
Mohsen Gheisarieha

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.

api.ytu.routeme.me
Also called by 1 other listing: Unblocker-4, unblock your favorite websites

AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.

Publishers can request a review.

Findings

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-359
SourceAI SANDBOX

Popup login analytics sends email and device ID to Amplitude

During popup login, the shipped code logs analytics events including the email entered or stored for the account, plus a persistent device ID, timestamp, and app version, sent to Amplitude's API, which was seen carrying this identifier.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You use the popup's premium login controls or choose to log out.

The relevant paths are the send-code, verify-code, login-failed, and logout handlers.

The extension did this

The extension builds an authentication analytics event that can include your email address.

The analytics helper adds a persistent device identifier and sends the event to Amplitude.

02EvidenceFIELD TABLE
Fields included in the analytics event
FieldValueWhy it matters
Your email address
jordan.lee@example.com (illustrative)This ties the popup login event to the account address you entered or had stored in the extension.
Authentication step
login_successfulThis says which login action happened, such as requesting a code, completing login, failing login, or logging out.
Persistent device identifier
web_pybrl6xmmmrhlg9vbThis lets analytics events from the same browser profile be linked over time.
Session timestamp
1720791446123 (illustrative)This groups the event with other popup activity from the same browser session.
Extension platform and version
Chrome Extension / 4.0.0This describes the software environment that produced the event.
03EvidenceNETWORK CAPTURE
Captured request
POSThttps://api2.amplitude.com/2/httpapi
Observed Amplitude POST traffic from the popup reached api2.amplitude.com; the recorded non-auth popup events carried device_id/user_id web_pybrl6xmmmrhlg9vb. The recorded traffic did not preserve an auth-email request body.
Headers
Acceptapplication/json
Content-Typeapplication/json
04EvidenceCODE COMPARE
The code that does this

Popup authentication events feed the Amplitude HTTP API

What it actually does
No separate deobfuscated tree was present; the shipped popup source is already readablepopup/popup.js
document.addEventListener('DOMContentLoaded', () => {
    const emailForm = document.getElementById('email-form');
    const codeForm = document.getElementById('code-form');
    const emailInput = document.getElementById('email-input');
    const sendCodeBtn = document.getElementById('send-code-btn');
    const verificationCode = document.getElementById('verification-code');
    const verifyCodeBtn = document.getElementById('verify-code-btn');
    const haveCodeBtn = document.getElementById('have-code-btn');
    // Email validation
    emailInput.addEventListener('input', () => {
        const isValidEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emailInput.value);
        sendCodeBtn.disabled = !isValidEmail;
    });

    // Handle email submission
    sendCodeBtn.addEventListener('click', async () => {
        amplitudeTracker.trackButtonClick("Send Code Button");
        try {
            // Add your API call here to send verification code
            sendCode(emailInput.value, (data) => {
                if(data.statusCode  == 200){
                    amplitudeTracker.trackAuthEvent("code_sent", { email: emailInput.value, status: "success" });
                    showToast("Code sent to email", "success");
                    emailForm.classList.add('hidden');
                    codeForm.classList.remove('hidden');
                    chrome.storage.local.set({"YTU_EMAIL": emailInput.value});
                    chrome.storage.local.set({"YTU_CODE": "SEND"});
                }
                else if(data.statusCode == 201){
                    amplitudeTracker.trackAuthEvent("code_sent", { email: emailInput.value, status: "not_premium", error_code: data.statusCode });
                    showToast("Email address is not premium", "error");
                }
                else{
                    amplitudeTracker.trackAuthEvent("code_sent", { email: emailInput.value, status: "failed", error_code: data.statusCode });
                    showToast("(" + data.statusCode + ") Failed to send code", "error");
                }
            });
            
            
        } catch (error) {
            amplitudeTracker.trackError("code_send_error", error.message, { email: emailInput.value });
            document.getElementById('email-error').textContent = error.message;
            document.getElementById('email-error').style.display = 'block';
        }
    });

    haveCodeBtn.onclick = () => {
        amplitudeTracker.trackButtonClick("Have Code Button");
        emailForm.classList.add('hidden');
        codeForm.classList.remove('hidden');
    }   

    // Handle verification code submission
    verifyCodeBtn.addEventListener('click', async () => {
        amplitudeTracker.trackButtonClick("Verify Code Button");
        try {
            const storageResult = await chrome.storage.local.get("YTU_EMAIL");
            const email = storageResult["YTU_EMAIL"];
            verifyCode(email, verificationCode.value, (data) => {
                if(data.statusCode  == 200){
                    userEmail = email;
                    amplitudeTracker.trackAuthEvent("login_successful", { email: email });
                    amplitudeTracker.setUserId(email);
                    showToast("Login successful", "success");
                    chrome.storage.local.set({"YTU_CODE": "VERIFY"});
                    showPage(false,"login-page")
                    checkPremium();
                    sendConnectionStatusToServiceWorker("disconnect");
                }
                else{
                    amplitudeTracker.trackAuthEvent("login_failed", { email: email, error_code: data.statusCode });
                    showToast("Failed to login", "error");
                }
            });
            
        } catch (error) {
            amplitudeTracker.trackError("verification_error", error.message, { email: email });
            showToast("Something went wrong", "error");
        }
    });
});

document.getElementById('logout-btn').onclick = () => {
    amplitudeTracker.trackButtonClick("Logout Button");
    showAreYouSure(true,"Are you sure you want to logout?<br>Your Subscription remain active but this extension will back to free plan.<br>You can login again anytime.",(isSure) => {
        if(isSure){
            amplitudeTracker.trackAuthEvent("logout", { email: userEmail });
            chrome.storage.local.set({"YTU_CODE": ""});
            chrome.storage.local.set({"YTU_EMAIL": ""});
            showToast("Logged out successfully", "success");
            checkPremium();
            sendConnectionStatusToServiceWorker("disconnect");
        }
        else{
            showAreYouSure(false,"",() => {});
        }
    });
}
No separate deobfuscated tree was present; the shipped analytics helper is already readablepopup/amplitude.js
const AMPLITUDE_API_KEY = '680812b42b998d072fd8d2ddf1f2aa70';
const AMPLITUDE_SECRET_KEY = '36c8e4734f7608aacca72929bd21dd9a';
const AMPLITUDE_PROJECT_ID = '727399';

class AmplitudeTracker {
    constructor() {
        this.deviceId = this.generateDeviceId();
        this.sessionId = this.generateSessionId();
        this.userId = null;
        this.userProperties = {};
    }

    // Generate a unique device ID
    generateDeviceId() {
        let deviceId = localStorage.getItem('amplitude_device_id');
        if (!deviceId) {
            deviceId = 'web_' + Math.random().toString(36).substr(2, 9) + Date.now().toString(36);
            localStorage.setItem('amplitude_device_id', deviceId);
        }
        return deviceId;
    }

    // Generate a unique session ID
    generateSessionId() {
        return Date.now();
    }

    // Set user ID when user logs in
    setUserId(userId) {
        this.userId = userId;
    }

    // Set user properties
    setUserProperties(properties) {
        this.userProperties = { ...this.userProperties, ...properties };
    }

    // Track an event
    async trackEvent(eventType, eventProperties = {}) {
        const event = {
            event_type: eventType,
            user_id: this.userId || this.deviceId,
            device_id: this.deviceId,
            session_id: this.sessionId,
            time: Date.now(),
            event_properties: eventProperties,
            user_properties: this.userProperties,
            platform: 'Chrome Extension',
            app_version: '4.0.0'
        };

        try {
            const response = await fetch('https://api2.amplitude.com/2/httpapi', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Accept': 'application/json'
                },
                body: JSON.stringify({
                    api_key: AMPLITUDE_API_KEY,
                    events: [event]
                })
            });

            if (!response.ok) {
                console.warn('Amplitude tracking failed:', response.status);
            }
        } catch (error) {
            console.warn('Amplitude tracking error:', error);
        }
    }

    // Track authentication events
    trackAuthEvent(eventType, additionalProperties = {}) {
        this.trackEvent('Authentication Event', {
            event_type: eventType,
            timestamp: new Date().toISOString(),
            ...additionalProperties
        });
    }
}

const amplitudeTracker = new AmplitudeTracker();
window.amplitudeTracker = amplitudeTracker;
05EvidenceTHIRD PARTY LIST
Destination receiving the analytics event
  • api2.amplitude.com

    Amplitude HTTP API endpoint that receives the popup authentication analytics event.

What it can do

Permissions this extension asks for, as declared in version 4.1.4. 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.ytu.routeme.me

    https://api.ytu.routeme.me/*

  • Read and change your data on routeme.me

    https://routeme.me/*

  • Route all of your browsing through a server of its choosing

    proxy

  • Store data in your browser

    storage

  • Schedule its own background tasks

    alarms

  • Act on the current tab, but only after you click the extension

    activeTab

Updated 30 September 2026gpnebajhkedajplkepiafghcfoljbgmk