# Poke Shield - Privacy Blocker

A privacy-focused Chrome / Chromium extension (Manifest V3) that blocks ads,
trackers, and telemetry, cleans tracking URLs, and hides annoying overlays. It
is an **unpacked developer build** and is **not published on the Chrome Web
Store**.

Everything runs locally in your browser. The extension sends no telemetry and
does not collect or transmit your browsing history.

---

## Install (Load unpacked)

1. Download and unzip `poke-privacy-blocker.zip`.
2. Open Chrome / Chromium and go to `chrome://extensions`.
3. Turn on **Developer mode** (toggle in the top-right corner).
4. Click **Load unpacked**.
5. Select the extracted `extension/` folder (the one containing `manifest.json`).
6. Pin Poke Shield from the toolbar to open the popup.

The extension is enabled by default with all protections on.

---

## What it does

| Feature | How it works |
| --- | --- |
| **Tracker blocker** | `declarativeNetRequest` static ruleset (`rules/trackers.json`) blocks cross-site trackers, fingerprinters, and session-recording scripts. |
| **Ad blocker** | `rules/ads.json` blocks ad servers, ad networks, and ad exchanges. |
| **Telemetry & pixels** | `rules/telemetry.json` blocks analytics, advertising pixels, and beacons: Google Analytics, Google Tag Manager, Meta/Facebook Pixel, TikTok Pixel, Criteo, Hotjar, Mixpanel, Segment, Sentry tracing, and more. |
| **URL cleaner** | Content script (`content/url-cleaner.js`) strips `utm_*`, `fbclid`, `gclid`, `mc_eid`, `igshid`, `dclid`, `msclkid`, `ttclid`, `twclid`, `_ga` and similar tracking parameters from the current URL and from outbound links, preserving functional parameters. |
| **Cosmetic filtering** | Content script (`content/cosmetic-filter.js`) hides clearly labeled ad containers, ad slots, sponsored posts, cookie banners, and anti-adblock overlays with a conservative selector list, and collapses empty ad slots left behind after network blocking. |
| **Annoyance blocking** | `rules/annoyances.json` blocks consent-management and anti-adblock scripts. |
| **YouTube handling** | Main-world sanitizer removes ad fields from player responses before playback, plus cosmetic hiding of sponsored/ad modules and a guarded skip fallback (see "YouTube handling" below). |
| **Redirect cleaning** | `rules/url-tracking.json` unwraps common tracking redirectors (Google `/url`, Facebook `l.php`, Reddit `out.reddit`, YouTube `/redirect`, DuckDuckGo `/l`). |

---

## File layout

```
extension/
  manifest.json              MV3 manifest + static ruleset declarations
  background/
    service-worker.js        Settings, ruleset toggles, allowlist, stats, badge
  content/
    url-cleaner.js           Query-parameter stripping (document_start)
    cosmetic-filter.js       Ad/annoyance hiding + empty-slot collapse
    youtube.js               YouTube cosmetic hiding + guarded skip fallback
    youtube-sanitize.js      YouTube player ad-data sanitizer (MAIN world)
  rules/
    youtube.json             YouTube ad/telemetry endpoint rules
    ads.json                 Ad server / network rules
    trackers.json            Cross-site tracker rules
    telemetry.json           Analytics / pixel / beacon rules
    annoyances.json          Consent + anti-adblock rules
    url-tracking.json        Redirector-unwrap rules
  popup/                     Toolbar dashboard (toggles, stats, allowlist)
  options/                   Full settings page
  icons/                     Generated PNG icons + source SVG
  README.md                  This file
```

---

## Privacy model

- **No remote code.** No external scripts are loaded at runtime.
- **No telemetry.** The extension never phones home.
- **No browsing-history collection.** The extension only reads the URL of the
  active tab to power the per-site allowlist toggle in the popup.
- **Local storage.** Settings and the blocked-request counter live in
  `chrome.storage` on your device.
- **Best-effort stats.** The blocked counter uses
  `chrome.declarativeNetRequest.onRuleMatchedDebug`, which requires the
  `declarativeNetRequestFeedback` permission. It only counts requests the
  extension has host access to. If the counter is unavailable on a given build
  it simply stays at zero; nothing breaks.

---

## Limitations & site breakage

- Blocking is a curated starter set, not a full commercial filter. Some ads or
  trackers will still get through.
- Aggressive blocking can break sites that hard-depend on a blocked domain
  (paywalls, some login flows, some video players). If a site misbehaves, add
  it to the **allowlist** from the popup or options page.
- Cosmetic filtering is deliberately conservative to avoid hiding real content.
  It targets clearly labeled cookie, sponsored, and anti-adblock elements only.
- URL cleaning preserves functional parameters and only removes known tracking
  keys; it never touches the path or fragment.
- `declarativeNetRequest` has platform limits (see below). This starter set
  stays well within them.

---

## List attribution & licensing

The bundled rules are an **original, curated starter set**. They are **not** a
wholesale copy of any upstream list. The projects below are inspirations and
**optional compatible sources** you can import or convert yourself. Always
respect each project's license when importing its content.

