Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/ISSUE_TEMPLATE/broken_site.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ body:
- "Not sure"
validations:
required: true
- type: dropdown
id: decoy_mode
attributes:
label: Was experimental Decoy Mode on?
description: If possible, reproduce once with Decoy Mode off and include both results.
options:
- "No"
- "Yes"
- "Not sure"
validations:
required: true
- type: textarea
id: media
attributes:
Expand Down
4 changes: 3 additions & 1 deletion .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ Closes #

- [ ] I did not add broad/high-breakage domains.
- [ ] I did not add payment processors, login providers, captcha services, core CDNs, or broad platform domains.
- [ ] I did not add analytics, telemetry, external network calls, remote logging, or servers.
- [ ] I did not add extension-owned analytics, telemetry, remote logging, servers, or network requests. Decoy Mode changes only eligible page-initiated requests.
- [ ] I did not fabricate or rewrite purchase, conversion, transaction, revenue, product, currency, or ad-click fields.
- [ ] I did not add declarativeNetRequestFeedback.
- [ ] I did not add webRequestBlocking.
- [ ] I did not reintroduce privacy score.
- [ ] I ran npm run generate:rules.
- [ ] I ran npm run test:evidence.
- [ ] I ran npm run check.
- [ ] I ran JSON/JS syntax checks.
- [ ] I updated README/docs if behavior changed.
22 changes: 13 additions & 9 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ Thanks for helping improve GetBlocked! The project is intentionally small, local
3. Run the relevant commands:

```bash
npm run generate:rules
npm run test:evidence
npm run check
```

4. Open a pull request.
Expand All @@ -33,8 +32,11 @@ Useful files:
- `rules/rules.json`: generated DNR rules.
- `shared/tracker-catalog.json`: source tracker catalog.
- `shared/config.js`: generated content-script config.
- `shared/decoy-transform.js`: request-field replacement helpers.
- `content-script.js`: visible tracking-signal detection.
- `background.js`: local report state and URL-cleaning counts.
- `decoy-bridge.js`: isolated-world Decoy Mode bridge.
- `decoy-interceptor.js`: experimental main-world request wrappers.
- `background.js`: local report, rule-mode, session-profile, and URL-cleaning state.
- `popup/`: popup UI.

