Is Focus & Productivity Booster safe?
Focus & Productivity Booster sends the title and hostname of every blocked page to safefocusing.com and fetches the list of sites it blocks from the same server.
When you visit a site on the extension's block lists (social media, streaming, user-added domains, and a remotely fetched list), it loads an iframe from safefocusing.com/safe/block.php with the page title and hostname appended to the URL. The set of blocked sites is pulled from safefocusing.com/filter/ at startup with no integrity check, and the extension strips X-Frame-Options and Referer headers for requests from safefocusing.com. A content-script message handler also runs fetch() with a URL and request options supplied by any message whose origin string merely contains 'safefocusing.com'.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Framing and referrer headers removed for safefocusing.com
The extension installs a network rule for safefocusing.com main-frame, sub-frame, and XHR loads.
It strips X-Frame-Options and Referer from matching traffic, so those pages lose a framing header and source-page context.
What actually happens
You install the extension and the background service worker starts.
The extension registers a browser network rule for requests initiated by safefocusing.com.
That rule removes one response header that blocks framing and one request header that identifies the referring page.
Concrete fields in session rule 1
- Site that starts the requestsafefocusing.com
Only requests started by this site match the rule, so the header changes are tied to that site rather than every site you visit.
- Frame-blocking response headerX-Frame-Options
This header normally lets a site say it should not be embedded in another page. Removing it can change whether that page can be framed.
- Referring-page request headerReferer
This header can show which page led to a request. Removing it strips that source-page context from matching requests.
- Affected request typesmain frame, subframe, XMLHttpRequest
The rule covers page loads, embedded frames, and background page requests initiated by the matching site.
The code that does this
The shipped bundle and readable source register the same header-removal rule
Readable session-rule registration
background.jschrome.declarativeNetRequest.updateSessionRules({ addRules: [{ id: 1, priority: 1, action: { type: chrome.declarativeNetRequest.RuleActionType.MODIFY_HEADERS, responseHeaders: [{ header: "X-Frame-Options", operation: chrome.declarativeNetRequest.HeaderOperation.REMOVE }], requestHeaders: [{ header: "Referer", operation: chrome.declarativeNetRequest.HeaderOperation.REMOVE }] }, condition: { initiatorDomains: ["safefocusing.com"], resourceTypes: [chrome.declarativeNetRequest.ResourceType.XMLHTTPREQUEST, chrome.declarativeNetRequest.ResourceType.MAIN_FRAME, chrome.declarativeNetRequest.ResourceType.SUB_FRAME] } }], removeRuleIds: [1]});Domain named by the rule condition
- safefocusing.com
Requests initiated by this host match the session rule that removes the listed response and request headers.
Remote filter list controls content-script injection
A request to safefocusing.com/filter/ returned HTTP 200.
The code fetches that list, saves it as childSafetyUris, and, with Child Safety on by default, registers icontent.js/css in all frames for hosts from the list.
No body was recorded.
What actually happens
The extension refreshes its settings after the background service worker starts.
It requests a domain list from safefocusing.com and uses the returned hosts to register content scripts.
The scripts are registered for all frames on HTTPS match patterns built from the response.
Captured request
HTTP 200 observed during dynamic analysis; no request body was recorded in the available evidence.
Fields that turn the remote list into injection rules
- Remote list endpointhttps://safefocusing.com/filter/
This address supplies the list that decides which browsing locations receive the extension's page scripts.
- Stored host listchildSafetyUris
The extension saves the returned list locally so later code can decide whether the current site is on that list.
- Generated match patternhttps://*.wikipedia.org/* (illustrative)
Each returned host is converted into an HTTPS rule that covers that host's subdomains and paths.
- Injected filesicontent.js, icontent.css
These extension files are the page scripts and styles that run when you browse to a matched host.
- Frame coverageallFrames: true
The rule applies inside embedded frames as well as the top-level page on a matched host.
The code that does this
The shipped bundle fetches the remote list and registers all-frame scripts
Default Child Safety setting
background.jsconst _ = p(te), ae = { enabled: !0, autoBlocks: [{ name: "Child Safety", slug: "childSafety", enabled: !0 }, { name: "Social Media", slug: "socialMedia", enabled: !1 }, { name: "Streaming Services", slug: "streamingServices", enabled: !1 }], customDomains: [] }, ie = async () => { const s = await _.storage.local.get("settings"); return s.hasOwnProperty("settings") ? s.settings : ae };Remote hosts become all-frame content-script rules
background.jsasync function s(t, g) { if (t.length === 0) { var l = await chrome.scripting.getRegisteredContentScripts({ ids: [g] }); l.length > 0 && await chrome.scripting.unregisterContentScripts({ ids: [g] }); return } try { await chrome.scripting.unregisterContentScripts({ ids: [g] }) } catch {} const f = t.map(b => { try { const U = b.includes("://") ? b : `https://${b}`; return "https://*." + new URL(U).host + "/*" } catch { return b } }); chrome.scripting.registerContentScripts([{ id: g, matches: f, allFrames: !0, js: ["icontent.js"], css: ["icontent.css"], runAt: "document_end" }])}const e = async t => { const g = t.customDomains.filter(d => d.enabled).map(d => d.uri); await s(g, "customDomains"); const l = ["facebook.com", "instagram.com", "twitter.com", "youtube.com", "x.com"], f = t.autoBlocks.filter(d => d.enabled && d.slug == "socialMedia").length > 0; await s(f ? l : [], "socialMedia"); const b = ["netflix.com", "hulu.com", "hbo.com", "hbo.com", "hbo.com"], U = t.autoBlocks.filter(d => d.enabled && d.slug == "streamingServices").length > 0; await s(U ? b : [], "streamingServices"); var R = []; try { var B = await fetch("https://safefocusing.com/filter/"); R = await B.json(), await chrome.storage.local.set({ childSafetyUris: R }) } catch {} const X = t.autoBlocks.filter(d => d.enabled && d.slug == "childSafety").length > 0; await s(X ? R : [], "childSafety")};Remote host involved in the rule generation path
- safefocusing.com
Provides the filter endpoint whose JSON response is used to derive content-script match patterns.
Where it sends data
Destinations our analysis observed Focus & Productivity Booster 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.
- safefocusing.com
Focus & Productivity Booster sends data to safefocusing.com. No other extension we have analyzed sends data here.