| Project | What it is | Source / license |
| --- | --- | --- |
| EasyList | Ad-blocking filter lists | https://easylist.to - GNU GPL v3 |
| EasyPrivacy | Tracking-protection filter list | https://easylist.to - GNU GPL v3 |
| Peter Lowe's Ad and tracking server list | Blocklist of ad/tracking servers | https://pgl.yoyo.org/adservers/ - MIT |
| AdGuard Base / Tracking Protection | Ad & tracking filter lists | https://adguard.com/en/filter-rules.html - GPL v3 |
| OISD | Domain blocklist | https://oisd.nl - MIT |
| HaGeZi's Multi PRO / The Blocklist Project | Tracking / ads blocklist | https://github.com/hagezi/dns-blocklists - CC BY 4.0 |
| ClearURLs | URL tracking-parameter removal | https://gitlab.com/ClearURLs/ClearUrls - MPL 2.0 |
| uBlock Origin | Ad/tracker blocker (syntax reference) | https://github.com/gorhill/uBlock - GPL v3 |

### MV3 limits & conversion notes

Chrome's `declarativeNetRequest` API caps each static ruleset at **3000 rules**,
allows up to **100 static rulesets** with **50 enabled at once**, and limits
regex rules to **1000**. uBlock/EasyList-style rules use a different syntax
(domain anchors like `||domain^`, cosmetic `##` rules, `$` modifiers), so they
must be converted to MV3 `urlFilter` / `regexFilter` / `redirect` rules before
use. This project ships small, hand-curated rulesets that stay far below the
limits; import larger lists at your own discretion and re-validate them.

---

## Threat model

- **In scope:** third-party ads, trackers, analytics, pixels, beacons, session
  recording, consent/anti-adblock scripts, and tracking query parameters.
- **Out of scope:** first-party cookies, fingerprinting done by the site itself
  via its own domain, DNS-level blocking, and browser-fingerprint
  randomization. This extension does not spoof or randomize your fingerprint.
- **Trust boundary:** the extension is trusted to read the active tab URL and to
  modify page DOM (cosmetic filtering, URL cleaning). It does not read passwords,
  form data, or browsing history.

---

## Testing checklist

- [ ] `chrome://extensions` loads the unpacked folder with no manifest errors.
- [ ] Popup opens; master toggle and all feature toggles persist after reload.
- [ ] Visit a page with Google Analytics / GTM: network requests to
  `google-analytics.com` / `googletagmanager.com` are blocked and the counter
  increments.
- [ ] Visit a page with a cookie banner: the banner is hidden.
- [ ] Open a URL containing `?utm_source=x&fbclid=y`: the params are stripped
  from the address bar without a reload loop.
- [ ] Click a link with tracking params: the cleaned URL loads.
- [ ] Allowlist a domain: blocking stops on that domain; remove it and blocking
  resumes.
- [ ] Reset all settings returns everything to defaults.
- [ ] Run `npm run validate` (or the build) to confirm manifest + rules JSON are
  valid.

## Cosmetic filtering

Cosmetic filtering hides only advertising-related elements: ad containers
(`.ad-container`, `[class*="ad-slot"]`, `[id*="google_ads"]`,
`ins.adsbygoogle`, `[data-ad-slot]`), sponsored posts and labels, cookie-consent
banners, and anti-adblock overlays. Selectors are conservative and
advertising-specific; arbitrary content is never hidden. A `MutationObserver`
collapses empty ad slots and placeholders that remain after network blocking
removed their ad content, so pages no longer show empty grey boxes.

## YouTube handling (best-effort)

YouTube ad handling is a two-layer, best-effort design inspired by uBlock
Origin / uBOL / Brave scriptlet concepts. YouTube changes frequently, and
browser extension APIs and site policies can limit what is possible. It does
not claim to guarantee bypass or evasion.

**Primary - early data sanitization** (`content/youtube-sanitize.js`, MAIN
world, `document_start`): before the player consumes it, the script removes
ad-related fields (`adPlacements`, `playerAds`, `adSlots`, `adBreakParams`) from
`ytInitialPlayerResponse` and relevant player objects, and wraps page-context
`JSON.parse`, `fetch`, and `XMLHttpRequest` so that `/youtubei/v1/player`
responses are sanitized before the player reads them. Wrappers are narrowly
scoped to YouTube player responses, keep all normal video data intact, avoid
recursive hooks, and fail safe (original data is returned if anything throws).

**Secondary - cosmetic filtering** (`content/youtube.js`, isolated world,
`document_idle`): hides sponsored banner cards, video overlays, home-feed promo
shelves, sidebar and in-feed ad modules
(`ytd-promoted-video-renderer`, `ytd-ad-slot-renderer`, `.ytp-ad-module`,
`.ytp-ad-overlay-container`, and similar) with a MutationObserver and a
scheduled scan for SPA navigation. The only fallback is a single, guarded click
of a visible "Skip Ad" button when an ad is actively showing - it never
aggressively fast-forwards or changes audio.

**Network layer** (`rules/youtube.json`): blocks dedicated YouTube ad and
telemetry endpoints (`/api/stats/ads`, `/api/stats/qoe`, `/ptracking`,
`/pagead/`, `/youtubei/v1/log_event`, and similar), while never blocking the
video player data itself.

If YouTube changes its markup or API, some or all of this may stop working.
That is expected; the extension degrades gracefully and never breaks playback.

---

## Build & validation

From the repo root:

```bash
node scripts/package-extension.mjs   # validates, generates icons, builds the zip
npm run validate                    # runs the validation + packaging tests
```

The packaging script is dependency-free and reproducible. It writes
`public/poke-privacy-blocker.zip` and mirrors the source into
`public/extension/` so the hosted project page can serve both.
