feat(replay): add selective unmasking and protect sensitive inputs - #574
feat(replay): add selective unmasking and protect sensitive inputs#574marandaneto wants to merge 2 commits into
Conversation
PR overviewAll previously flagged issues have been addressed. No open security concerns remain on this pull request. Security reviewNo open security issues remain on this pull request. Fixed/addressed: 1 · PR risk: 0/10 |
posthog-flutter Compliance ReportDate: 2026-09-11 10:48:26 UTC ✅ All Tests Passed!45/45 tests passed Capture Tests✅ 29/29 tests passed View Details
Feature_Flags Tests✅ 16/16 tests passed View Details
|
|
Reviews (1): Last reviewed commit: "feat(replay): add selective unmasking an..." | Re-trigger Greptile |
Android emulator validationValidated commit All 70 tests passed: the 69 regression tests plus a temporary interaction test that typed synthetic values into fields, enabled “show password,” and toggled the unmask wrapper off and on. Pixel assertions and inspection of the captured source and masked images confirmed:
The regression tests also checked captured pixels at 1x and 2x resolution. The earlier before/after run reproduced 62 failures against the pre-fix masking code on the emulator. The temporary integration app used the SDK from this PR's worktree, a fake SDK platform, and the production mask painter. This validates Flutter rendering and captured replay pixels, not recording uploads or backend ingestion. No iOS device run was performed. No further SDK changes were needed. |
💡 Motivation and Context
Fixes #569.
Flutter apps cannot currently reveal selected safe content while keeping global replay masking enabled. Disabling
maskAllTextsalso leaves card-number, expiration-date, security-code, OTP, and password autofill fields without automatic SDK masking. Material fields withobscureText: trueare already protected, but Cupertino and directEditableTextfields do not have the same protection.This adds
PostHogUnmaskWidgetfor known-safe Flutter text and images:Explicit
PostHogMaskWidgetmasks and sensitive inputs remain masked regardless of nesting. Sensitive inputs include obscured fields, password keyboard types, and password, new-password, card-number, expiration-date (including day, month, and year), security-code, and OTP autofill hints. The mask also covers scaled text that extends beyond a dense field's layout bounds.Flutter web still requires canvas masking to be enabled. The new widget does not remove masks from overlapping widgets or change native platform views or captured native screens. API documentation, the public API snapshot, and a minor changeset are included.
💚 How did you test it?
git diff --checkpassed.autoreview --mode branch --base origin/mainon commit56fd14cba20ea185989e11d53b6bfd712b4a8ebe. It reported no actionable findings.The tests use a fake SDK platform and a posthog-js stub. They do not upload recordings or verify backend ingestion. No iOS device run was performed.
📝 Checklist
If releasing new changes
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Implemented with Pi using Git, Flutter, and GitHub CLI. The work was done in a dedicated worktree with reproduction-first tests and a separate Pi autoreview pass. Explicit masks and sensitive inputs take precedence over unmasking to prevent an overly broad wrapper from revealing them. Human review is required.