diff --git a/lib/main.dart b/lib/main.dart index dca6595e..bce9f004 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -81,6 +81,7 @@ void main() async { options.attachStacktrace = true; options.enableAutoSessionTracking = false; options.beforeSend = _beforeSend; + options.beforeBreadcrumb = _beforeBreadcrumb; }, appRunner: () async { // Initialize settings first to get saved locale @@ -150,6 +151,19 @@ void main() async { ); } +Breadcrumb? _beforeBreadcrumb(Breadcrumb? breadcrumb, Hint hint) { + if (breadcrumb == null) return null; + + final message = breadcrumb.message; + final data = breadcrumb.data; + if (message == null && (data == null || data.isEmpty)) return breadcrumb; + + return breadcrumb.copyWith( + message: message != null ? LogRedactionManager.redact(message) : null, + data: data?.map((k, v) => MapEntry(k, v is String ? LogRedactionManager.redact(v) : v)), + ); +} + FutureOr _beforeSend(SentryEvent event, Hint hint) { // Drop event if user opted out of crash reporting final instance = SettingsService.instanceOrNull; diff --git a/lib/utils/log_redaction_manager.dart b/lib/utils/log_redaction_manager.dart index 50b181a9..44644508 100644 --- a/lib/utils/log_redaction_manager.dart +++ b/lib/utils/log_redaction_manager.dart @@ -12,6 +12,12 @@ class LogRedactionManager { static final RegExp _ipv4Pattern = RegExp(r'\b(\d{1,3})([.-])(\d{1,3})\2(\d{1,3})\2(\d{1,3})\b'); static final RegExp _ipv4HostPattern = RegExp(r'^\d{1,3}([.-]\d{1,3}){3}$'); + /// Pattern-based catch-all for Plex tokens in query strings/headers. + static final RegExp _plexTokenQueryParam = RegExp( + r'X-Plex-Token=[^&#\s]+', + caseSensitive: false, + ); + // Combined regex for single-pass redaction (rebuilt on set changes) static RegExp? _combinedPattern; @@ -90,7 +96,10 @@ class LogRedactionManager { (match) => _maskIpv4(match.group(1)!, match.group(2)!, match.group(5)!), ); - // Pass 2: All tracked values in single pass + // Pass 2: Strip X-Plex-Token query parameters (pattern-based, no pre-registration needed) + redacted = redacted.replaceAll(_plexTokenQueryParam, 'X-Plex-Token=[REDACTED]'); + + // Pass 3: All tracked values in single pass if (_combinedPattern != null) { redacted = redacted.replaceAllMapped(_combinedPattern!, (match) { final value = match.group(0)!;