Is Web Ad Blocker safe?
Web Ad Blocker is high risk. Web Ad Blocker's background worker fetches JSON config from webadblocker.org on every start or install, storing it in chrome.storage. We observed nearly 40 values, covering the upgrade footer, trial length, and upsell-exempt domains.…
Who publishes itWeb Ad Blocker - no other listings under this identity
Web Ad Blocker - 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
Remote Server Config Controls Web Ad Blocker's Behavior Without a Code Update
Web Ad Blocker's background worker fetches JSON config from webadblocker.org on every start or install, storing it in chrome.storage.
We observed nearly 40 values, covering the upgrade footer, trial length, and upsell-exempt domains.
You start Chrome or install Web Ad Blocker.
Chrome fires the onStartup and onInstalled events the extension listens for.
The extension fetches a settings file from webadblocker.org and applies it immediately.
The response controls interface and monetization behavior, such as whether an upgrade footer appears, without a new extension release.
| Field | Value | Why it matters | |
|---|---|---|---|
Upgrade footer toggle | SHOW_INLINE_FOOTER_EVENT: yes | Turns the in-page upgrade footer overlay on or off for users who haven't paid. | |
Footer split-test variant | SHOW_FOOTER_STRATEGY_C: yes, SHOW_FOOTER_STRATEGY_D: yes | Chooses which footer design variant is shown as part of a split test. | |
Free trial length | TRIAL_DURATION_DAYS: 3 | Sets how many days the free trial lasts before the extension prompts you to pay. | |
Post-trial reminder schedule | POST_TRIAL_REMINDER_SKIP_DAYS: 2 | Controls how many days after the trial ends before payment reminder prompts resume. | |
License verification endpoint | URL_API_REGISTER: https://keys.webadblocker.org/web-service-register | Points the extension at the server URL used to register a paid license key. | |
Domains exempt from upsell prompts | CORPORATE_WHITELIST: ["chase.com", "google.com", "paypal.com", ...] | Lists sites, including major banks and Google and Microsoft services, where the extension suppresses its own monetization prompts. |
| Cookie | PHPSESSID=<redacted>; track_uid=<redacted>; track_installdate=2026-08-16; track_first_visit=thankyou%20chrome%20(ch1)%20-%202026-08-16; wab_installed_prev=yes |
The install/startup fetch is unconditional; a separate, sampled path exists elsewhere
// DETECT WHEN CHROME BROWSER LOADS
chrome.runtime.onStartup.addListener( async function (){
console.log("\ud83d\udd27 [SW DEBUG] Browser startup detected");
if(!SW?.TOTAL_COUNTER?.trk && !SW?.TOTAL_COUNTER?.ads){
IDB.readTableByKey('totalCounter', `last30Days`, (data) => {
SW.TOTAL_COUNTER = data || {ads: 0, trk: 0};
console.log("\ud83d\udd27 [SW DEBUG] Loaded total counter:", SW.TOTAL_COUNTER);
});
}
SW.SERVER_SETTINGS = await SSET.getServerConfigNowAsync();
SW.USER_SETTINGS = await STORAGE.readAllSettingsAsync();
SW.WHITELIST = await WLIST.getEffectiveListWithExtra(false);
SW.HIDDEN_LIST = await HLIST.getUserList();
console.log("\ud83d\udd27 [SW DEBUG] Settings loaded on startup");
console.log("\ud83d\udd27 [SW DEBUG] Server settings:", SW.SERVER_SETTINGS);
console.log("\ud83d\udd27 [SW DEBUG] User settings keys:", Object.keys(SW.USER_SETTINGS));
console.log("\ud83d\udd27 [SW DEBUG] Whitelist:", SW.WHITELIST);
await SW.processWithScripts();
if ((SW.isInFreeTrial()) || (SW.isRegisteredNotExpired())) {
console.log("\ud83d\udd27 [SW DEBUG] User is in trial or registered, updating tabs");
(!TABS.loaded) && TABS.updateTabs();
} else {
console.log("\ud83d\udd27 [SW DEBUG] User not in trial/registered, updating tabs with disabled state");
TABS.updateTabs(false);
TOTALS.forceExpiredIcon();
}
// SET OUR UNINSTALL URL
SW.setUninstallURL();
if (SW.bDebugMode || COMMON.rand(1, 5) == 5) { // 20% of the time
LIC.verifyKey(SW);
}
});SSET.getServerConfigNow = (fn) => {
console.log('** SSET.getServerConfigNow');
fetch('https://webadblocker.org/pluginservice-mv3/ajax-getconfig.php')
.then(response => response.json())
.then(json => {
STORAGE.saveSetting('xab_SERVER_SETTINGS',json);
STORAGE.readSetting('xab_SERVER_SETTINGS',fn);
if (typeof SW == 'object') {
SW.updatedServerSettings();
}
})
.catch(error => {
console.error('error',error);
});
};SSET.getServerConfigNonCritical = (nMax) => {
return new Promise(resolve => {
// we use -1 as a trick to force pulling from local settings unless it's empty
if ((COMMON.rand(1,nMax) == nMax) && (nMax != -1)) { // if nMax == 5, then run 20% of the time
SSET.getServerConfigNow(function(o) {
resolve(o);
});
} else {
SSET.getLocalSettings(function(o,bEmpty) {
if (!bEmpty) {
resolve(o);
} else {
SSET.getServerConfigNow(function(o) {
resolve(o);
});
}
});
}
});
};- webadblocker.org
Serves the remote configuration that controls the extension's interface and monetization behavior at runtime.
- keys.webadblocker.org
Registration and license-verification endpoints returned inside the remote configuration.
Web Ad Blocker sends footer-click analytics to meteor4.com
The code sends split-test analytics to meteor4.com when the footer upgrade overlay shows or is clicked.
Passive analysis recorded no traffic since the overlay never appeared, but footer scripts inject on HTTP/HTTPS pages regardless.
You encounter the extension's footer upgrade overlay or click its upgrade button.
The overlay only appears after the extension's install-age, page, license, reminder, and server-setting checks allow it.
The extension sends a split-test analytics event to meteor4.com.
The event names record whether the footer was shown or whether the upgrade button was clicked.
| Field | Value | Why it matters | |
|---|---|---|---|
Footer test bucket | wab-footer-test1 | Shows which experiment group was associated with your footer overlay. | |
Interaction event | B - Clicked Upgrade (A) | Records what happened in the extension footer, such as the overlay being shown or the upgrade button being clicked. | |
Fixed flag | yes | Adds a constant marker to the request, so every tracked footer event carries the same flag value. | |
Empty extra field | nf= | Leaves an extra request field blank while still including the field name in the URL. |
Footer events feed the meteor4.com tracking request
"content_scripts": [ {
"all_frames": false,
"css": [ "content.css" ],
"js": [ "modules/jquery-3.6.0.min.js", "modules/common.js", "modules/storage.js", "modules/sset.js", "modules/idb.js", "modules/wlist.js", "modules/hlist.js", "modules/stats.js", "modules/lic.js", "modules/totals.js", "modules/tutorial.js", "modules/notif.js", "modules/foot.js", "modules/head.js", "filters/hosts.js", "filters/sel.js", "filters/extra.js", "filters/fb.js", "filters/yt.js", "filters/search.js", "filters/track.js", "content.js" ],
"matches": [ "http://*/*", "https://*/*" ],
"run_at": "document_start"
} ]// called from content.js
FOOT.showFoot = (totals) => {
var extensionOrigin = 'chrome-extension://' + chrome.runtime.id;
if (!location.ancestorOrigins.contains(extensionOrigin)) {
console.log('FOOT: !location.ancestorOrigins.contains(extensionOrigin)');
let iframe = document.createElement('iframe');
iframe.setAttribute('id','wab-iframe2');
// Must be declared at web_accessible_resources in manifest.json
let sShowFooterC = CONT.SERVER_SETTINGS.SHOW_FOOTER_STRATEGY_C || 'no';
bShowFooterC = (sShowFooterC == 'yes');
let sFootOff = CONT.USER_SETTINGS.xab_foot_off || 'no';
let bFootOff = (sFootOff == 'yes');
// commented out below so that we always show the older footer (foot.html) for now on 11/6/2024
//if (bFootOff && bShowFooterC) {
//iframe.src = chrome.runtime.getURL('/foot2.html');
//} else {
//iframe.src = chrome.runtime.getURL('/foot.html');
//}
//for testing -- iframe.src = chrome.runtime.getURL('/foot-b.html');
//for testing -- iframe.style.cssText = 'display:block !important;background:transparent;position:fixed;left:0;width:100%;bottom:0px;height:205px;z-index:2147483647;border:0px;';
let sShowFooterD = CONT.SERVER_SETTINGS.SHOW_FOOTER_STRATEGY_D || 'no'; // implemented on the server on 11/6/2024
bShowFooterD = (sShowFooterD == 'yes');
if (bShowFooterD) { // show split test
if (COMMON.rand(1,2) == 1) { // condition A (control)
STATS.track('wab-footer-test1','A - Footer Shown (A)');
iframe.src = chrome.runtime.getURL('/foot-a.html');
iframe.style.cssText = 'display:block !important;background:transparent;position:fixed;left:0;width:100%;bottom:0px;height:180px;z-index:2147483647;border:0px;';
} else { // condition B (test)
STATS.track('wab-footer-test1','A - Footer Shown (B)');
iframe.src = chrome.runtime.getURL('/foot-b.html');
iframe.style.cssText = 'display:block !important;background:transparent;position:fixed;left:0;width:100%;bottom:0px;height:205px;z-index:2147483647;border:0px;';
}
} else { // don't show split test
iframe.src = chrome.runtime.getURL('/foot.html');
iframe.style.cssText = 'display:block !important;background:transparent;position:fixed;left:0;width:100%;bottom:0px;height:180px;z-index:2147483647;border:0px;';
}
//iframe.style.cssText = 'display:block !important;background:transparent;position:fixed;left:0;width:100%;bottom:0px;height:180px;z-index:2147483647;border:0px;';
document.body.appendChild(iframe);
let oIframe = document.getElementById('wab-iframe2');
if (oIframe) {
console.log('FOOT: grabbed iframe handle');
setTimeout(function(){
if (oIframe.contentWindow) {
updateTotals = async () => {
CONT.USER_SETTINGS = await STORAGE.readAllSettingsAsync();
let nTotalAds = (totals && totals.ads) ? totals.ads : 0;
let nTotalTrackers = (totals && totals.trk) ? totals.trk : 0;
let nMaxAds = CONT.USER_SETTINGS.xab_max_ads || 0;
let nMaxTrackers = CONT.USER_SETTINGS.xab_max_trackers || 0;
nMaxAds = (nMaxAds < nTotalAds) ? nTotalAds : nMaxAds;
nMaxTrackers = (nMaxTrackers < nTotalTrackers) ? nTotalTrackers : nMaxTrackers;
nMaxAds = (nMaxAds > COMMON.MAX_TOTAL_AD_COUNT) ? COMMON.MAX_TOTAL_AD_COUNT : nMaxAds;
nMaxTrackers = (nMaxTrackers > COMMON.MAX_TOTAL_AD_COUNT) ? COMMON.MAX_TOTAL_AD_COUNT : nMaxTrackers;
STORAGE.saveSetting('xab_max_ads',nMaxAds);
STORAGE.saveSetting('xab_max_trackers',nMaxTrackers);
CONT.USER_SETTINGS.xab_max_ads = nMaxAds;
CONT.USER_SETTINGS.xab_max_trackers = nMaxTrackers;
oIframe.contentWindow.postMessage({onWABUpdatedMaxCount:{maxAds:nMaxAds,maxTrackers:nMaxTrackers}},'*');
};
updateTotals();
}
},2000);
}
}
};// called from foot.html
FOOT.onUserClickUpgrade = () => {
let sWhich = 'A';
if ($('#wabfoot').hasClass('wabfootb')) { // condition B (test)
STATS.track('wab-footer-test1','B - Clicked Upgrade (B)');
sWhich = 'B';
} else { // condition A (control)
STATS.track('wab-footer-test1','B - Clicked Upgrade (A)');
}
FOOT.onUserClickClose();
window.parent.postMessage({onWABFootUpgrade:true,whichFooter:sWhich},'*');
};
// called from foot.html
FOOT.loadFootPageCode = () => {
window.addEventListener('message',function(e) {
let o = event.data;
(o.onWABUpdatedMaxCount) && FOOT.onUpdatedCount(o.onWABUpdatedMaxCount);
},false);
$(document).ready(function() {
$('#wabfoot #remind').click(function(e) {
FOOT.onUserClickReminder();
});
$('#wabfoot #upgrade').click(function(e) {
e.preventDefault();
FOOT.onUserClickUpgrade();
return false;
});
$('#wabfoot #close').click(function(e) {
e.preventDefault();
FOOT.onUserClickClose();
return false;
});
});
};var STATS = {}; // feature split test tracking
STATS.track = (sBucket,sEvent) => { // for split tests
// meteor4.com, owned by webadblocker.org
fetch('https://meteor4.com/meteor/write?b=' + '' + encodeURIComponent(sBucket) + '&ev=' + encodeURIComponent(sEvent) + '&f=yes&nf=')
.then(response => response.text())
.then(text => {
console.log('STATS: tracking response text: ',text);
})
.catch(error => {
console.error('error',error);
});
};- meteor4.com
Receives footer split-test analytics. A source comment says this host is owned by webadblocker.org.