diff --git a/src/content/content.js b/src/content/content.js index 47fd4e5..b843d72 100644 --- a/src/content/content.js +++ b/src/content/content.js @@ -301,7 +301,7 @@ const explicit = substitute(smart.text, mappings); allReplacements.push(...explicit.replacements); - // 3. Secret scanner (API keys, tokens, SSNs, credit cards, etc.) + // 3. Auto Redact (API keys, tokens, SSNs, credit cards, custom patterns, etc.) let finalText = explicit.text; if (settings.secretScanning !== false) { const secrets = scanAndRedactSecrets(finalText); @@ -665,8 +665,9 @@ } // ============================================================ - // Secret Scanner (inline for page world) - // Detects API keys, tokens, passwords, SSNs, credit cards, etc. + // Auto Redact — Secret Scanner (inline for page world) + // Detects API keys, tokens, passwords, SSNs, credit cards, + // plus user-defined custom patterns from settings. // ============================================================ const SECRET_PATTERNS = [ // OpenAI @@ -710,7 +711,17 @@ const redactions = []; let result = text; - for (const pat of SECRET_PATTERNS) { + // Combine built-in + custom patterns + const allPatterns = [...SECRET_PATTERNS]; + const custom = settings.customSecretPatterns || []; + for (const cp of custom) { + if (!cp.enabled || !cp.pattern) continue; + try { + allPatterns.push({ name: cp.name, re: new RegExp(cp.pattern, 'g'), to: cp.redact }); + } catch { /* invalid regex — skip */ } + } + + for (const pat of allPatterns) { pat.re.lastIndex = 0; const matches = []; let m; diff --git a/src/lib/auto-detect.js b/src/lib/auto-detect.js index bea7464..f06f336 100644 --- a/src/lib/auto-detect.js +++ b/src/lib/auto-detect.js @@ -2,7 +2,7 @@ * Silent Send - Auto-Detect * * Scans text for potential PPI that the user hasn't configured. - * This catches things the identity and secret scanner can't — + * This catches things the identity and auto-redact scanner can't — * because the user forgot or didn't know to configure them. * * Returns warnings (not auto-redactions) so the user can decide. diff --git a/src/lib/org-policy.js b/src/lib/org-policy.js index a4efa70..4e53470 100644 --- a/src/lib/org-policy.js +++ b/src/lib/org-policy.js @@ -198,9 +198,9 @@ const OrgPolicy = { }, /** - * Get org-required secret scanner patterns. + * Get org-required auto-redact patterns. * - * @returns {Array} additional patterns to add to the secret scanner + * @returns {Array} additional patterns to add to auto-redact */ async getOrgSecretPatterns() { const policy = await this.getPolicy(); diff --git a/src/lib/secret-scanner.js b/src/lib/secret-scanner.js index 89758f0..4679d08 100644 --- a/src/lib/secret-scanner.js +++ b/src/lib/secret-scanner.js @@ -1,11 +1,13 @@ /** - * Silent Send - Secret Scanner + * Silent Send - Auto Redact (Secret Scanner) * * Detects common secret/credential patterns in text and either * warns or auto-redacts them. This catches things the identity-based * smart patterns can't: API keys, tokens, passwords, SSNs, credit * cards, private keys, connection strings, etc. * + * Supports user-defined custom patterns for proprietary token formats. + * * Each pattern has: * - name: human-readable label * - regex: detection pattern @@ -163,12 +165,37 @@ const SECRET_PATTERNS = [ const SecretScanner = { /** - * Scan text for secrets. Returns list of findings. + * Build the full pattern list (built-in + custom). + * Custom patterns come from settings.customSecretPatterns. */ - scan(text) { - const findings = []; + _buildPatterns(customPatterns) { + const all = [...SECRET_PATTERNS]; + if (Array.isArray(customPatterns)) { + for (const cp of customPatterns) { + if (!cp.enabled || !cp.pattern) continue; + try { + all.push({ + name: cp.name || 'Custom Pattern', + regex: new RegExp(cp.pattern, 'g'), + redact: cp.redact || '[REDACTED-CUSTOM]', + severity: 'critical', + }); + } catch { /* invalid regex — skip */ } + } + } + return all; + }, - for (const pattern of SECRET_PATTERNS) { + /** + * Scan text for secrets. Returns list of findings. + * @param {string} text + * @param {Array} [customPatterns] — from settings.customSecretPatterns + */ + scan(text, customPatterns) { + const findings = []; + const patterns = this._buildPatterns(customPatterns); + + for (const pattern of patterns) { // Reset regex lastIndex pattern.regex.lastIndex = 0; let match; @@ -204,9 +231,11 @@ const SecretScanner = { /** * Redact all critical secrets in text. Warnings are not auto-redacted. * Returns { text, redactions[] } + * @param {string} text + * @param {Array} [customPatterns] — from settings.customSecretPatterns */ - redact(text) { - const findings = this.scan(text); + redact(text, customPatterns) { + const findings = this.scan(text, customPatterns); const redactions = []; let result = text; diff --git a/src/lib/storage.js b/src/lib/storage.js index 61d11c3..dea8bfa 100644 --- a/src/lib/storage.js +++ b/src/lib/storage.js @@ -40,6 +40,7 @@ const DEFAULT_SETTINGS = { autoAddDetected: true, maxLogEntries: 100, customDomains: [], + customSecretPatterns: [], categories: ['name', 'email', 'phone', 'address', 'ssn', 'dob', 'domain', 'password', 'general'], browserSync: false, }; diff --git a/src/options/options.html b/src/options/options.html index 147f151..504f2e4 100644 --- a/src/options/options.html +++ b/src/options/options.html @@ -49,17 +49,38 @@
- -

Auto-detect and redact API keys, tokens, passwords, SSNs, credit card numbers

+ +

Automatically detect and redact API keys, tokens, passwords, SSNs, credit card numbers, and custom patterns

+ + +
+

Custom Secret Patterns

+

+ Define your own patterns to catch proprietary tokens, internal URLs with keys, or any format the built-in scanner doesn't cover. +

+
+
+
+ + +
+
+ + +
+
+

+ Tip: For a URL like https://dns.example.com/abc123, use a pattern like dns\.example\.com/[A-Za-z0-9;]+ to match the secret path segment. +

+
+
-
-

Warn when potential personal data (IPs, addresses, paths) is detected that you haven't configured