Going back to a known-good baseline. This version had:
- Working reveal mode with CSS Highlight API
- Working substitution (fetch + XHR hooks)
- Smart patterns (names, emails, phones, usernames)
- Encryption/sync (password, TOTP, WebAuthn)
- Multiple identity profiles
- Activity log
- Secret scanner
- Auto-detect PII warnings
- Pre-send PII detection
Kept current manifests (UUID, data_collection_permissions, version).
No renames applied — uses original naming (secretScanning, PPI, etc).
Will re-apply renames and new features from this working base.
https://claude.ai/code/session_01KF4i7Ra7zCEDskxDBaNtcT
The data-ss-config attribute on the script tag was being removed
(via script.onload) before content.js could read it. Changed approach:
inject config as a separate <script type="application/json" id="ss-config-data">
element that persists in the DOM until content.js reads and removes it.
This eliminates the race condition between script execution and onload
removal. Bump 0.9.20.
https://claude.ai/code/session_01KF4i7Ra7zCEDskxDBaNtcT
Restored injector.js from v2.0.14 (commit 9a11896) which:
- Requests decrypted config from background via get:decrypted-config
message instead of passing empty arrays when data is encrypted
- Handles the identity.profiles merge correctly for background responses
- Passes ss_settings directly (not checking _ssLocalEncrypted which
caused settings loss)
Added missing get:decrypted-config message handler to service-worker.js
which returns decrypted mappings, identity, and settings via Storage
module.
https://claude.ai/code/session_01KF4i7Ra7zCEDskxDBaNtcT
Reverted content.js to commit 9a11896 (the last version where reveal
mode worked) and re-applied only the renames:
- PPI → PII
- secretScanning → autoRedact
- SECRET_PATTERNS → REDACT_PATTERNS
- scanAndRedactSecrets → runAutoRedact
- category: 'secret' → category: 'redact'
- Added customRedactPatterns support to runAutoRedact
This restores:
- Individual word storage in sessionSubstitutions (needed for reveal)
- fetch(Request) handling (not just fetch(url, options))
- Blob/ArrayBuffer/URLSearchParams body conversion
- isInNonChatArea scoping (narrowed version)
- Proper noun detection gated by settings.detectProperNouns
- Mapping values added to configured skip set
https://claude.ai/code/session_01KF4i7Ra7zCEDskxDBaNtcT
The class-based selectors ([class*="header"], [class*="Header"],
[class*="nav-"], etc.) were matching Claude.ai's chat content area
elements, preventing reveal from running on any response text.
Narrowed to only structural elements: nav, aside, [role="navigation"],
[role="complementary"], [data-sidebar]. Removed HEADER/FOOTER from
SKIP_REVEAL_TAGS since sites use these tags inside chat layouts.
https://claude.ai/code/session_01KF4i7Ra7zCEDskxDBaNtcT
The smart engine records individual name parts ("Ademo"→"John",
"Demo"→"Smith") AND the combined form ("Ademo Demo"→"John Smith")
in sessionSubstitutions. The catch-all in buildRevealPairs was
adding all of them, causing partial replacements that corrupted
the DOM and made the cache oscillate between 4 and 0 pairs.
Fix: skip session entries whose key is a substring of a longer
entry (e.g. "ademo" is part of "ademo demo"). Only the combined
form gets added as a reveal pair.
Also: remove debug logging, improve cache with size tracking.
https://claude.ai/code/session_01KF4i7Ra7zCEDskxDBaNtcT
Root cause found: commit 9a11896 (v2.0.14) added isInNonChatArea()
and expanded SKIP_REVEAL_TAGS with NAV/ASIDE/HEADER/FOOTER, but that
commit was on a branch that was never merged into main. When we started
our work from main, these fixes were missing.
Restored:
- isInNonChatArea() function — prevents reveal from touching sidebars,
navigation, headers, footers, and other non-chat UI
- SKIP_REVEAL_TAGS expanded with NAV, ASIDE, HEADER, FOOTER
- isInNonChatArea checks added to revealInElement, unrevealInElement,
and highlightMatches (both element-level and walker-level)
https://claude.ai/code/session_01KF4i7Ra7zCEDskxDBaNtcT
Two bugs found:
1. Individual name parts ("Ademo"→"John", "Demo"→"Smith") were added
as reveal pairs, causing partial replacements that corrupted the DOM.
The smart engine sends combined forms ("Ademo Demo"→"John Smith")
which the catch-all already handles. Removed individual name entries
from buildRevealPairs — only emails, usernames, hostnames, phones
are matched individually.
2. Cache invalidated on every ss:config-updated (including settings-only
changes like reveal toggle). Now only invalidates when mappings or
identity actually change.
https://claude.ai/code/session_01KF4i7Ra7zCEDskxDBaNtcT
If reveal mode was saved as ON in settings, the page loaded with
revealMode=true and prevRevealMode=true. The checkRevealToggle
function only fires on transitions (off→on or on→off), so the
reveal interval was never started. Added initialization check
that starts the reveal interval immediately if revealMode is
already true at page load.
https://claude.ai/code/session_01KF4i7Ra7zCEDskxDBaNtcT
AMO expects { required: false } not { collect_user_data: false }.
Bumped strict_min_version to 140.0 (when data_collection_permissions
was introduced). Version 0.9.8.
https://claude.ai/code/session_01KF4i7Ra7zCEDskxDBaNtcT
When at-rest encryption is enabled, storage.onChanged fires with
encrypted blobs for ss_settings. The injector was passing this
encrypted blob directly as settings to the page world content script,
overwriting real settings with { _ssLocalEncrypted: true, data: ... }.
This broke reveal mode, highlights, and any setting toggle because
the content script's settings object became the encrypted blob.
Fix: skip encrypted settings blobs in injector.js (same check already
existed for mappings and identity). The background's settings:updated
message already sends decrypted settings correctly.
https://claude.ai/code/session_01KF4i7Ra7zCEDskxDBaNtcT
Added copilot.microsoft.com to host_permissions, content_scripts
matches, and BUILTIN_URL_PATTERNS in both Chrome and Firefox manifests
plus the service worker.
Updated README:
- Added Copilot to supported services table
- Added Edge and Brave to browser list
- Added note about desktop apps (can't intercept, use web version)
- Removed old duplicate browser note
https://claude.ai/code/session_01SWSwDfMVij53bCTNSCLMwn
New AI sites: Perplexity, Copilot, DeepSeek, HuggingChat, Poe
Developer/support: GitHub, GitLab, Reddit (www + old), Stack Overflow, Pastebin
The existing interception is service-agnostic — it scans all JSON strings
in POST/PUT/PATCH requests through the 4-stage substitution pipeline.
No site-specific handling needed; all sites use the same method.
https://claude.ai/code/session_01KF4i7Ra7zCEDskxDBaNtcT
Accept (+) button:
- Was reading raw storage (getStorageData) which returns encrypted
blobs when encryption is enabled, silently failing to add mappings
- Fixed: adds directly to the local mappings array and persists via
setStorageData (storage bridge handles encryption transparently)
Auto-detect false positives:
- Was only checking identity values, not explicit mappings — values
already in the mappings table still got flagged as unconfigured PPI
- Fixed: now adds all mapping real/substitute values to the skip set
Ignore button:
- Changed from plain text link to grey pill button for better UX
- Still persists permanently via ss_ignored_ppi in storage
https://claude.ai/code/session_01SWSwDfMVij53bCTNSCLMwn
When at-rest encryption is enabled, storage.local contains encrypted
blobs. The injector reads raw storage (content script world, no
access to IndexedDB CryptoKey) and sees { _ssLocalEncrypted: true }.
It passed empty config to content.js → no mappings → no substitution.
This is why Firefox stopped working after encryption was enabled.
Chrome/Brave worked because the user hadn't set up encryption there.
Fixed: injector now detects encrypted data and asks the background
script for decrypted config via 'get:decrypted-config' message.
The background uses the Storage module (which has IndexedDB access)
to decrypt and return the data. Falls back to empty config if the
vault is actually locked.
https://claude.ai/code/session_01SWSwDfMVij53bCTNSCLMwn
The early hook approach (inline script, then external early-hook.js)
kept breaking Firefox due to CSP restrictions and timing issues with
the async external script load. Each fix for ChatGPT introduced a
new regression for Firefox/Brave.
Reverted to the original simple approach:
- Injector reads storage, injects content.js via <script src="...">
- content.js captures window.fetch at load time and patches it
- No inline scripts, no early hooks, no __ssOriginalFetch globals
This is what worked on Claude.ai across all browsers before the
ChatGPT fix attempts. ChatGPT support may need a different approach
later (possibly using declarativeNetRequest for header-only changes,
or a ChatGPT-specific content script), but it should not break the
core functionality on Claude.ai.
Kept the Request object handling in the fetch interceptor (needed for
some frameworks) but removed all early hook dependencies.
https://claude.ai/code/session_01SWSwDfMVij53bCTNSCLMwn
The inline <script> with textContent was blocked by claude.ai's
Content Security Policy on Firefox (Chrome is more permissive).
No fetch interception = no substitution = completely broken on FF.
Fixed by moving the early fetch hook to its own file (early-hook.js)
loaded via <script src="..."> which is CSP-compliant. Added to
web_accessible_resources in both Chrome and Firefox manifests.
Also fixed duplicate 'const api' declaration in injector.js that
would have crashed the content script.
https://claude.ai/code/session_01SWSwDfMVij53bCTNSCLMwn