Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
835f86e
docs: add Privacy at Capture v2 simplification design spec
Aug 25, 2026
62f611a
docs: add privacy v2 implementation plan
Aug 26, 2026
0880e2b
feat(privacy): compile policy onto selector lists and rrweb options
Aug 26, 2026
54798a2
fix(privacy): restore interim maskAllElementAttributes/maskAttributeF…
Aug 26, 2026
01fbc2e
feat(privacy): fixed whole-value detectors, delete range and custom-p…
Aug 26, 2026
2b253f2
fix(privacy): tighten phone pattern quantifier for whole-value semant…
Aug 26, 2026
ec48742
feat(privacy): sanitizeUrl strips userinfo, uses precompiled sets, fa…
Aug 26, 2026
90036fe
feat(privacy): unmask selector + detector hook in core text masking, …
Aug 26, 2026
72e4763
fix(privacy): keep inherited masking across shadow/iframe boundaries,…
Aug 26, 2026
22c9d9d
feat(privacy): single maskInput entry point, Sentry-style fn composition
Aug 26, 2026
145ac97
feat(privacy): single attribute finalization pass, added-node coverag…
Aug 26, 2026
43afe1e
fix(privacy): apply policy to renamed rr_src, make maskAttributeFn a …
Aug 26, 2026
5d32701
fix(privacy): let an emptied attribute reach the policy block
Aug 26, 2026
bdb7597
feat(privacy): CSS is never masked; delete stylesheet masking call sites
Aug 26, 2026
1b65915
fix(canvas): masking forces FPS capture path; content-box region scal…
Aug 26, 2026
0bf6128
fix(privacy): plugin compile fallback, shared untainted tagName, plug…
Aug 26, 2026
1525d45
fix(privacy): route remaining mutation.ts tagName reads through untai…
Aug 26, 2026
f00cea8
docs(privacy): v2 types sync, changeset, guide
Aug 26, 2026
f34e6c7
fix(privacy): scan input values and live text mutations with detectors
Aug 26, 2026
9da8a3a
docs(privacy): fix detector-coverage claim, changeset hygiene, legacy…
Aug 26, 2026
f7c4f1c
test(privacy): perf smoke + full sweep
Aug 26, 2026
5201b4c
fix(privacy): final review fixes — phone recall, disclosures, preset …
Aug 26, 2026
0d60d4d
Apply formatting changes
roggernaut Aug 26, 2026
101010b
chore(privacy): neutral vendor attribution, remove internal process docs
Aug 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions .changeset/calm-ravens-protect.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@
"rrweb-snapshot": minor
---

Add an opt-in, versioned privacy policy with strict, balanced, custom, and
legacy presets. Policies consistently protect text, form values, sensitive
attributes, URLs, snapshots, and incremental mutations while preserving the
existing rrweb masking options as the backwards-compatible legacy path. The
vendor-neutral `data-privacy="exclude|mask|allow"` HTML binding works without
recorder-specific configuration. Add fail-closed canvas-region masking for
complex canvas applications, suppress unmasked full-snapshot canvas stills,
and provide coarse and callback-based final attribute masking escape hatches.
Add an opt-in, versioned `privacyPolicy` with `strict`, `balanced`, and
`legacy` presets. Compiled policies consistently protect text, form values,
sensitive attributes (`title`, `placeholder`, `aria-label`), and URLs across
full snapshots and incremental mutations, while the existing rrweb masking
options remain the backwards-compatible `legacy` default. CSS is never
masked, on any preset. Under `balanced`/`strict`, the vendor-neutral
`data-privacy="exclude|mask|allow"` HTML binding and common cross-vendor
masking class names are recognized directly in markup; selector-based policy
`rules` work under every preset, including `legacy`. Add fail-closed
`canvasMasking` region masking for complex canvas applications (configuring
it forces the FPS capture path and suppresses the unmasked `rr_dataURL`
full-snapshot still), plus coarse (`maskAllElementAttributes`) and
callback-based (`maskAttributeFn`) final attribute masking escape hatches.
2 changes: 0 additions & 2 deletions .changeset/khaki-hoops-smile.md

This file was deleted.

2 changes: 1 addition & 1 deletion .changeset/kind-pumas-detect.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"@rrweb/types": minor
---

Move Highlight-style heuristic PII auto-detection out of `balanced`/`strict`
Move heuristic PII auto-detection out of `balanced`/`strict`
defaults and into an opt-in `@rrweb/rrweb-plugin-privacy-detectors` plugin.
Presets still mask form values and honor policy rules; email/phone/card/SSN/IP
text matching is enabled only by the plugin or `applyPrivacyDetectors`.
9 changes: 0 additions & 9 deletions .changeset/loud-lions-protect.md

This file was deleted.

46 changes: 46 additions & 0 deletions .changeset/privacy-v2-simplification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
"rrweb-snapshot": minor
"rrweb": minor
"@rrweb/types": major
"@rrweb/rrweb-plugin-privacy-detectors": minor
"@rrweb/utils": minor
---

Privacy at Capture v2: policies now compile onto rrweb's existing masking
primitives; heuristic detectors are a fixed whole-value set (custom regex
patterns removed); CSS is never masked; canvas masking forces the FPS capture
path; selector and config errors fail closed. BREAKING (@rrweb/types):
`ImageBitmapDataURLWorkerParams` is a union; privacy rule `style`,
`classification`, custom detectors, and the `'custom'` preset are removed.

Additional breaking/behavior notes:

- `needMaskingText` (exported from `rrweb-snapshot`) gained parameters; old
positional callers break.
- `<style>` text inside masked subtrees is no longer masked on any path,
including `characterData` mutations -- this is deliberate: CSS is never
masked.
- Heuristic detection now masks whole values -- there is no more
character-range `'xxxx'`-shape masking. It scans page text nodes and form
input values, both at snapshot time and on live updates (`characterData`
mutations and input events), whenever the value would otherwise be recorded
unmasked. Attribute values are not scanned.
- `maskInputFn`/`maskAttributeFn` outputs are constrained under
`balanced`/`strict`: `maskInputFn` output is star-replaced (the callback
controls length, never content), and `maskAttributeFn` output is
policy-final (the compiled policy can still narrow, but never restore,
what the callback chose to keep).
- `maskAllElementAttributes` and `maskAttributeFn` are now mutually
exclusive: when both are supplied, `maskAllElementAttributes` wins and
`maskAttributeFn` is ignored with a one-time console warning.
- Protected inputs -- `password`, `hidden`, `data-rr-is-password`, and
autocomplete `cc-*`/`current-password`/`new-password`/`one-time-code` --
are now **always** masked, with no `privacyPolicy` required and regardless
of `maskInputOptions`. Previously `hidden` inputs and autocomplete-tagged
credit-card/password/OTP fields could record their raw value under
`legacy`; they cannot anymore.
- An invalid `maskTextSelector`/`unmaskTextSelector` (including the plain
`record()`-level string options, not just policy `rules`) now fails closed
-- the bad selector throws inside the mask decision, which is caught and
masks the text -- instead of being silently ignored as if it had never been
set.
Loading
Loading