fix: correct data_collection_permissions format, bump 0.9.8
Silent Send
A browser extension (Chrome, Firefox, and Safari) that intercepts personal information and substitutes it with user-defined replacements before sending to AI services.
Supported services
| Service | Domains | Status |
|---|---|---|
| Claude | claude.ai, claude.ai/code | Tested |
| ChatGPT | chatgpt.com, chat.openai.com | Tested |
| Copilot | copilot.microsoft.com | Untested |
| Grok | grok.x.ai, x.com/i/grok | Untested |
| Gemini | gemini.google.com | Untested |
| OpenWebUI | localhost, 127.0.0.1, or custom domain | Untested |
Browsers: Chrome, Edge, Brave, Firefox, and Safari. Edge and Brave use the Chrome extension directly.
Desktop apps (Claude, ChatGPT, Copilot) bypass the browser — use the web version with the extension for PPI protection.
Note: Claude and ChatGPT are tested. Other services have interception patterns defined but may need adjustments. PRs welcome.
How it works
- You fill in your Identity — name, email, username, computer name, phone
- Smart patterns auto-catch variations —
jsmith@macbook-pro,John's,/home/jsmith,555.123.4567 - Auto-redacts credentials — API keys, tokens, passwords, SSNs, credit cards (zero config)
- You type normally — you see your real text while composing
- On send, it swaps — the extension intercepts the API request and replaces real values with substitutes
- Badge shows count — the extension icon shows how many substitutions were made
- Reveal mode — translates AI responses back to your real data, right in the chat window
Smart pattern examples
| You type | What gets sent |
|---|---|
jsmith@macbook-pro |
ademo@mycomputer |
anyone@gmail.com |
anon@example.com (catch-all) |
John Smith |
Alex Demo |
Smith, John |
Demo, Alex |
John's code |
Alex's code |
/home/jsmith/project |
/home/ademo/project |
~jsmith |
~ademo |
C:\Users\jsmith |
C:\Users\ademo |
(555) 123-4567 |
(555) 000-0000 |
555.123.4567 |
(555) 000-0000 |
macbook-pro |
mycomputer |
JohnSmith |
AlexDemo |
johnsmith |
alexdemo |
john.smith |
alex.demo |
john_smith |
alex_demo |
smith-john |
demo-alex |
Auto-redact (automatic, no configuration needed)
| You type | What gets sent |
|---|---|
sk-proj-abc123xyz789... |
[REDACTED-OPENAI-KEY] |
sk-ant-api01-xyz... |
[REDACTED-ANTHROPIC-KEY] |
ghp_xxxxxxxxxxxxxxxxxxxx |
[REDACTED-GITHUB-TOKEN] |
AKIAIOSFODNN7EXAMPLE |
[REDACTED-AWS-KEY] |
sk_live_abc123... |
[REDACTED-STRIPE-KEY] |
AIzaSyxxxxxxxxxxxxxxxxx |
[REDACTED-GOOGLE-KEY] |
glpat-xxxxxxxxxxxx |
[REDACTED-GITLAB-TOKEN] |
xoxb-xxx-xxx-xxx |
[REDACTED-SLACK-TOKEN] |
Bearer eyJhbGciOi... |
Bearer [REDACTED] |
password=MyS3cret! |
password=[REDACTED] |
api_key=abcdef123456... |
api_key=[REDACTED] |
postgres://user:pass@host |
postgres://REDACTED:REDACTED@host |
-----BEGIN RSA PRIVATE KEY----- |
[REDACTED-PRIVATE-KEY] |
123-45-6789 |
[REDACTED-SSN] |
4111 1111 1111 1111 |
[REDACTED-CARD] |
Proper noun detection (opt-in)
The auto-detect scanner can optionally flag capitalized phrases that might be names, company names, or project names you forgot to configure. Disabled by default because it can produce false positives on normal phrases like "Getting Started" or "Generate Design".
Enable it in the popup → Options tab → Detect proper nouns.
When enabled, phrases like "Acme Corp" or "Project Atlas" will be flagged as warnings so you can decide whether to add them as mappings. You can click "ignore" on any false positive to permanently dismiss it.
Bulk import (speed up setup)
Import your existing data from password managers and browser autofill to pre-populate identity and mappings:
| Source | What's imported |
|---|---|
| Chrome password CSV | Usernames, emails, domains, passwords (auto-redacted) |
| Firefox logins CSV | Usernames, emails, domains, passwords (auto-redacted) |
| Bitwarden CSV | Usernames, emails, domains, passwords (auto-redacted) |
| 1Password CSV | Usernames, emails, domains, passwords (auto-redacted) |
| Browser autofill CSV | Names, emails, phones, addresses |
| Plain CSV (2 columns) | Real → substitute pairs |
| Plain text (1 per line) | Auto-categorized values needing substitutes |
Passwords are imported as exact-match mappings (e.g. MyS3cret! → [REDACTED-PASSWORD-1]) so they get caught in any context — not just password=value patterns. Imported passwords are protected: they're shown as dots in the UI and require your vault encryption password to reveal. When at-rest encryption is enabled, imported passwords are AES-256 encrypted in storage like all other sensitive data.
Go to Options → Transfer Data → Import CSV / Password Export.
Document scanning
When you upload files to an AI service, Silent Send extracts and scans the text for PII before the file is sent:
| Format | How it works |
|---|---|
| Text extracted from content streams, PII substituted, uploaded as clean plaintext | |
| DOCX, XLSX, PPTX | XML text extracted from ZIP structure, PII substituted, uploaded as plaintext |
| ODT, ODS, ODP | OpenDocument XML text extracted, PII substituted |
| DOC, XLS | Legacy binary format — readable text runs extracted |
| RTF | Formatting stripped, text extracted |
| TXT, CSV, JSON, code files | Direct string substitution |
| Images (PNG, JPG, etc.) | Not scanned — no text to extract |
| Scanned PDFs (image-only) | Not scanned — no text layer |
For PDF/DOCX/XLSX uploads, a preview panel shows what PII was found before uploading. You can choose to substitute and upload, or upload the original. Text files are substituted silently. The original file on your disk is never modified — substitution only happens to the in-flight upload.
First-time setup
After installing the extension, it does nothing until you configure it. The icon will be gray to remind you.
- Click the Silent Send icon in your toolbar
- You'll see the Identity tab with a red "Setup required" banner
- Fill in your real info and fake substitutes:
- Names — add as many as needed (first, last, nicknames). Click "+ Add" for more rows.
- Emails — your real email → fake email. Set a catch-all for unknown addresses.
- Usernames — your system username → fake username
- Hostnames — your computer name → fake computer name
- Phones — your phone number → fake number
- Click Save Identity
- The icon turns black — you're now protected
You can create multiple profiles (Personal, Work, Spouse) using the dropdown at the top. Each can be toggled on/off independently.
Icon colors
| Icon color | Badge | Meaning |
|---|---|---|
| Gray | Not configured — does nothing until you set up your identity | |
| Black | Active and protecting | |
| Blue | Reveal mode on — showing your real data in AI responses | |
| Red | Manually disabled | |
| Any | LOCK (red) | Vault locked — encrypted data, needs password to unlock |
| Any | SYN (purple) | New settings synced from another device |
Reveal mode
When reveal mode is on (eye icon or Alt+Shift+R), the AI's responses are displayed with your real data instead of the fake substitutes. This is purely a local display change — the AI never received your real data. It only ever saw the fake names, emails, paths, etc.
This exists so you can easily copy paths, commands, and code from the AI's response and paste them directly into your terminal or editor without manually translating fake values back to real ones.
For example:
- AI responds:
Edit the file at /home/ademo/project/config.yaml - With reveal mode ON, you see:
Edit the file at /home/jsmith/project/config.yaml - Copy that path, paste into terminal — it works
Toggle it off and the display reverts to the fake data the AI actually received.
Keyboard shortcuts
| Shortcut | Action |
|---|---|
Alt+Shift+R |
Toggle reveal mode |
Alt+Shift+S |
Toggle Silent Send on/off |
Remap in Chrome: chrome://extensions/shortcuts | Firefox: about:addons → gear → Manage Extension Shortcuts
How to verify it's working
-
Test tab — click the extension icon → Test tab. Type text containing your real data and see the substituted version live, highlighted in green. This is the quickest way to confirm your identity is configured correctly.
-
Badge count — after sending a message, the extension icon shows a green number (e.g. "3") indicating how many substitutions were made. If you see a number, it's working.
-
Inspect the actual network request — this is the definitive proof that your real data never reaches the AI. The steps vary slightly by browser:
Firefox:
- Press F12 to open DevTools → click the Network tab
- Send a message in the AI chat that contains your real data
- In the network log, find the row with Method POST and File events (for Claude) or conversation (for ChatGPT)
- Click that row
- Click the Request tab in the right panel
- Expand the JSON: look inside
events → 0 → message → content - You should see your replaced data (e.g. "Ademo Demo"), not your real data (e.g. "John Smith")
Chrome / Chromium / Edge:
- Press F12 to open DevTools → click the Network tab
- Send a message in the AI chat that contains your real data
- In the network log, find the row with Method POST and Name chat or events or conversation
- Click that row
- Click the Payload tab in the right panel
- Expand the request body and look for the message content
- You should see your replaced data, not your real data
Safari:
- Safari → Settings → Advanced → check "Show features for web developers"
- Press Cmd+Option+I to open Web Inspector → click the Network tab
- Send a message in the AI chat that contains your real data
- Find the POST request in the network log
- Click it → click Request in the detail panel
- You should see your replaced data, not your real data
If your real data appears anywhere in the request body, the substitution isn't working — check that the extension is enabled and your identity is configured.
-
Activity tab — click the extension icon → Activity tab. Shows a timestamped log of every substitution with the original and replaced values.
-
Console log — DevTools (F12) → Console shows
[Silent Send] Substituted N value(s) in <url>for each intercepted request. -
Reveal mode — toggle with the eye icon or
Alt+Shift+R. When on, the AI's responses display your real data instead of the replaced values. When off, you see what the AI actually received. If toggling changes the text, substitution is working.
Installation
Prerequisites
Step 1: Get the code
Open a terminal (Terminal on Mac, Command Prompt or PowerShell on Windows, any terminal on Linux) and run:
git clone https://github.com/outis1one/silent-send.git
cd silent-send
This downloads the extension code to a silent-send folder on your computer.
Chrome
- Open
chrome://extensions/in Chrome (orbrave://extensions/in Brave) - Enable Developer mode (toggle in the top right corner)
- Click Load unpacked
- Navigate to the
silent-sendfolder you cloned and select it - Navigate to any supported AI site — the extension icon appears in your toolbar
That's it for Chrome. No build step, no account, no store, no fees.
Important: After reloading the extension (e.g. after a code update), you must refresh any open AI chat tabs (F5 or Ctrl+R). The old content script keeps running until the page is refreshed.
Firefox (signed, persistent)
Firefox requires extensions to be cryptographically signed before it will permanently install them. Mozilla provides free signing — no store listing, no review process, no fees. You just need a free Firefox account.
Step 1: Create a free Firefox account
- Go to https://accounts.firefox.com/ and sign up (or sign in if you have one already)
- This is the same account used for Firefox Sync — you may already have one
Step 2: Generate your signing keys
- Go to https://addons.mozilla.org/developers/addon/api/key/
- Sign in with your Firefox account
- You'll see two values on that page:
- JWT issuer — looks like
user:12345678:901 - JWT secret — a long string of random characters
- JWT issuer — looks like
- You need both of these. Copy them or keep the page open.
Step 3: Install dependencies and save your signing keys
In your terminal, inside the silent-send folder:
Mac / Linux:
npm install
cp .env.example .env
Windows (Command Prompt):
npm install
copy .env.example .env
Now open the .env file in any text editor (Notepad, VS Code, etc.) and replace the placeholder values with the two values from step 2:
WEB_EXT_API_KEY="user:12345678:901"
WEB_EXT_API_SECRET="your-jwt-secret-here"
Save and close the file.
Step 4: Build and sign
All platforms (Mac, Linux, Windows with Git Bash):
npm run sign:firefox
The sign script reads your .env file automatically — no need to source it. First-time signing can take 1-5 minutes while Mozilla validates and approves the extension. Subsequent signs are usually faster. When done, you'll find a signed .xpi file in dist/firefox-signed/.
Windows (Command Prompt — if not using Git Bash):
node -e "require('fs').readFileSync('.env','utf8').split('\n').forEach(l=>{const[k,v]=l.split('=');if(k&&v)process.env[k.trim()]=v.trim().replace(/^\"|\"$/g,'')})" && npm run sign:firefox
Windows (PowerShell):
Get-Content .env | ForEach-Object { if ($_ -match '^(.+?)=(.*)$') { [Environment]::SetEnvironmentVariable($matches[1], $matches[2].Trim('"')) } }
npm run sign:firefox
Step 5: Install
- Drag the
.xpifile into any Firefox window, or - Firefox menu → File → Open File → select the
.xpi - Click Add when prompted
Done. The extension is permanently installed — survives restarts, updates, everything. You only need to re-sign if you update to a newer version of Silent Send.
Firefox (temporary, no signing needed)
If you just want to try it out quickly:
Mac / Linux:
npm install && npm run run:firefox
Windows:
npm install && npm run run:firefox
This opens Firefox with the extension pre-loaded. Resets when Firefox closes — useful for testing.
Safari (macOS)
Safari extensions require an Xcode project wrapper. Apple provides a converter that does this automatically.
Prerequisites
- macOS with Xcode installed (free from Mac App Store)
- Xcode Command Line Tools:
xcode-select --install - For App Store distribution: Apple Developer account ($99/year)
Build the Safari extension
git clone https://github.com/outis1one/silent-send.git
cd silent-send
npm install
./build-safari.sh
This generates an Xcode project at safari-build/. Open it in Xcode:
open safari-build/Silent\ Send.xcodeproj
Test without an Apple Developer account
- Open the Xcode project
- Select Product → Run (Cmd+R) — this builds and launches Safari with the extension
- In Safari: Settings → Extensions → enable "Silent Send"
- If Safari says the extension is unsigned:
- Safari menu → Settings → Advanced → check "Show features for web developers"
- Safari menu → Develop → Allow Unsigned Extensions (you'll need to re-enable this every time Safari restarts)
Custom domains (OpenWebUI, etc.)
If you run OpenWebUI or another AI service on a custom domain (not localhost), go to Options → Custom Domains and add your domain (e.g. https://ai.myserver.com). The extension will activate on those domains too.
For Chrome, you'll need to also grant the extension permission to access the new domain via chrome://extensions/ → Silent Send → Details → Site access.
Architecture
manifest.json — Chrome extension manifest (Manifest V3)
manifest.firefox.json — Firefox variant (adds gecko ID for signing)
build.sh — Copies the right manifest to dist/{chrome,firefox}/
build-safari.sh — Converts to Safari extension via Xcode project
sign-firefox.sh — Signs Firefox extension via Mozilla API
src/
background/
service-worker.js — Badge management, auto-sync alarms, org policy polling
content/
injector.js — Content script (isolated world) — loads config, bridges messaging
content.js — Page script (main world) — hooks fetch(), does substitution, document scanning
content.css — Visual indicators (highlights, reveals, document scan preview)
popup/
popup.html/css/js — Quick access: identity, mappings, activity, test, options
options/
options.html/css/js — Full mapping management, import/export, settings, custom domains
lib/
substitution-engine.js — Core explicit find/replace logic
smart-patterns.js — Auto-detection of emails, names, usernames, hostnames, phones, paths
secret-scanner.js — Auto-redact API keys, tokens, passwords, SSNs, credit cards
crypto.js — AES-256-GCM encryption, PBKDF2 key derivation, TOTP (RFC 6238), WebAuthn, key caching
sync.js — Cross-browser sync with encryption (browser sync, Gist, folder, URL, sync codes)
storage.js — Browser storage wrapper with transparent at-rest encryption
auto-detect.js — PII pattern detection (IPs, addresses, paths, proper nouns)
document-scanner.js — PDF/DOCX/XLSX/ODT/RTF text extraction and scanning
import-parser.js — Bulk import from CSV, password managers, autofill exports
version-history.js — Sync version snapshots + rollback
merge.js — Three-way field-level merge for sync conflicts
org-policy.js — Organization policy management (shared rules, compliance)
tamper-guard.js — Admin password protection for destructive actions
browser-polyfill.js — Chrome/Firefox API compatibility
Sync features
Keep your identities, mappings, and settings in sync across browsers and devices.
Sync methods
| Method | How it works | Chrome | Firefox | Brave | Safari |
|---|---|---|---|---|---|
| Sync Code | Generate a code, paste in another browser | Yes | Yes | Yes | Yes |
| GitHub Gist | Store settings in a private Gist (needs a free GitHub PAT) | Yes | Yes | Yes | Yes |
| Custom URL | Any endpoint supporting GET + PUT (WebDAV, cloud function, etc.) | Yes | Yes | Yes | Yes |
| Browser account sync | Automatic via your Chrome/Firefox account | Yes | Yes | No | No |
| Auto-Sync Folder | Pick a cloud-synced folder (Dropbox, OneDrive, etc.) | Yes | No | No | No |
Auto-Sync Folder uses the File System Access API which is only available in Chrome. All other methods work in every browser.
Auto sync
When configured, the extension automatically pushes and pulls settings on a configurable interval (5/15/30/60 minutes) using GitHub Gist or a custom URL endpoint. Local changes trigger an immediate push.
Conflict resolution
When both this device and another device change the same data between syncs, the extension performs a three-way merge:
- Non-conflicting changes are merged automatically
- True conflicts (same field changed on both sides) are presented in a side-by-side UI where you choose "Keep Local" or "Keep Remote" for each conflict
Version history + rollback
Every sync operation saves a snapshot of your data. You can browse previous versions and restore any snapshot. Configurable max snapshots (default 10).
Connected devices
Each device registers itself with a name and browser type. The device list is shared via sync data so you can see all connected devices, when they last synced, and remove old ones.
Organization / Team
For teams that want to enforce privacy rules across all members:
- Admin creates a JSON policy file hosted at any URL (static file, S3, cloud function)
- Team members join by entering the policy URL or an invite code in Options → Organization
- Org rules merge with personal rules — required mappings are always active and cannot be disabled
- Compliance dashboard shows which required fields are configured (without revealing actual PII)
- Policy updates are polled automatically (hourly)
Org policy format
{
"orgId": "acme-corp",
"orgName": "Acme Corp",
"version": 2,
"requiredMappings": [
{ "real": "acme-internal.com", "substitute": "example-corp.com", "category": "domain" }
],
"requiredSecretPatterns": [
{ "name": "Acme Token", "regex": "acme_[a-z0-9]{32}", "redact": "[REDACTED-ACME-TOKEN]" }
],
"sharedIdentityRules": {
"requireCatchAllEmail": true,
"requiredCategories": ["name", "email", "domain"]
}
}
Tamper protection
Optional admin password (separate from vault password) that gates destructive actions:
- Disabling the extension
- Clearing data or mappings
- Leaving an organization
- Exporting data in plaintext
This is a deterrent for casual tampering. It cannot prevent browser-level uninstall or developer tools access.
Privacy & Security
- All data stays local in browser storage — no external servers, no telemetry, no analytics
- The extension only activates on supported AI sites (and any custom domains you add)
- Your real identity data never leaves your machine
At-rest encryption
When you enable sync encryption (Options → Sync Between Browsers → Sync Encryption), all sensitive data is AES-256-GCM encrypted before being written to browser storage:
| What's encrypted | Contains |
|---|---|
| Identity profiles | Real names, emails, usernames, hostnames, phones + substitutes |
| Mappings | All real → substitute pairs |
| Activity log | History of what was substituted |
| Settings | Custom domains, configuration preferences |
| TOTP secret | Authenticator app shared secret |
| All sync data | Everything sent to Gist, sync folders, custom URLs, browser sync |
Only two things remain plaintext — the encryption salt (needed to derive the key) and a verification blob (needed to check the password). Neither contains PII.
Without at-rest encryption, data is stored in plaintext in the browser's local storage (similar to cookies and localStorage). Anyone with file system access to your browser profile directory could read it.
Vault unlock
After a browser restart, the extension is in a locked state:
- Badge shows LOCK in red — substitutions are paused
- Click the extension icon to see the unlock prompt
- Enter your password (first time per device), or use biometric/TOTP for re-verification
- Protection resumes immediately across all open tabs
This is similar to how password managers work — your vault is locked until you authenticate.
Authentication options
| Method | When it's used |
|---|---|
| Password | Required once per device to derive the encryption key. The key is then cached indefinitely in IndexedDB. |
| TOTP | Optional second factor alongside password. Can also be used alone for re-verification after the key is cached. |
| WebAuthn (biometric/PIN) | Primary re-verification method after first setup. Uses fingerprint, Face ID, or Windows Hello. |
Re-verification (biometric, TOTP, or password) is only triggered when the configurable TTL expires (default: 90 days) and new sync data exists. If nothing changed, you're never prompted.
Cross-device sync encryption
All sync channels (browser sync, GitHub Gist, folder sync, custom URL, sync codes) encrypt data before sending. A new device bootstraps itself from the encrypted sync payload:
- Pull encrypted data from any sync channel
- Enter the same password used on the original device (once)
- Full configuration (including TOTP secret) is restored from the encrypted payload
- WebAuthn credential is registered locally for future re-verification
Managed browser deployments
For organizations that want to prevent extension removal:
- Chrome / Chromium / Edge: Use the
ExtensionInstallForcelistgroup policy. See Chrome Enterprise policies. - Firefox: Use the
ExtensionSettingspolicy inpolicies.jsonor via Group Policy. See Firefox Enterprise policies.
These are standard browser management features — Silent Send does not attempt to prevent its own removal.
Smart reveal
Reveal mode only replaces values that were actually substituted in outbound messages during the current session. If the AI uses a word that happens to match one of your substitute values (e.g., the AI says "the user should..." and "user" is a configured substitute), it won't be falsely revealed as your real username.
What Silent Send can't catch
Silent Send works well for text you type and most document uploads, but some things will get through:
- Images and screenshots — can't scan pixels. A screenshot of your terminal with your username in it goes through unchanged.
- Scanned PDFs — if the PDF is just an image with no text layer, there's nothing to substitute.
- Base64 and encoded data — data embedded in encoded formats isn't detected.
- Names inside other words — if your name is "Art", it won't catch "article" (word boundaries prevent most false positives, but edge cases exist).
- Data you haven't configured — it can only substitute what you told it about, plus known secret formats. Your home address or employer name won't be caught unless you add them.
- Short names — names under 3 characters are skipped for usernames/hostnames to avoid false positives.
- Custom secret formats — the auto-redactor knows common API key prefixes (sk-, ghp_, AKIA, etc.) but won't catch proprietary token formats your company uses.
Think of it like a spell checker for privacy — it catches most things, but you should still glance at sensitive messages before sending.
Disclaimer
Silent Send is provided "as is" and "as available" without warranty of any kind, express or implied. It is a convenience tool that reduces — but cannot eliminate — the risk of accidentally sharing personal information with AI services. It is not a security guarantee and should not be your only privacy protection.
What this means in practice:
- Silent Send may fail to detect or substitute personal information in certain formats, edge cases, images, or data you haven't configured.
- Third-party websites (ChatGPT, Claude, Gemini, Reddit, GitHub, etc.) may change their interfaces, APIs, or data submission methods at any time. Such changes can cause Silent Send to stop intercepting data without any visible error or warning. The Silent Send contributors have no control over and accept no responsibility for third-party changes.
- You are solely responsible for verifying that your personal data has been properly substituted before sending. The Test tab in the popup is provided for this purpose.
- Silent Send is not a substitute for professional data protection, legal compliance, or security tooling. It does not guarantee compliance with any regulation (GDPR, HIPAA, CCPA, PCI-DSS, or otherwise).
- No contributor, maintainer, or distributor of Silent Send shall be liable for any damages arising from its use, including but not limited to privacy breaches, identity theft, data exposure, or regulatory penalties — whether caused by software bugs, third-party changes, misconfiguration, or any other reason.
The source code is available for inspection — you don't have to take our word for it.
License
MIT License — free to use, modify, and distribute. See the LICENSE file for the full disclaimer of warranty and limitation of liability.
Contributions welcome. If you find a bug, especially a privacy-related one, please open an issue.
Support
Silent Send is a weekend project — built because the developer wanted it and could not find what the developer wanted (reveal especially). No donations needed. If you find it useful, great — enjoy. If it helps you keep your personally identifiable information private, that's thanks enough. More people having access to privacy is the goal.
That said, Claude access isn't free. If you have a desire to give a coffee back, it would be appreciated — but don't feel any obligation to tip.
A few things to know:
- Donations do not influence updates. Silent Send may or may not get updates based on the developer's usage and available time.
- Donating does not create any warranty, support obligation, or expectation of future development.
- This is and always will be a free, non-commercial project.