merge: integrate claude/read-repo-YMu21 branch
Merged changes from the other session: - Ko-fi support link in options footer - PPI → PII renaming across codebase - Legal/licensing updates (stronger disclaimer, non-commercial only) - Custom secret/auto-redact patterns - Internal refactoring of secret scanner to auto-redact naming - Custom domains in popup Options tab - Additional AI services (Perplexity, DeepSeek, HuggingChat, Poe) - Developer sites (GitHub, GitLab, Reddit, StackOverflow, Pastebin) - Dynamic content script registration for custom domains Resolved conflicts in options.html and popup.html (kept newer "Auto Redact" naming with custom patterns description). https://claude.ai/code/session_01SWSwDfMVij53bCTNSCLMwn
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
/**
|
||||
* 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 —
|
||||
* Scans text for potential PII that the user hasn't configured.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
const PPI_PATTERNS = [
|
||||
const PII_PATTERNS = [
|
||||
// --- Network ---
|
||||
{
|
||||
name: 'Private IP Address',
|
||||
@@ -21,7 +21,7 @@ const PPI_PATTERNS = [
|
||||
regex: /\b(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\b/g,
|
||||
category: 'network',
|
||||
hint: 'IP address — could identify your network',
|
||||
// Exclude common non-PPI IPs
|
||||
// Exclude common non-PII IPs
|
||||
exclude: /^(?:127\.0\.0\.1|0\.0\.0\.0|255\.255\.255\.\d+|8\.8\.[84]\.[84]|1\.1\.1\.1|1\.0\.0\.1)$/,
|
||||
},
|
||||
{
|
||||
@@ -126,12 +126,12 @@ const PPI_PATTERNS = [
|
||||
},
|
||||
];
|
||||
|
||||
// Context words that make ambiguous patterns more likely to be PPI
|
||||
// Context words that make ambiguous patterns more likely to be PII
|
||||
const CONTEXT_WORDS = /\b(?:born|birthday|dob|birth|passport|license|driver|ssn|social\s*security|address|home|live|lives|reside|zip|postal)\b/i;
|
||||
|
||||
const AutoDetect = {
|
||||
/**
|
||||
* Scan text for potential unconfigured PPI.
|
||||
* Scan text for potential unconfigured PII.
|
||||
* Pass in identity so we can skip values the user already configured.
|
||||
*
|
||||
* Returns array of { name, value, hint, category, index }
|
||||
@@ -167,7 +167,7 @@ const AutoDetect = {
|
||||
}
|
||||
}
|
||||
|
||||
for (const pattern of PPI_PATTERNS) {
|
||||
for (const pattern of PII_PATTERNS) {
|
||||
// Skip context-dependent patterns if no context words present
|
||||
if (pattern.contextRequired && !hasContext) continue;
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
/**
|
||||
* Silent Send - Secret Scanner
|
||||
* Silent Send - Auto Redact
|
||||
*
|
||||
* 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
|
||||
@@ -13,7 +15,7 @@
|
||||
* - severity: 'critical' (always redact) or 'warning' (flag but allow)
|
||||
*/
|
||||
|
||||
const SECRET_PATTERNS = [
|
||||
const REDACT_PATTERNS = [
|
||||
// --- API Keys ---
|
||||
{
|
||||
name: 'OpenAI API Key',
|
||||
@@ -161,14 +163,39 @@ const SECRET_PATTERNS = [
|
||||
},
|
||||
];
|
||||
|
||||
const SecretScanner = {
|
||||
const AutoRedact = {
|
||||
/**
|
||||
* Build the full pattern list (built-in + custom).
|
||||
* Custom patterns come from settings.customRedactPatterns.
|
||||
*/
|
||||
_buildPatterns(customPatterns) {
|
||||
const all = [...REDACT_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;
|
||||
},
|
||||
|
||||
/**
|
||||
* Scan text for secrets. Returns list of findings.
|
||||
* @param {string} text
|
||||
* @param {Array} [customPatterns] — from settings.customRedactPatterns
|
||||
*/
|
||||
scan(text) {
|
||||
scan(text, customPatterns) {
|
||||
const findings = [];
|
||||
const patterns = this._buildPatterns(customPatterns);
|
||||
|
||||
for (const pattern of SECRET_PATTERNS) {
|
||||
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.customRedactPatterns
|
||||
*/
|
||||
redact(text) {
|
||||
const findings = this.scan(text);
|
||||
redact(text, customPatterns) {
|
||||
const findings = this.scan(text, customPatterns);
|
||||
const redactions = [];
|
||||
let result = text;
|
||||
|
||||
@@ -220,7 +249,7 @@ const SecretScanner = {
|
||||
redactions.push({
|
||||
original: f.value,
|
||||
replaced: f.redactTo,
|
||||
category: 'secret',
|
||||
category: 'redact',
|
||||
pattern: f.name,
|
||||
});
|
||||
}
|
||||
@@ -237,7 +266,7 @@ const SecretScanner = {
|
||||
};
|
||||
|
||||
if (typeof globalThis !== 'undefined') {
|
||||
globalThis.SecretScanner = SecretScanner;
|
||||
globalThis.AutoRedact = AutoRedact;
|
||||
}
|
||||
|
||||
export default SecretScanner;
|
||||
export default AutoRedact;
|
||||
@@ -1,11 +1,11 @@
|
||||
/**
|
||||
* Silent Send - Document Scanner
|
||||
*
|
||||
* Scans uploaded documents for PPI and substitutes/redacts before
|
||||
* Scans uploaded documents for PII and substitutes/redacts before
|
||||
* the file reaches the AI service.
|
||||
*
|
||||
* Supported formats:
|
||||
* - PDF: Extract text, scan for PPI, create sanitized plaintext version
|
||||
* - PDF: Extract text, scan for PII, create sanitized plaintext version
|
||||
* (PDFs can't be reliably edited in-place without breaking layout)
|
||||
* - DOCX: Parse XML, find-replace text, repackage ZIP (layout preserved)
|
||||
* - XLSX: Parse cells, find-replace values, repackage (formatting preserved)
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* Modes:
|
||||
* - Silent: substitute and upload (default for text files)
|
||||
* - Preview: show PPI findings, let user confirm before upload (default for PDF/DOCX/XLSX)
|
||||
* - Preview: show PII findings, let user confirm before upload (default for PDF/DOCX/XLSX)
|
||||
*
|
||||
* Integration:
|
||||
* - The fetch interceptor in content.js detects multipart/form-data uploads
|
||||
@@ -70,9 +70,9 @@ const DocumentScanner = {
|
||||
},
|
||||
|
||||
/**
|
||||
* PDF: extract text, scan for PPI, create sanitized text file.
|
||||
* PDF: extract text, scan for PII, create sanitized text file.
|
||||
* PDFs can't be reliably edited in-place, so we extract text,
|
||||
* substitute PPI, and send the clean text instead.
|
||||
* substitute PII, and send the clean text instead.
|
||||
*/
|
||||
async _processPDF(file, filename, substituteAll, options) {
|
||||
const text = await this._extractPDFText(file);
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* - Policy updates are applied automatically
|
||||
*
|
||||
* Privacy: the org admin can check compliance (are required fields
|
||||
* configured?) but CANNOT see individual PPI values.
|
||||
* configured?) but CANNOT see individual PII values.
|
||||
*/
|
||||
|
||||
import api from './browser-polyfill.js';
|
||||
@@ -198,11 +198,11 @@ 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() {
|
||||
async getOrgRedactPatterns() {
|
||||
const policy = await this.getPolicy();
|
||||
if (!policy?.requiredSecretPatterns?.length) return [];
|
||||
|
||||
@@ -220,7 +220,7 @@ const OrgPolicy = {
|
||||
|
||||
/**
|
||||
* Check if the user's configuration meets org policy requirements.
|
||||
* Returns compliance status WITHOUT revealing actual PPI values.
|
||||
* Returns compliance status WITHOUT revealing actual PII values.
|
||||
*
|
||||
* @returns {{ compliant: boolean, missing: string[], configured: string[] }}
|
||||
*/
|
||||
|
||||
+3
-2
@@ -23,7 +23,7 @@ const KEYS = {
|
||||
SETTINGS: 'ss_settings',
|
||||
};
|
||||
|
||||
// Keys that contain sensitive PPI and should be encrypted at rest
|
||||
// Keys that contain sensitive PII and should be encrypted at rest
|
||||
// All user data keys are encrypted at rest — settings included since
|
||||
// custom domains and configuration can reveal what services the user
|
||||
// accesses. Only ss_sync_encryption (salt, verification blob) and
|
||||
@@ -34,12 +34,13 @@ const DEFAULT_SETTINGS = {
|
||||
enabled: true,
|
||||
showHighlights: false,
|
||||
revealMode: false,
|
||||
secretScanning: true,
|
||||
autoRedact: true,
|
||||
autoDetect: true,
|
||||
autoRedactDetected: true,
|
||||
autoAddDetected: true,
|
||||
maxLogEntries: 100,
|
||||
customDomains: [],
|
||||
customRedactPatterns: [],
|
||||
categories: ['name', 'email', 'phone', 'address', 'ssn', 'dob', 'domain', 'password', 'general'],
|
||||
browserSync: false,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user