dollar
@dollar
Делай добро и бросай его в воду.

Как сделать расширение Chrome менее подозрительным?

Написал простенькое расширение, которое показывает, заблокирован ли сайт Роскомнадзором. Но Google его отклонил к публикации, объяснив, что расширение подозрительное. Как быть?

Текст письма от Google
Dear Developer,

Your Google Chrome item, "BlockListCheck", with ID:
mdbffnnpjhnfmnenfkffjohdgjfeiodn did not comply with our policies and was
removed from the Google Chrome Web Store.

We routinely review items in the Chrome Web Store for compliance with our
Program policies to ensure a safe and trusted experience for our users. Per
our policies, where possible, make as much of your code visible in the
package as you can. If some of your app's logic is hidden and it appears to
be suspicious, we may remove it. During the course of a review, your item
was found to be suspicious
and has one or more file(s) that contain
minified or obfuscated code which is not human readable.

To have your item reinstated, please make any necessary changes to ensure
that all of the files and code are included in the item’s package and are
human readable.

If you'd like to re-submit your item, please make appropriate changes to
the item so that it complies with our policies, then re-publish it in your
developer dashboard. Please reply to this email for issues regarding this
item removal.

*Please keep in mind that your re-submitted item will not be immediately
published live in the store. All re-submitted items undergo a strict
compliance review and will be re-published if the item passes review.

*Important Note- Repeated or egregious violations in the store may result
in your developer account being banned from the store. This may also result
in the suspension of related Google services associated with your Google
account. All re-submitted items will continue to be subject to Chrome Web
Store policies and terms of service.

Thank you for your cooperation,
Google Chrome Web Store team

Код простейший:
popup.js - 8 строк
let time_str = chrome.extension.getBackgroundPage().temp_domain_blocked;

document.addEventListener('DOMContentLoaded', function () {
	if (time_str && time_str != "?")
		document.getElementById('time').innerHTML = "Дата блокировки: " + time_str;
	else 
		document.getElementById('time').innerHTML = "В реестре отсутствует";
})
background.js - 86 строк
function extractHostname(url) {
    var hostname;
    if (url.indexOf("//") > -1) {
        hostname = url.split('/')[2];
    }
    else {
        hostname = url.split('/')[0];
    }
    hostname = hostname.split(':')[0];
    hostname = hostname.split('?')[0];
    return hostname;
}

function extractRootDomain(url) {
    var domain = extractHostname(url),
        splitArr = domain.split('.'),
        arrLen = splitArr.length;

    if (arrLen > 2) {
        domain = splitArr[arrLen - 2] + '.' + splitArr[arrLen - 1];
        if (splitArr[arrLen - 2].length == 2 && splitArr[arrLen - 1].length == 2) {
            domain = splitArr[arrLen - 3] + '.' + domain;
        }
    }
    return domain;
}

var data_updated = "?";
var data_blocked_ip = {};
var data_blocked_domain = {};

var temp_domain_blocked = "?";

function updateIcon(url) {
	//chrome.browserAction.setIcon({imageData:canvasContext.getImageData(0, 0, canvas.width,canvas.height)});
	temp_domain_blocked = "?";
	//console.log("url:",url);
	if (!url)
		chrome.browserAction.setIcon({path: "images/circ_gray_gray_16.png"});
	else if (url.substr(0,4) != "http" && url.substr(0,5) != "https") {
		chrome.browserAction.setIcon({path: "images/circ_gray_gray_16.png"});
	}
	else if (temp_domain_blocked = data_blocked_domain[extractHostname(url)] || data_blocked_domain[extractRootDomain(url)] ) {
		chrome.browserAction.setIcon({path: "images/circ_pink_red_16.png"});
	}
	else
		chrome.browserAction.setIcon({path: "images/circ_green_green_16.png"});
}

function addDomain(domain, date) {
	data_blocked_domain[domain] = date;
}

var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
	if (this.readyState == 4 && this.status == 200) {
		let data = JSON.parse(xhttp.responseText);
		console.log('rules loaded');
		data_updated = Object.keys(data)[0];
		data = data[data_updated];
	   
		for(let i=0,len=data.length;i<len;i++){
			let row = data[i];
			for(let j=0;j<row.ip.length;j++) data_blocked_ip[row.ip[j]] = true;
			if (row.page) addDomain(row.page, row.date);
		}
		console.log('done');
    }
};
xhttp.open("GET", "testdata.txt", true);
xhttp.send();

chrome.tabs.onActivated.addListener(function(activeInfo) {
	//console.log([activeInfo.tabId, activeInfo.windowId]);
	chrome.tabs.get(activeInfo.tabId, function( tab) {
		console.log("onActivated",tab.url,tab)
		updateIcon(tab.url)
	})
});

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
	if (changeInfo.url && tab.active) {
		console.log("onUpdated",changeInfo.url,changeInfo,tab);
		updateIcon(changeInfo.url)
	}
})
Разрешения - только доступ к вкладкам
{
	"manifest_version": 2,
 
	"name": "BlockListCheck",
	"short_name": "BlockListCheck",
	"description": "Показывает в виде иконки, внесён ли сайт в реестр, и как именно.",
	"version": "0.11",
	"icons": {
			"16": "images/logo_16.png",
			"32": "images/logo_32.png",
			"48": "images/logo_48.png"
	},
 
	"permissions": [
		"tabs"
	],
	"background": {
		"scripts": ["background.js"],
		"persistent": true
	},
	"options_page": "options.html",
	"browser_action": {
		  "default_icon": {
			"16": "images/logo_16.png",
			"32": "images/logo_32.png",
			"48": "images/logo_48.png"
		  },
		  "default_title": "BlockListCheck",
		  "default_popup": "popup/popup.html"
	}
}

То есть расширение даже не имеет доступа к содержимому страниц. Может только читать URL вкладки. Не обращается к внешним ресурсам! То есть априори (согласно коду) не может ничего отправить или получить с других сайтов. Код не обфусцирован и крайне простой.

База реестра Роскомнадзора скачана с Роскомсвободы (json 20 мегабайт). И сохранена в локальном файле расширения в виде json файла. (В будущем хотел, конечно же, прикрутить авто обновление).

В чём может заключаться подозрительность, и как доказать Гуглу, что всё чисто?
  • Вопрос задан
  • 534 просмотра
Решения вопроса 3
riky
@riky
Laravel
скорее всего из-за большого размера джейсона.
попробуйте засабмитить вначале с урезанным файлом до 1мб например.
Ответ написан
Taraflex
@Taraflex
Ищу работу. Контакты в профиле.
(json 20 мегабайт)

Посмотрите как сжали информацию на antizapret.prostovpn.org
В файле https://antizapret.prostovpn.org/proxy.pac
Ответ написан
profesor08
@profesor08
Не обращается к внешним ресурсам!

var xhttp = new XMLHttpRequest();
....

Что-то тут не сходится.

И не понятно зачем выкачивать базу, если можно сверяться с ней на лету. Укажи в манифесте правило для разрешения обращения к сайту Роскомсвободы. И на лету грузи тот json и сверяйся с ним. Другого выхода у тебя нет, так как многие символы там закодированы и их нельзя с ходу распознать не перекодируя в нормальный вид.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы