Skip to content

Privacy and security

Session replay that assumes the recording is hostile

Rendering another company’s DOM inside your dashboard is the most dangerous thing a replay tool does, and recording your users’ screens is the most sensitive. AnyReplay is built so that neither can go wrong quietly: masking happens before anything is sent, passwords and payment fields are never recorded at all, replay cannot execute code, and every rule here is enforced by a test rather than a promise.

Never recorded
passwords, card fields
No scripts
replay iframe
Argon2id
password hashing
Append-only
audit trail
A faceted glass shield glowing indigo, with blurred masked rectangles behind frosted glass

Masking is yours to set, and it happens before the network

The browser SDK masks what people type by default, so a replay of a form shows it being filled in with asterisks — you still see the misread label and the field that would not validate. maskAllInputs: false records the values themselves, and maskAllTyping: true masks rich-text editors as well. Beneath them is a floor no option can lift: passwords, one-time codes, card numbers, CVVs, expiry dates, bank details and any value shaped like a card number are replaced on the user’s device or in their browser, before a single byte is sent. Nothing is uploaded and then hidden, because hidden is not the same as absent.

Which means how much a recording contains is your decision, and we would rather say that plainly than let you assume it is empty. Mark the sensitive parts of your pages with ar-mask and they keep their shape and lose their words; keep every field masked and a reviewer still sees that a field was filled in, where, and how long it took. Everything downstream — storage, replay, translation — only ever sees what left the browser. The masking documentation lists exactly what is never recorded.

The replay sandbox: three walls, one test

The player renders a customer’s DOM inside the dashboard. Three things stand between that and a cross-tenant compromise:

  1. Script bodies never leave the customer’s page. rrweb replaces them with a placeholder at record time.
  2. Scripts are rebuilt as noscript. Even if markup carried code, replay cannot execute it.
  3. The replay iframe is sandboxed without allow-scripts. rrweb adds that permission only when canvas replay is switched on, so it stays off — and a test fails the build if anyone turns it on.

Checked in a real browser, the replay iframe reports sandbox="allow-same-origin" and the recorded page’s script tags come back as noscript. Mobile sessions are recorded as structured data rather than markup, so there is no foreign DOM to render at all.

The project key is public. The origin allow-list is not.

The key in your snippet ships in your HTML, so it cannot be a secret and is not treated as one. Ingest is a separate service with the opposite load profile to the dashboard — high-volume, unauthenticated, write-only — and the real access control is its server-side Origin allow-list, which a page cannot forge. An app has no web origin, so it is checked against the project’s Allowed apps by the bundle id it sends as appId — a filter that keeps stray traffic out, not a secret. Ingest also enforces rate limits — 120 requests a minute per device, so one busy phone cannot use up a project’s budget — idempotent chunk uploads and payload validation, each covered by its own tests.

Tenant isolation, verified from the outside

Every organisation-scoped route is exercised in the test suite from a foreign tenant. Chunk keys embed the project and session ids, and every chunk read is organisation-scoped, so an unchecked read cannot stream another customer’s recording to anyone holding an id. A resource you do not own answers 404, never 403: the API is not an existence oracle.

Accounts, roles and the audit trail

Passwords are hashed with Argon2id at OWASP parameters, enforced by test. Refresh tokens rotate, and a replayed token revokes its whole family. Five roles — owner, admin, moderator, member and viewer — map onto a permission matrix that the API enforces and the tests cover cell by cell; no role can grant a role at or above its own rank. Permission changes, deletions and key rotations are written to an append-only audit trail.

Retention you set, deletion you can prove

Retention is configured in days per organisation. A sweeper removes recordings past it on a fixed schedule, the deletion is recorded in the audit trail, and the Free plan’s 14 days work the same way as a longer paid window. Consent gates are available on both SDKs (requireConsent records nothing until you say so), and the privacy policy describes what AnyReplay itself stores about your team.

What we would tell your security team

The API test suite boots the real application against a real PostgreSQL engine and drives it over HTTP; nothing is mocked, because an authorisation test that mocks the guard proves nothing. The browser SDK has a bundle budget enforced in CI. Security headers are set on every response. If you need a questionnaire or a DPA, that is part of the Enterprise plan on the pricing page, and the compare pages set these choices against other tools’.

Watch any session in your language.

Install in minutes, keep the Free plan for as long as you like. One project and 500 sessions a month, free.