Version
5.23.0
Steps to Reproduce
When using PostHogMaskWidget to selectively mask sensitive fields (e.g., password inputs) with maskAllTexts = false, the masked content may still appear unmasked in PostHog session recordings, even if I wrap these fields in PosthogMaskWidget
Expected Result
If I wrap something in PosthogMaskWidget, I eexpect it to be masked on sessionReplay, currently this doean't happen. Example:
PostHogMaskWidget( child: FormBuilderTextField( name: widget.name, initialValue: widget.initialValue, autofocus: widget.autofocus, obscureText: _isObscured, textInputAction: widget.textInputAction, keyboardType: widget.keyboardType, autofillHints: widget.autofillHints, maxLines: widget.maxLines, textCapitalization: widget.isSecureField ? TextCapitalization.none : widget.textCapitalization, decoration: InputDecoration( hintText: widget.hintText, errorText: widget.errorText, errorStyle: const TextStyle(fontSize: 0), suffix: widget.isSecureField ? GestureDetector( onTap: _toggleVisibility, child: Text( _isObscured ? LocaleKeys.show.tr() : LocaleKeys.hide.tr(), ), ) : null, ), onChanged: widget.onChanged, onSubmitted: widget.onSubmitted, validator: _validateField, ), ),
Actual Result
The Flutter plugin configures the native PostHog SDK (both iOS and Android) with sessionReplay = true, which enables the native SDK's own session replay mechanism alongside Flutter's screenshot-based
replay.
Android (PosthogFlutterPlugin.kt):
posthogConfig.getIfNotNull("sessionReplay") {
sessionReplay = it // enables native SDK session replay
}
iOS (PosthogFlutterPlugin.swift):
if let sessionReplay = posthogConfig["sessionReplay"] as? Bool {
config.sessionReplay = sessionReplay // enables native SDK session replay
}
This results in two parallel recording streams:
- Flutter-side (PostHogWidget / ScreenshotCapturer): Captures screenshots from the RepaintBoundary, applies masks from PostHogMaskWidget and TextField(obscureText: true), then sends masked image bytes
to native via sendFullSnapshot
- Native-side (posthog-ios / posthog-android): Captures the raw FlutterView / FlutterSurfaceView content directly — without any masking
Both produce $snapshot events sent to PostHog, meaning unmasked frames from the native SDK can appear in recordings.
Version
5.23.0
Steps to Reproduce
When using PostHogMaskWidget to selectively mask sensitive fields (e.g., password inputs) with maskAllTexts = false, the masked content may still appear unmasked in PostHog session recordings, even if I wrap these fields in PosthogMaskWidget
Expected Result
If I wrap something in PosthogMaskWidget, I eexpect it to be masked on sessionReplay, currently this doean't happen. Example:
PostHogMaskWidget( child: FormBuilderTextField( name: widget.name, initialValue: widget.initialValue, autofocus: widget.autofocus, obscureText: _isObscured, textInputAction: widget.textInputAction, keyboardType: widget.keyboardType, autofillHints: widget.autofillHints, maxLines: widget.maxLines, textCapitalization: widget.isSecureField ? TextCapitalization.none : widget.textCapitalization, decoration: InputDecoration( hintText: widget.hintText, errorText: widget.errorText, errorStyle: const TextStyle(fontSize: 0), suffix: widget.isSecureField ? GestureDetector( onTap: _toggleVisibility, child: Text( _isObscured ? LocaleKeys.show.tr() : LocaleKeys.hide.tr(), ), ) : null, ), onChanged: widget.onChanged, onSubmitted: widget.onSubmitted, validator: _validateField, ), ),Actual Result
The Flutter plugin configures the native PostHog SDK (both iOS and Android) with sessionReplay = true, which enables the native SDK's own session replay mechanism alongside Flutter's screenshot-based
replay.
Android (PosthogFlutterPlugin.kt):
posthogConfig.getIfNotNull("sessionReplay") {
sessionReplay = it // enables native SDK session replay
}
iOS (PosthogFlutterPlugin.swift):
if let sessionReplay = posthogConfig["sessionReplay"] as? Bool {
config.sessionReplay = sessionReplay // enables native SDK session replay
}
This results in two parallel recording streams:
to native via sendFullSnapshot
Both produce $snapshot events sent to PostHog, meaning unmasked frames from the native SDK can appear in recordings.