## How To Run Tests
Expand All @@ -51,16 +53,14 @@ Run the evidence fixture:
npm run test:evidence
```

Run syntax checks:
Run the complete local check suite:

```bash
node --check background.js
node --check content-script.js
node --check popup/popup.js
node --check scripts/generate-rules.mjs
node --check scripts/evaluate-test-set.mjs
npm run check
```

For Decoy Mode work, also run `npm run test:browser` when a compatible local Chromium-family browser is available. See [docs/DECOY_MODE.md](docs/DECOY_MODE.md) and [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md).

## How To Add A Tracker Domain

The easiest first PR is adding one well-scoped tracker domain and one test fixture.
Expand All @@ -84,6 +84,7 @@ For broken sites, include:
- Steps to reproduce.
- Chrome version and OS.
- Whether disabling GetBlocked! fixes it.
- Whether Decoy Mode was off or on.
- Suspected tracker category or domain, if known.
- Screenshot or video when useful.

Expand All @@ -109,6 +110,7 @@ You do not need to ask before opening a small PR for tracker-domain additions, b
- [ ] I updated docs if behavior changed.
- [ ] I ran `npm run generate:rules` if the catalog or params changed.
- [ ] I ran `npm run test:evidence`.
- [ ] I ran `npm run check`.
- [ ] I ran relevant JSON/JS syntax checks.
- [ ] I did not add broad/high-breakage domains.
- [ ] I did not add exaggerated privacy claims.
Expand All @@ -122,6 +124,8 @@ You do not need to ask before opening a small PR for tracker-domain additions, b
- Do not block captcha services.
- Do not block core CDNs.
- Do not add external analytics, telemetry, remote calls, or logging.
- Do not initiate, duplicate, replay, or fabricate tracker events. Decoy Mode may only modify eligible page-initiated requests to catalog domains.
- Do not rewrite purchase, conversion, transaction, revenue, product, currency, or ad-click fields.
- Do not reintroduce `declarativeNetRequestFeedback`.
- Do not reintroduce `webRequestBlocking`.
- Do not reintroduce privacy score.
Expand Down
66 changes: 61 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

**Cleaner pages. Fewer trackers. Local-only.**

GetBlocked! is a lightweight, local-only Chrome extension that helps reduce common third-party website tracking by blocking known tracker requests, cleaning tracking links, and explaining tracking attempts.
GetBlocked! is a lightweight, local-only Chrome extension that helps reduce common third-party website tracking by blocking known tracker requests, cleaning tracking links, and explaining tracking attempts. An optional experimental Decoy Mode can instead let known tracker requests through while replacing supported analytics identifiers with one consistent fake browser-session profile.

It is built as a small, inspectable Manifest V3 project for people who want a friendly privacy tool and for contributors who want quick, useful pull requests.

Expand All @@ -17,10 +17,12 @@ It is built as a small, inspectable Manifest V3 project for people who want a fr
- Detects visible tracking attempts such as pixels, suspicious scripts, tracking iframes, and tracking links.
- Shows a compact popup report with:
- Blocked on this page
- Decoyed on this page
- Tracking links cleaned
- Visible tracking attempts detected
- Detected categories
- Keeps report data local in `chrome.storage.local`.
- Saves the Decoy Mode preference locally and keeps the generated fake profile only in `chrome.storage.session`.

## What GetBlocked! Can Block

Expand All @@ -38,6 +40,8 @@ Current coverage includes:

The tracker list is intentionally conservative. Rules are limited to third-party requests to reduce website breakage.

When experimental Decoy Mode is on, the main tracker-blocking rule is disabled, but tracking-parameter cleanup remains enabled. Page-level `fetch`, `XMLHttpRequest`, and `navigator.sendBeacon` calls to domains in the same catalog are intercepted where feasible.

## What GetBlocked! Cannot Do

- It does not block every tracker.
Expand All @@ -46,6 +50,23 @@ The tracker list is intentionally conservative. Rules are limited to third-party
- It does not stop server-side tracking.
- It does not fully prevent advanced fingerprinting.
- It is not meant to replace full-featured ad blockers.
- Decoy Mode cannot hide an IP address, TLS/network metadata, browser fingerprint, or identifiers added outside the supported request formats.
- Decoy Mode cannot rewrite image pixels, scripts, forms, WebSockets, or requests that begin before its session configuration is available.

## Experimental Decoy Mode

Decoy Mode is off by default. Use the clearly labeled **Experimental** toggle in the popup to enable it.

While enabled:

- Static rule `1`, the catalog-based third-party tracker blocker, is disabled.
- Static rule `1000`, tracking-parameter cleanup for top-level navigation, stays enabled.
- Known tracker requests made with `fetch`, `XMLHttpRequest`, and `navigator.sendBeacon` are inspected in the page's main JavaScript world.
- Common analytics identifiers and profile fields, including anonymous, client, user, device, and session IDs plus supported email/name/phone fields, are replaced when their request format is supported.
- One coherent fake profile is reused across tabs for the current browser/extension session. It is discarded when Chrome restarts or the extension is reloaded, disabled, or updated.
- A request counts as decoyed only when at least one supported field is actually replaced.

Decoy Mode does not create requests and never changes event names, event types, order or transaction IDs, products, prices, amounts, currencies, conversions, purchases, or ad-click fields. Existing transactional events are not invented or reclassified. Because tracker requests are allowed to reach their destinations, those services may still observe the user's IP address and other network metadata. See [Decoy Mode details](docs/DECOY_MODE.md).

## How GetBlocked! Is Different

Expand All @@ -64,9 +85,10 @@ GetBlocked! does not send browsing data to any server. The extension uses:

- `declarativeNetRequest` for local Chrome-managed request blocking.
- `chrome.storage.local` for page report data.
- `chrome.storage.session` for the in-memory Decoy Mode fake profile.
- A content script that scans the current page locally for visible tracking signals.

There are no external analytics, telemetry endpoints, remote logs, or bundled remote assets in the extension.
There are no extension-owned analytics, telemetry endpoints, remote logs, or bundled remote assets. In Decoy Mode, the page's existing tracker requests are intentionally allowed through with supported identifiers replaced; GetBlocked! does not initiate additional tracker requests.

## Install Locally In Chrome

Expand All @@ -77,7 +99,7 @@ There are no external analytics, telemetry endpoints, remote logs, or bundled re
5. Select the GetBlocked! project folder.
6. Pin GetBlocked! and open the popup on normal web pages.

The production build avoids debug-only DNR feedback permissions. The popup uses local page signals plus Chrome's production DNR action-count badge as a page-level estimate, while blocking and URL-cleaning rules remain enforced by MV3 `declarativeNetRequest`.
The production build avoids debug-only DNR feedback permissions. The popup uses local page signals plus Chrome's production DNR action-count badge as a page-level estimate. In normal mode, blocking and URL cleanup are enforced by MV3 `declarativeNetRequest`; in Decoy Mode, only the blocking rule is disabled.

## Contribute In 10 Minutes

Expand Down Expand Up @@ -113,7 +135,7 @@ npm run generate:rules
This updates:

- [rules/rules.json](rules/rules.json), used by Chrome `declarativeNetRequest`.
- [shared/config.js](shared/config.js), used by the content script and popup category detection.
- [shared/config.js](shared/config.js), used by page detection and to scope Decoy Mode to the tracker catalog.

Do not edit generated rules/config by hand unless you also update the generator or source catalog.

Expand All @@ -134,12 +156,43 @@ Useful individual checks:
```bash
npm run generate:rules
npm run test:evidence
npm run test:decoy
npm run check:syntax
npm run check:json
npm run check:generated
npm run check:safety
```

Run the automated browser test with a compatible Chromium-family browser:

```bash
npm run test:browser
```

This launches Chrome with the unpacked extension loaded, navigates to
`test/manual-test.html` with common tracking URL parameters, and verifies:

- Tracking parameters (`utm_source`, `fbclid`, `gclid`, …) are removed from the
final page URL by the extension's `declarativeNetRequest` redirect rules.
- The extension background service worker returns a report with nonzero page
activity detected by the content script.
- Decoy Mode disables only the blocking rule, reuses one session profile,
preserves URL cleanup, counts modified requests, and restores normal mode.
- No unexpected runtime exceptions are thrown by the extension.

No npm packages are required. The test uses only Node.js built-ins and Chrome's
remote debugging protocol (CDP). Some branded browser builds ignore
`--load-extension`; if no compatible browser is found or the unpacked extension
does not load, the test exits with code 0 and prints a skip notice.

Override defaults with environment variables:

| Variable | Default | Purpose |
|---|---|---|
| `CHROME_PATH` | auto-detected | Path to a compatible Chromium-family executable |
| `TEST_PORT` | `8765` | Local static file server port |
| `DEBUG_PORT` | `9333` | Chrome CDP remote debugging port |

## Manual Browser Check

After loading the unpacked extension, start a simple local server from this folder:
Expand All @@ -154,14 +207,17 @@ Then open:
http://localhost:8080/test/manual-test.html?utm_source=demo&utm_medium=test&fbclid=manual
```

