Pharos privacy policy
DRAFT. Not legal advice. Needs legal review before any Chrome Web Store submission. Written for the alpha (5 to 10 trusted testers who install the unpacked extension themselves). It describes what the code in this repository does as of version 0.6.0 (Weekend 4.5 added the optional alpha tester backend, section 2a; Weekend 5 added rescans when a page changes after it was checked, section 1). If the code and this document disagree, the code is wrong or this document is out of date: please open an issue.
Pharos is a browser extension that warns about and blocks phishing pages, fake virus warnings, payment scams and malicious downloads. To do that it has to look at the pages you visit. This document says exactly what it looks at, what leaves your computer, what stays, and what never happens.
A shorter, plain-language version ships inside the extension (extension/privacy.html, linked from onboarding and Settings → Privacy).
1. What Pharos reads
| Data | When | Why |
|---|---|---|
| Page URL | Every page you open (top frame) | Checked against blocklists, scored by local URL heuristics, sent to the checkers below for pages that aren't already known |
| Page title | Every page Pharos checks | Context for the checkers |
| Visible page text and inline scripts (DOM text) | Every page Pharos checks | Read on your computer only: (a) hashed into a short fingerprint so a page that was already judged isn't sent again; (b) matched against patterns that identify redirect notices and browser security-warning pages, which Pharos skips. The text itself is not stored and not sent anywhere |
| Screenshot of the visible part of the page | Only once the screenshot checker (Cloudflare) is set up, and only for pages that aren't on the popular-sites allowlist, aren't blocked or warned by the URL checks, and aren't in the verdict cache. Taken again if the page changes significantly after it was checked (a full-screen overlay appears, it goes fullscreen, its content is replaced, it opens repeated dialogs, or its text changes a lot), because scam pages can look harmless at first | Sent to the screenshot checker (Clef) and, when it is unsure, to the AI double-check (the arbiter) |
| Download URL and file name | Every download | Checked against blocklists and file-name heuristics; suspicious downloads are paused until you choose Keep or Discard |
How often a page opens alert()/confirm() dialogs | Every page | A page firing many dialogs in a short time is closed (a common scam trap) |
The arbiter does not receive page text. It gets the same screenshot, URL and title as Clef, plus Clef's probability scores.
2. What Pharos sends, and to whom
In Direct mode (the default) Pharos has no server of its own. Everything external goes from your browser directly to a third party, using accounts and API keys that you own. Alpha tester mode is different; see section 2a.
| Recipient | What is sent | When |
|---|---|---|
Cloudflare Workers AI (api.cloudflare.com, model @cf/cloudflare/clef-flash) on your Cloudflare account | Screenshot (JPEG, at most 1280 px wide), page URL, hostname, page title, and fixed instructions | Pages that reach the screenshot tier (see above) |
| The AI service you chose for the double-check: OpenAI, Anthropic, Google (Gemini) or xAI | The same screenshot, URL, hostname and title, plus Clef's scores | Only when Clef's answer is not a clear "legitimate" (typically a few pages in a hundred). Never when the arbiter is set to Off or has no key |
| Blocklist publishers: URLhaus (abuse.ch), OpenPhish, and PhishTank if you add a key | Nothing about you. Pharos downloads their public lists (PhishTank's download URL contains your PhishTank key) | On install, every 6 hours, and when you click Refresh |
| The same checkers, for "Test connection" | The Pharos icon as the image, and https://example.com/ as the URL | Only when you click Test connection or Check again |
Each of these companies handles that data under its own terms and privacy policy, under your account with them. Review those terms, in particular whether the provider may retain or train on API inputs.
2a. Alpha tester backend (only if you set an alpha token)
Alpha testers can use Pharos without any accounts of their own. This mode is only active when you explicitly choose it: by answering "Yes" to "Do you have a Pharos alpha token?" during setup and pasting a token, or by selecting "Alpha tester" under Settings → Backend mode and saving a token. Switching back to Direct mode stops it immediately.
In alpha mode, the Pharos developer runs a small server (a Cloudflare Worker with a D1 database, code in worker/). It holds the developer's own Cloudflare and AI keys; your browser never receives them.
What crosses the network to the Worker:
| Request | Contents | When |
|---|---|---|
Screenshot check (/v1/clef) | Your tester token, plus the same request Pharos would otherwise send to Cloudflare: screenshot, page URL, hostname, page title | Pages that reach the screenshot tier |
AI double-check (/v1/arbiter) | Your tester token, plus the same request Pharos would otherwise send to OpenAI or Anthropic: screenshot, URL, title, the screenshot checker's scores | When the screenshot checker is unsure |
Budget check (/v1/quota) | Your tester token | At browser start, every 5 minutes, and when you press Test or Check again |
Telemetry (/v1/telemetry) | Your tester token and the same counts as section 5 (verdicts by category, latency buckets, error and panic counts), plus each "Pharos got this wrong" report with the page's URL and title, and a note when the backend was unreachable | About once a minute, or after 50 events, only while "Help improve Pharos" is ticked (it is ticked for you when you switch to alpha mode; untick it to stop) |
The Worker passes screenshot and double-check requests on to Cloudflare Workers AI, OpenAI or Anthropic, under the developer's accounts, and returns their answers. Those providers' terms apply, under the developer's account.
What the Worker stores (D1):
| Table | Contents |
|---|---|
testers | Your token, the name and email the developer entered when inviting you, creation date, budget, amount spent, active flag |
events | Per check: the model, token counts, cost, latency and success or error status. Never the screenshot, the URL or the title of a checked page. Telemetry batches (counts only), panic-button triggers, quota-exceeded events, backend-health failures, and your "Pharos got this wrong" reports (which do include the URL and title you reported) |
daily_rollup | Per tester and day: number of checks, verdict counts, panic count, cost |
This data is linked to your tester token, and the developer knows which token they gave to whom, so it is pseudonymous rather than anonymous. It is used only to run the alpha: to keep within budgets, find bugs, and improve Pharos's accuracy. The developer sees it on a password-protected dashboard (tokens shown by their last 4 characters only) and, optionally, in a weekly email summary that lists false-positive reports with their URLs.
Retention: all telemetry and events are to be deleted 30 days after the alpha ends (the commands are in worker/README.md), and tester records with them. You can ask the developer to delete your data sooner.
Budget: each token has a small spending limit ($1 by default). When it is reached, Pharos shows a one-time notice and makes no calls to the Worker for 24 hours; it keeps protecting you with the checks that run on your computer (and your own Cloudflare key, if you set one up).
3. What Pharos stores on your computer
All in the browser's extension storage (chrome.storage), on this computer and this browser profile only. Nothing is synced to your Google account.
| Data | Where | How long |
|---|---|---|
| Settings: Cloudflare account ID and API token, arbiter provider, model and API keys, PhishTank key, thresholds, developer-mode and telemetry choices | chrome.storage.local | Until you change them, Reset Pharos, or uninstall |
| Verdict cache by page fingerprint (origin + text hash → verdict) | chrome.storage.session | Until the browser closes |
| Verdict cache by screenshot fingerprint (perceptual hash + URL → verdict) | chrome.storage.local | 24 hours, at most 2000 entries |
| Per-tab state (current verdict, pending scans, held downloads, protection status) | chrome.storage.session | Until the tab or browser closes |
| Blocklist index (blocked URL → which list) | chrome.storage.local | Replaced at every refresh |
| Scan log ("dev log"): page URLs, titles, verdicts, small screenshots, raw Clef answers, arbiter explanations, errors | chrome.storage.local | Only while developer mode is on; last 1000 entries |
| "Pharos got this wrong" reports: URL, title and the verdict shown | Scan log | Kept even with developer mode off, because you created them on purpose; same 1000-entry limit |
| Telemetry (only if you opt in): counts per day of verdicts by category, latency histograms per tier, error counts by type, panic-button counts, report counts | chrome.storage.local | 90 days, or until you erase it |
| Onboarding progress | chrome.storage.local | Until Reset Pharos or uninstall |
| Alpha tester settings (if used): backend mode, tester token, Worker address, a pending-upload queue of telemetry events, and the end of a quota pause | chrome.storage.local | Until you change them, Reset Pharos, or uninstall. The token is never written to the log (only its last 4 characters) |
API keys are never written to the scan log, telemetry, error messages or any exported file: every stored key is scrubbed from log entries before they are saved and again when the log is exported, and telemetry is rebuilt from fixed lists of allowed fields at export time.
4. What Pharos never sends
- Full page HTML, or the page's text (see section 1: it is only fingerprinted locally).
- Form field values: nothing you type (passwords, card numbers, messages) is read, let alone sent.
- Cookies, local storage or session tokens of any website.
- Browsing history: Pharos does not read your history, and never sends a list of the sites you visited. Each check concerns one page.
- Your identity: no account, name, email address, IP-based profile or device identifier is created or sent by Pharos. (The checkers you connect see requests from your browser under your API key, as with any API.) In alpha tester mode, requests carry your tester token, which the developer can match to the name they invited (section 2a).
- Telemetry: never sent automatically in Direct mode. In alpha tester mode it is uploaded to the alpha Worker while you are opted in (sections 2a and 5).
5. Telemetry
- Off by default. Turned on only by ticking "Help improve Pharos" under Settings → Privacy.
- When on, Pharos keeps counts only, on your computer. The categories are fixed lists in the code (
extension/lib/telemetry.js); anything unexpected is counted as "other". No URLs, titles, page content, screenshots, error messages or keys. - In Direct mode, nothing is uploaded. "Export telemetry" saves a JSON file to your Downloads folder. It reaches the Pharos team only if you choose to email or message it yourself.
- In alpha tester mode the counts (and your "got this wrong" reports, with their URLs) are also uploaded to the alpha Worker while the box is ticked; see section 2a.
- "Erase all telemetry" deletes the counts at any time. Turning telemetry off stops counting.
6. Your rights and controls
- Inspect: Settings → Debug → Scan log shows every logged event, with the screenshot and the raw response behind it.
- Export: the scan log (Settings → Debug → Export log) and telemetry (Settings → Privacy → Export telemetry) export as JSON files. Review the log before sharing it: it contains URLs and screenshots.
- Erase: Clear log; Erase all telemetry; or Reset Pharos (Settings → Privacy), which after a confirmation deletes everything in
chrome.storage.localandchrome.storage.session(settings, keys, caches, log, telemetry, onboarding progress) and restarts setup. - Limit what is sent: set the AI double-check to Off, or raise its threshold, so fewer or no pages reach a second provider. Leaving the Cloudflare credentials empty stops all screenshots (Pharos then checks URLs only).
- Uninstall: removing the extension deletes all of its storage.
7. Children
Pharos is not directed at children and collects no personal information about anyone.
8. Changes
This is a draft for an alpha. Material changes will be noted in the repository's commit history and announced to testers before they ship.
9. Open items for legal review
- Whether the screenshot and URL sent to third-party AI providers, under the user's own account, make Pharos a "processor" in any jurisdiction, and the disclosures the Chrome Web Store's Limited Use policy requires for that.
- Provider data-retention terms (Cloudflare Workers AI, OpenAI, Anthropic, Google, xAI) to summarise for users.
- Whether a screenshot of an arbitrary page counts as "personal and sensitive user data" under the Chrome Web Store User Data Policy (it can show email, bank or health content), and the prominent-disclosure / consent flow that would require before the first screenshot is taken.
- Contact details and a data-request process for a public release.
- Alpha backend (section 2a): the developer acts as the controller of the data in D1 and as the account holder sending tester screenshots to providers; whether testers' consent at setup is sufficient, and whether the invite email should carry this notice too.