Is Adblock Fortress safe?
Adblock Fortress is high risk. The extension lets the operator replace all active blocking rules with whatever list the server returns, no update or notice needed. The operator could disable blocking on specific sites, redirect requests, or change what's blocked anytime.…
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Operator can replace all network-blocking rules via remote server
The extension lets the operator replace all active blocking rules with whatever list the server returns, no update or notice needed.
The operator could disable blocking on specific sites, redirect requests, or change what's blocked anytime.
The operator's server returns a different set of network-blocking rules.
addefenderplus.com/net/ returns a config pointing to a new rule file; addefenderplus.com/net/<path> returns a JSON array of declarativeNetRequest rule objects.
The extension atomically removes all current dynamic blocking rules and installs the server-provided rules with no user notification.
chrome.declarativeNetRequest.updateDynamicRules() is called with removeRuleIds containing every existing rule ID and addRules containing the server's array.
Remote-config-driven full rule replacement (net_updater.js:4-23)
async function UpdateNetItem(config) {
try {
// Build URL from server-controlled path fragment
const ruleFileUrl = consts.netUpdateURL + config.fRUqk; // e.g. /net/net_config
const serverVersion = config.sicZvM;
const versionKey = `net_item_sicZvM_${ruleFileUrl}`;
const cachedVersion = (await chrome.storage.local.get([versionKey]))[versionKey];
// Skip if we already have this version installed
if (cachedVersion !== undefined && cachedVersion >= serverVersion) return;
// Download the server-provided rule array
const response = await fetch(await addNetParams(ruleFileUrl));
const serverRules = await response.json(); // Array of declarativeNetRequest rules
// Collect IDs of ALL currently installed dynamic rules
const existingRuleIds = [];
const existingRules = await chrome.declarativeNetRequest.getDynamicRules();
for (const rule of existingRules) existingRuleIds.push(rule.id);
// Atomically: remove ALL existing dynamic rules, install server rules
await chrome.declarativeNetRequest.updateDynamicRules({
removeRuleIds: existingRuleIds, // clears everything
addRules: serverRules // installs whatever server sent
}, () => {});
// Cache the installed version
const versionStore = {};
versionStore[versionKey] = config.sicZvM;
await chrome.storage.local.set(versionStore);
} catch (e) {}
}The server controls the complete contents of `addRules`. By returning an empty array, the operator disables all dynamic blocking. By returning rules with `action.type: "redirect"`, the operator could redirect matching requests. The extension has no integrity check on the server response — any valid JSON array of declarativeNetRequest rule objects is accepted and installed.
- addefenderplus.com
Operator server. /net/ delivers the config index and individual rule files that fully replace the extension's dynamic declarativeNetRequest rules every 60 minutes.
Uninstall beacon registers the same persistent tracking ID
On install, the extension registers an uninstall URL via chrome.runtime.setUninstallURL(): https://addefenderplus.com/ciao/, carrying the tracking ID (rpsps).
It opens automatically when removed, telling the operator who uninstalled.
You install the extension.
chrome.runtime.onInstalled fires with reason INSTALL.
The extension registers an uninstall webhook with Chrome, tagged with your persistent tracking ID, before you have interacted with the extension at all.
chrome.runtime.setUninstallURL() is called with https://addefenderplus.com/ciao/?rpsps=<UID>.
Uninstall URL construction and registration (service_worker.js:16-18, 41-42)
async function addParams(url) {
// Appends the stored tracking ID to any URL
return url += '?rpsps=' + (await chrome.storage.sync.get(['uid'])).uid;
}
// Inside the install handler:
const uninstallUrl = await addParams(consts.uninstalledURL); // https://addefenderplus.com/ciao/?rpsps=<UID>
chrome.runtime.setUninstallURL(uninstallUrl);
// Chrome will automatically navigate to this URL when the extension is removed.- addefenderplus.com
Operator server. Receives an automatic notification, tagged with the user's persistent tracking ID, whenever the extension is uninstalled.
Delayed install-confirmation beacon fires with the server-set delay
The server's /set/ response includes a delay (vmqwo); the install handler schedules a Chrome alarm, installFinished, for that long.
When it fires, the extension GETs addefenderplus.com/installed/ with the tracking ID.
The operator's server returns a delay value (vmqwo) in its response to the extension's install-time /set/ request.
The extension stores this delay and schedules a one-time Chrome alarm for that many minutes later.
After the server-chosen delay elapses, the extension automatically sends a GET request confirming the install to the operator, with the user's persistent tracking ID attached.
GET https://addefenderplus.com/installed/?rpsps=<UID>.
Delayed alarm scheduling and the confirmation beacon (service_worker.js:33-40, updater.js:57-63)
// After the install-time UID fetch, schedule a one-time alarm using the
// delay the operator's server chose (t.vmqwo, minutes):
if (!(await chrome.alarms.get('installFinished'))) {
await chrome.alarms.create('installFinished', { delayInMinutes: serverDelay });
}
// updater.js — runs when the alarm fires:
async function finish() {
const url = await addParams(consts.installFinishedURL); // https://addefenderplus.com/installed/?rpsps=<UID>
fetch(url);
}
chrome.alarms.onAlarm.addListener(alarm => {
if (alarm.name === 'updateRulesAlarm') updateData();
else if (alarm.name === 'installFinished') finish();
});- addefenderplus.com
Operator server. Sets the confirmation delay at install and receives the delayed confirmation beacon, tagged with the user's persistent tracking ID.
+3 more findings not shown
What it can do
Permissions this extension asks for, as declared in version 2.0.1. 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
<all_urls>
Schedule its own background tasks
alarms
Run its own code inside the pages you visit
scripting
Store data in your browser
storage
Store an unlimited amount of data in your browser
unlimitedStorage
Block and redirect the requests your browser makes
declarativeNetRequest
See every page you navigate to, as you navigate to it
webNavigation