With GetBlocked! enabled, the tracking parameters should be removed from the page URL and the popup should show page-level tracker activity. For a before/after check, compare the browser Network panel with the extension disabled and then enabled.
With GetBlocked! enabled and Decoy Mode off, the tracking parameters should be removed from the page URL and known third-party tracker requests should be blocked. The popup should show page-level tracker activity.

Then turn on **Decoy Mode (Experimental)** in the popup and reload the fixture. URL cleanup should continue, supported identifiers in the fixture's `fetch`, XHR, and beacon calls should be replaced, and **Decoyed on this page** should increase. The tracker requests themselves may still fail because the example endpoints reject test/CORS traffic; the counter records the local replacement attempt. Turn Decoy Mode off again to restore normal blocking.

## Contributor Links

- [Contributing guide](CONTRIBUTING.md)
- [Adding trackers](docs/ADDING_TRACKERS.md)
- [Broken sites](docs/BROKEN_SITES.md)
- [Development guide](docs/DEVELOPMENT.md)
- [Decoy Mode](docs/DECOY_MODE.md)
- [Good first issues](docs/GOOD_FIRST_ISSUES.md)
- [Labels guide](docs/LABELS.md)
- [Launch copy](docs/LAUNCH_COPY.md)
Expand Down
10 changes: 10 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ GetBlocked! should remain local-only.
- Remote logging should not be added.
- Remote scripts, fonts, or assets should not be added.

Experimental Decoy Mode does not change this extension-owned local-only requirement. It has no backend and creates no tracker traffic, but it intentionally allows the page's existing catalog-matched tracker requests to reach their remote destinations after supported identifier/profile replacement. Those destinations can still observe IP address and network metadata. Privacy reports should distinguish extension-owned network activity from page-owned traffic modified by Decoy Mode.

## Decoy Mode Safety Boundary

- Only exact domains and subdomains generated from `shared/tracker-catalog.json` may be targeted.
- The fake profile must remain in `chrome.storage.session` and must not contain user-derived data.
- Request wrappers must not create, replay, duplicate, or schedule network events.
- Event names/types and transactional fields such as purchases, conversions, orders, products, prices, amounts, currencies, and ad clicks must not be fabricated or rewritten.
- The popup must continue warning that allowed tracker requests can reveal IP/network metadata.

## Permission Expansion

Permission expansion is security-sensitive. Any PR that changes `manifest.json` permissions should explain:
Expand Down
Loading
Loading