Blog

Why sensitive data never leaves the device in uxLens recordings

July 14, 2026 · 5 min read

A session-replay tool that ships a raw screen recording somewhere and then tries to redact it after the fact is trusting every downstream system, the network, the storage layer, the backend, to handle sensitive data correctly before that redaction happens. uxLens takes the opposite approach: masking happens before a frame is ever encoded, on the device, so sensitive content never exists in an unmasked form outside the phone.

Masking native Flutter content

The SDK walks the live Semantics tree, the same accessibility tree screen readers use, at capture time. Fields matching a built-in or configured keyword list (password, card number, CVV, SSN, email, and more) get their region painted black on the captured ui.Image before it's ever compressed. Password fields are also caught automatically by their obscured-text flag, regardless of what their label says, so a misnamed or unlabeled password field is still masked.

Because this runs against the render tree at the moment of capture, there's no unmasked intermediate image sitting in memory at any point, encoding starts from pixels that are already masked.

The harder case: WebView content

Native Flutter content is straightforward because uxLens controls the render tree. A WebView is a different problem: its content is composited outside Flutter's render tree entirely, and a payment form is often served through a cross-origin iframe from a gateway the host app doesn't control, which means the page can't even read the iframe's contents to check what's in it.

uxLens's WebView masking fails closed: a WebView is suppressed from the moment it mounts, and again at the start of every navigation, until a detector has actually run and confirmed the page holds no payment UI or sensitive field. Detection is content-based rather than URL-based, matching known payment gateways, card-shape input heuristics, and merchant-rendered label text ("Card number", "Security code") that's visible in the top document even when the actual input fields live in an unreadable cross-origin iframe. Once any focused iframe is flagged, suppression latches until the page navigates away, so a filled-in card form is never captured partway through checkout.

Why fail closed

The guiding rule is: if the SDK can't positively confirm a screen is safe, it doesn't capture it. That trades a small amount of replay coverage (a page the detector can't run on stays suppressed) for a much stronger guarantee: nothing sensitive leaves the device, not "nothing sensitive that the redaction step happened to catch."