Trust
Threat model, every browser permission, what extension sync can see, how to verify builds, audit status, and how to report a vulnerability.
Last updated: August 22, 2026
Personal Shield is a tracker and known-bad-host blocker with signed list updates. It is not a VPN, antivirus product, or anti-fingerprinting browser.
Advertising and analytics trackers
Blocks requests to known ad and tracker hosts from lists such as EasyList and EasyPrivacy, plus a small baseline shipped in the extension before the first account sync.
Known malware and phishing hosts
Applies malware-category lists (for example URLhaus-based filters) when those lists are enabled. This is domain/URL blocking, not antivirus scanning of files.
Cosmetic ad and annoyance elements
When annoyance/cosmetic lists are on, hides matching page elements. Selectors are constrained in the content script; allowlisted sites skip cosmetics.
Tampered remote rule updates
Account rule payloads are signed with ECDSA P-256 (ES256). Production builds pin the public key, reject unsigned or replayed sets, and can roll back to the last verified snapshot on the device.
DNS-level ads and trackers on phones
Personal Shield setup uses privacy DNS (DoH/DoT profiles). That path is separate from the browser extension and does not see page contents.
Malware already on the device
The extension cannot detect or remove malicious software, browser exploits, or a compromised OS. Use OS updates and a dedicated antivirus product for that.
Phishing and social engineering
A lookalike login page on a domain that is not on a blocklist still works. PrivyDeck does not replace a password manager, passkeys, or common-sense URL checks.
Complete browser fingerprinting
Blocking third-party trackers reduces some signals. It does not randomize canvas, WebGL, fonts, or other fingerprint surfaces the way a dedicated anti-fingerprinting browser does.
IP or location hiding
Personal Shield is not a VPN. Sites and networks still see your IP. Encrypted DNS hides some DNS lookups from the local network, not your destination IP.
First-party tracking on the site you opened
A site can still count you with its own cookies, login, and first-party scripts. Blocking is strongest against third-party ad and analytics hosts.
Unknown or brand-new trackers
Protection follows published filter lists and your allow/deny choices. Zero-days and unlisted hosts are not blocked until a list or you add them.
Install-time permissions match what blocking actually needs. There are no tabs, history, or downloads permissions. Optional permissions are not used yet; host access for websites is required because that is where blocking happens. Firefox adds webRequest and dns so domain lists and CNAME uncloaking work under Firefox’s smaller dynamic-rule cap.
| Permission | Where | Required | Why |
|---|---|---|---|
| declarativeNetRequest | Chrome, Edge, Brave, Opera, Firefox | Yes | Installs block and allow rules so ads, trackers, and malware hosts never load. This is the core blocking engine on Chromium. |
| declarativeNetRequestFeedback | Chromium-based | Yes | Reads matched-rule counts so the toolbar badge and dashboard can show how many requests were blocked. It does not grant page content access. We keep it required so install-time stats work; a future release may request it only when you enable counts. |
| storage | All | Yes | Stores the account token hash locally, last-known-good rules, allowlist, engine settings, and an on-device policy log. Nothing in this store is your full browsing history. |
| alarms | All | Yes | Wakes the service worker on a timer to refresh signed rules and check the rules version. No extra hosts are contacted beyond your PrivyDeck hub. |
| Host access to https://*/* (and http://*/* in the content script) | All | Yes | Blocking and cosmetic hiding have to apply on the websites you visit. Without this, declarativeNetRequest cannot cancel third-party requests on those sites. The connect-bridge script is limited to privydeck.com; cosmetics run elsewhere and skip allowlisted hosts. |
| Host access to privydeck.com (and wss://ws.privydeck.com) | All | Yes | Fetches signed protection config, reports aggregate block counts, and receives live rule-refresh notices. Production builds pin these hub origins. |
| webRequest + webRequestBlocking | Firefox only | Yes | Firefox caps dynamic declarativeNetRequest rules at 5,000. Domain blocks therefore also run through blocking webRequest so Firefox can apply the full account list. |
| dns | Firefox only | Yes | Resolves canonical names so a tracker hiding behind a CNAME alias can still be blocked. This stays on-device; resolved names are not uploaded. |
Source of truth: extension/manifest.json plus the Firefox extras added in scripts/build-extension.mjs.
Not end-to-end encrypted. Rule sync is authenticated and signed, not end-to-end encrypted. PrivyDeck compiles filter lists on the server and signs the payload. The extension verifies that signature with a pinned public key. The server necessarily sees the rule set it generated. This is different from the vault, which is encrypted in the browser before upload.
A P-256 private key on the server creates ES256 signatures (kid v1). Production extension packages embed the matching public key. Unsigned payloads are rejected in production. The connect token is a high-entropy secret shown once, stored hashed on the server, and kept in the extension’s local storage — it is not a vault key.
Account access uses passkeys plus optional one-time recovery codes (hashed at rest). Losing every passkey and every recovery code locks you out of the account. The vault passphrase is separate: if you lose it, vault files cannot be recovered. There is no key escrow.
Settings → Delete account (type DELETE, passkey step-up when you have a passkey). This cancels active Stripe subscriptions and permanently removes account rows, vault ciphertext, DSAR letters, devices, extension tokens, recovery codes, and household memberships you own.
Production zips are store-only (uncompressed) with sorted names and zeroed DOS timestamps so two builds of the same commit should hash the same. Tagged releases attach SHA-256 checksums and GitHub Artifact Attestations (SLSA provenance).
extension-v1.4.2).npm run extension:build with the same rule-signing public key used in that release (baked into config.js).SHA256SUMS.txt on the release. npm run extension:verify rebuilds twice and checks the hashes match each other.gh attestation verify dist/privy-deck-extension-chromium-VERSION.zip --owner N0L0g1cChrome Web Store and Firefox Add-ons wrap the package again. Store listings will not match the GitHub zip byte-for-byte. Use the GitHub artifacts to verify source, then install from the official store for auto-updates.
No independent security audit has been published yet. When one exists, the full report will be linked here — not only a pass/fail badge.
Intended scope for that review:
Before the first account sync, Chromium uses a packed baseline (top trackers plus optional ads/trackers/malware/annoyance rulesets). After connect, account-compiled lists replace that baseline.
Manifest V3 declarativeNetRequest has a dynamic rule budget (about 30k on Chromium, 5k on Firefox). PrivyDeck compiles a safe subset of ABP/uBO syntax; some path/regex filters that uBO can run will not apply. Published lab numbers will state the browser, list snapshot date, and that limitation.
What we will publish
Comparison method
Comparative lab numbers are not published yet. Filter-compiler smoke tests run in CI so syntax regressions are caught before a release.
Email security@privydeck.com. Use a descriptive subject. Include product area (extension, vault, API, hub), impact, and steps that stay within your own account. Do not attach stolen data from other users.
Please do not file public GitHub issues for unpatched vulnerabilities. Product support that is not a security bug still goes to support@privydeck.com. Full process: SECURITY.md.