The keyword pre-filter used case-sensitive string matching for all patterns,
but several regex patterns use the /i flag (e.g. generic_api_key). This meant
inputs like 'ApiKey = "secret"' would skip the keyword check for 'api_key'
and miss the redaction entirely.
Changes:
- Add caseInsensitive parameter to hasKeyword() that lowercases both content
and keywords before comparison
- Detect /i flag on pattern regex and pass it through automatically
- Narrow IP address keywords from ["."] to ["0.", "1.", ..., "9."] to reduce
false-positive regex invocations on content containing periods
- Fix email regex character class [A-Z|a-z] → [A-Za-z] (the pipe was literal)
- Add clarifying comment on url_with_creds pattern
- Add test cases for mixed-case and UPPER_CASE key assignments
- Relax SECRET_KEY test assertion to accept either redaction label
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The same HTML entity escaping logic was duplicated in three places:
MessageBubble.tsx, html-exporter.ts, and markdown.ts. Consolidate into
a single shared/escape-html.ts with a single-pass regex+lookup implementation
instead of five chained .replace() calls.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Shared module consumed by both the Express server and the React client:
types.ts:
- ParsedMessage: the normalized message unit (uuid, category, content,
toolName, toolInput, timestamp, rawIndex) that the parser emits and
every downstream consumer (viewer, filter, export) operates on
- MessageCategory: 9-value union covering user_message, assistant_text,
thinking, tool_call, tool_result, system_message, hook_progress,
file_snapshot, and summary
- SessionEntry / SessionListResponse / SessionDetailResponse / ExportRequest:
API contract types for the sessions list, session detail, and HTML
export endpoints
- ALL_CATEGORIES, CATEGORY_LABELS, DEFAULT_HIDDEN_CATEGORIES: constants
for the filter panel UI and presets (thinking + hook_progress hidden
by default)
sensitive-redactor.ts:
- 34 regex patterns derived from gitleaks production config, organized
into Tier 1 (known secret formats: AWS, GitHub, GitLab, OpenAI,
Anthropic, HuggingFace, Perplexity, Stripe, Slack, SendGrid, Twilio,
GCP, Azure AD, Heroku, npm, PyPI, Sentry, JWT, PEM private keys,
generic API key assignments) and Tier 2 (PII/system info: home
directory paths, connection strings, URLs with credentials, email
addresses, IPv4 addresses, Bearer tokens, env var secret assignments)
- Keyword pre-filtering: each pattern declares keywords that must appear
in the text before the expensive regex is evaluated, following the
gitleaks performance optimization approach
- False-positive allowlists: example/test email domains, localhost/
documentation IPs (RFC 5737), noreply@anthropic.com
- Pure functions: redactSensitiveContent returns {sanitized, count,
categories}, redactString returns just the string, redactMessage
returns a new ParsedMessage with content and toolInput redacted
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>