From 511ee321a7363fdabaa89e295fa34abf79080b29 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 27 Mar 2026 03:52:23 +0000 Subject: [PATCH 1/5] fix: disable proper noun detection by default (too many false positives) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Proper noun detection (flagging capitalized phrases like "Getting Started", "Generate Design", "Introduction Getting Started") now disabled by default. Enable via popup → Options tab → Detect proper nouns. The pattern-based detection (IPs, emails, API keys, addresses, paths, etc.) remains always-on and reliable. The capitalized phrase heuristic was producing too many false positives on normal UI phrases, headings, and instructions — adding words to the filter was a losing game. Added detectProperNouns toggle to popup Options tab. Updated README to note it's opt-in. https://claude.ai/code/session_01SWSwDfMVij53bCTNSCLMwn --- README.md | 12 ++++-------- src/content/content.js | 8 +++++--- src/lib/auto-detect.js | 9 ++++++--- src/popup/popup.html | 8 ++++++++ src/popup/popup.js | 2 ++ 5 files changed, 25 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index c87deb2..9628412 100644 --- a/README.md +++ b/README.md @@ -67,17 +67,13 @@ A browser extension (Chrome, Firefox, and Safari) that intercepts personal infor | `123-45-6789` | `[REDACTED-SSN]` | | `4111 1111 1111 1111` | `[REDACTED-CARD]` | -### Proper noun detection (automatic) +### Proper noun detection (opt-in) -The auto-detect scanner also catches capitalized words mid-sentence that might be names, company names, or project names you forgot to configure. For example: +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". -| You type | What happens | -|----------|-------------| -| `...talked to Sarah about the deploy` | Flags "Sarah" as a possible name | -| `...the Acme Corp internal API` | Flags "Acme Corp" as a possible organization | -| `...pushed to Project Atlas staging` | Flags "Project Atlas" as a possible project name | +Enable it in the popup → Options tab → **Detect proper nouns**. -These are flagged as warnings (not auto-redacted) so you can decide whether to add them as mappings. Common English words, programming terms, days, and months are excluded to reduce false positives. +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) diff --git a/src/content/content.js b/src/content/content.js index 47fd4e5..b0020fe 100644 --- a/src/content/content.js +++ b/src/content/content.js @@ -604,9 +604,11 @@ } // Proper noun heuristic — catch names, company names, project names - // that aren't configured in identity - const properNouns = detectProperNouns(text, configured); - findings.push(...properNouns); + // Disabled by default (too many false positives). Enable in Options. + if (settings.detectProperNouns) { + const properNouns = detectProperNouns(text, configured); + findings.push(...properNouns); + } // Deduplicate by value const seen = new Set(); diff --git a/src/lib/auto-detect.js b/src/lib/auto-detect.js index bea7464..e44ac75 100644 --- a/src/lib/auto-detect.js +++ b/src/lib/auto-detect.js @@ -136,7 +136,7 @@ const AutoDetect = { * * Returns array of { name, value, hint, category, index } */ - scan(text, identity) { + scan(text, identity, options) { if (!text || text.length < 5) return []; const hasContext = CONTEXT_WORDS.test(text); @@ -194,8 +194,11 @@ const AutoDetect = { } // Proper noun heuristic — catch names, company names, project names - const properNouns = this._detectProperNouns(text, configured); - findings.push(...properNouns); + // Disabled by default (too many false positives). Pass detectProperNouns: true to enable. + if (options?.detectProperNouns) { + const properNouns = this._detectProperNouns(text, configured); + findings.push(...properNouns); + } // Deduplicate overlapping matches findings.sort((a, b) => (a.index || 0) - (b.index || 0)); diff --git a/src/popup/popup.html b/src/popup/popup.html index 38c8635..8785a7c 100644 --- a/src/popup/popup.html +++ b/src/popup/popup.html @@ -236,6 +236,14 @@ +
+
+ Detect proper nouns + Flag capitalized phrases (names, companies) — may produce false positives +
+ +
+

Sync, encryption, org, version history, import/export, and more

