From 95534e28e039ad0f8623989ef96284eb34a5cc70 Mon Sep 17 00:00:00 2001 From: dab246 Date: Mon, 15 Dec 2025 13:52:35 +0700 Subject: [PATCH] TF-4136 security(sentry): scrub sensitive headers without mutating HTTP payloads --- core/lib/utils/config/env_loader.dart | 5 +-- core/lib/utils/sentry/sentry_initializer.dart | 45 ++++++++++++++++--- core/lib/utils/sentry/sentry_manager.dart | 2 +- docs/configuration/sentry_configuration.md | 12 ++++- lib/main/main_entry.dart | 4 +- 5 files changed, 57 insertions(+), 11 deletions(-) diff --git a/core/lib/utils/config/env_loader.dart b/core/lib/utils/config/env_loader.dart index aab975b31..9b4c49f28 100644 --- a/core/lib/utils/config/env_loader.dart +++ b/core/lib/utils/config/env_loader.dart @@ -1,5 +1,4 @@ import 'package:core/utils/app_logger.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; class EnvLoader { @@ -21,7 +20,7 @@ class EnvLoader { static Future loadFcmConfigFileToEnv({ Map? currentMapEnvData, - VoidCallback? onCallBack, + Future Function()? onCallBack, }) async { try { await dotenv.load( @@ -30,7 +29,7 @@ class EnvLoader { ); } catch (e) { logWarning('EnvLoader::loadFcmConfigFileToEnv: Exception = $e'); - onCallBack?.call(); + await onCallBack?.call(); } } diff --git a/core/lib/utils/sentry/sentry_initializer.dart b/core/lib/utils/sentry/sentry_initializer.dart index 601a3c407..73d5918bd 100644 --- a/core/lib/utils/sentry/sentry_initializer.dart +++ b/core/lib/utils/sentry/sentry_initializer.dart @@ -4,6 +4,14 @@ import 'package:core/utils/sentry/sentry_config.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; class SentryInitializer { + static const _blockedHeaderPatterns = [ + 'authorization', + 'cookie', + 'set-cookie', + 'x-auth', + 'x-token', + ]; + static Future init(FutureOr Function() appRunner) async { final config = await SentryConfig.load(); @@ -36,10 +44,37 @@ class SentryInitializer { SentryEvent event, Hint? hint, ) async { - // Ignore AssertionError events - if (event.throwable is AssertionError) { - return null; - } - return event; + final req = event.request; + if (req == null) return event; + + final sanitizedHeaders = Map.from(req.headers) + ..removeWhere( + (k, _) => _blockedHeaderPatterns.any( + (p) => k.toLowerCase().contains(p), + ), + ); + + final sanitizedRequest = SentryRequest( + url: req.url, + method: req.method, + headers: sanitizedHeaders, + queryString: req.queryString, + cookies: null, + data: null, + ); + + return SentryEvent( + eventId: event.eventId, + contexts: event.contexts, + throwable: event.throwable, + timestamp: event.timestamp, + level: event.level, + logger: event.logger, + request: sanitizedRequest, + tags: event.tags, + breadcrumbs: event.breadcrumbs, + user: event.user, + fingerprint: event.fingerprint, + ); } } diff --git a/core/lib/utils/sentry/sentry_manager.dart b/core/lib/utils/sentry/sentry_manager.dart index 909dd723a..999f28adf 100644 --- a/core/lib/utils/sentry/sentry_manager.dart +++ b/core/lib/utils/sentry/sentry_manager.dart @@ -68,7 +68,7 @@ class SentryManager { Breadcrumb( message: message, data: extras, - level: SentryLevel.info, + level: level, ), ); }, diff --git a/docs/configuration/sentry_configuration.md b/docs/configuration/sentry_configuration.md index 7d1dbdf39..209c02d3a 100644 --- a/docs/configuration/sentry_configuration.md +++ b/docs/configuration/sentry_configuration.md @@ -21,8 +21,18 @@ SENTRY_ENVIRONMENT= ### 2. Activate Sentry in environment file In [`env.file`](https://github.com/linagora/tmail-flutter/blob/master/env.file), ensure the following line is present: +- If you want to use Sentry: ```bash -SENTRY_ENABLED=true | false +SENTRY_ENABLED=true +``` + +- If you don't want to use Sentry: +```bash +SENTRY_ENABLED=false +``` + or +```bash +SENTRY_ENABLED= ``` ### 3. Verification diff --git a/lib/main/main_entry.dart b/lib/main/main_entry.dart index f2c31ac4e..bb7900e21 100644 --- a/lib/main/main_entry.dart +++ b/lib/main/main_entry.dart @@ -30,5 +30,7 @@ Future runTmailPreload() async { await CozyIntegration.integrateCozy(); await HiveCacheConfig.instance.initializeEncryptionKey(); - setPathUrlStrategy(); + if (PlatformInfo.isWeb) { + setPathUrlStrategy(); + } }