diff --git a/src/popup/popup.js b/src/popup/popup.js index 2f9e75d..3743790 100644 --- a/src/popup/popup.js +++ b/src/popup/popup.js @@ -225,6 +225,7 @@ async function initUnlockedUI() { $('#optAutoRedact').checked = settings.autoRedactDetected !== false; $('#optHighlights').checked = settings.showHighlights || false; $('#optDocPreview').checked = settings.docScanPreview !== false; + $('#optProperNouns').checked = settings.detectProperNouns || false; // Options tab change handlers const optHandlers = [ @@ -233,6 +234,7 @@ async function initUnlockedUI() { ['optAutoRedact', 'autoRedactDetected'], ['optHighlights', 'showHighlights'], ['optDocPreview', 'docScanPreview'], + ['optProperNouns', 'detectProperNouns'], ]; for (const [id, key] of optHandlers) { $(`#${id}`).addEventListener('change', async (e) => { From 0870c050cb17384e256013058a67f13cd7d27bed Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 27 Mar 2026 03:57:53 +0000 Subject: [PATCH 2/5] fix: sync code not transferring identity when encryption enabled _getAllData() was reading raw storage which contains encrypted blobs when at-rest encryption is enabled. The sync code export would send { _ssLocalEncrypted: true, data: } instead of actual identity data. The importing browser couldn't use these blobs. Fixed _getAllData() to use Storage._readSecure() which decrypts transparently. Fixed _applyData() to use Storage._writeSecure() so imported data gets encrypted on the receiving end. Also: hide the Auto-Sync Folder section entirely in browsers that don't support File System Access API (Firefox, Brave, Safari) instead of showing a broken-looking error message. https://claude.ai/code/session_01SWSwDfMVij53bCTNSCLMwn --- src/lib/sync.js | 36 ++++++++++++++++++++++++++---------- src/options/options.html | 2 +- src/options/options.js | 7 +++++++ 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/lib/sync.js b/src/lib/sync.js index 80c743a..b6a6b4e 100644 --- a/src/lib/sync.js +++ b/src/lib/sync.js @@ -791,25 +791,41 @@ const SilentSendSync = { // ---------------------------------------------------------------- async _getAllData() { - const result = await api.storage.local.get(null); + // Use dynamic import to avoid circular dependency + const StorageModule = (await import('./storage.js')).default; + const identity = await StorageModule._readSecure('ss_identity'); + const mappings = await StorageModule._readSecure('ss_mappings'); + const settings = await StorageModule._readSecure('ss_settings'); + const result = await api.storage.local.get('ss_lastModified'); return { version: '1', lastModified: result.ss_lastModified || Date.now(), - identity: result.ss_identity || {}, - mappings: result.ss_mappings || [], - settings: result.ss_settings || {}, + identity: identity || {}, + mappings: mappings || [], + settings: settings || {}, }; }, async _applyData(data, source = 'unknown') { - const toSet = { + const StorageModule = (await import('./storage.js')).default; + + // Write through Storage module so data gets encrypted if at-rest + // encryption is enabled + if (data.identity !== undefined) { + await StorageModule._writeSecure('ss_identity', data.identity); + } + if (data.mappings !== undefined) { + await StorageModule._writeSecure('ss_mappings', data.mappings); + } + if (data.settings !== undefined) { + await StorageModule._writeSecure('ss_settings', data.settings); + } + + // Metadata stays plaintext + await api.storage.local.set({ ss_lastModified: data.lastModified, ss_sync_notification: { source, time: Date.now() }, - }; - if (data.identity !== undefined) toSet.ss_identity = data.identity; - if (data.mappings !== undefined) toSet.ss_mappings = data.mappings; - if (data.settings !== undefined) toSet.ss_settings = data.settings; - await api.storage.local.set(toSet); + }); }, async _getSyncChunkKeys() { diff --git a/src/options/options.html b/src/options/options.html index ea8ce0a..4c4f82e 100644 --- a/src/options/options.html +++ b/src/options/options.html @@ -238,7 +238,7 @@
-
+

Auto-Sync Folder — fully automatic, no copy-paste

Pick the same folder in each browser once. Changes are written to diff --git a/src/options/options.js b/src/options/options.js index fbf0b11..ee75ddb 100644 --- a/src/options/options.js +++ b/src/options/options.js @@ -721,6 +721,13 @@ let syncDirHandle = null; const SYNC_FILE_NAME = 'silent-send-sync.json'; async function initFileSync() { + // Hide the entire section if File System Access API isn't supported + if (!window.showDirectoryPicker) { + const section = $('#fileSyncSection'); + if (section) section.style.display = 'none'; + return; + } + syncDirHandle = await SilentSendSync.loadSyncDirHandle(); updateFileSyncUI(); if (syncDirHandle) { From b7a5bcc2876e3a33999141afecf21863146e0bb8 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 27 Mar 2026 03:58:43 +0000 Subject: [PATCH 3/5] docs: add sync method compatibility table to README Shows which sync methods work in which browsers: - Sync Code, GitHub Gist, Custom URL: all browsers - Browser account sync: Chrome and Firefox only - Auto-Sync Folder: Chrome only (File System Access API) https://claude.ai/code/session_01SWSwDfMVij53bCTNSCLMwn --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 9628412..54702b8 100644 --- a/README.md +++ b/README.md @@ -398,6 +398,20 @@ src/ ## 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. From 8cff1ae3828ea291d975cba7ee3bde574bc91173 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 27 Mar 2026 04:01:25 +0000 Subject: [PATCH 4/5] fix: auto-sync token persistence + better status display Auto-sync now: - Persists Gist token in the auto-sync config so it survives page reloads (previously only read from the input field) - Saves token when the Gist token field changes (not just on toggle) - Validates that credentials exist before enabling - Shows current status: method, interval, last push/pull times - Updated UI description to clarify it works in all browsers https://claude.ai/code/session_01SWSwDfMVij53bCTNSCLMwn --- src/options/options.html | 6 +++-- src/options/options.js | 55 +++++++++++++++++++++++++++++++--------- 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/options/options.html b/src/options/options.html index 4c4f82e..05f5d7a 100644 --- a/src/options/options.html +++ b/src/options/options.html @@ -278,9 +278,11 @@

-

Auto Sync — background polling

+

Auto Sync — works in all browsers

- Automatically push and pull settings on an interval. Uses the Gist or URL method configured above. + Automatically push and pull settings in the background on a schedule. + Uses GitHub Gist or Custom URL — configure one of those above first, then enable auto sync here. + Changes you make locally are pushed immediately; remote changes are pulled on the interval.