privacy & capture

read this before deploying remediate to a context where end users will trigger captures.

screenshots, recordings, and nearbyText capture whatever is visible on the page at the moment of capture. that includes passwords, account numbers, addresses, payment info, anything in the dom. test your masking in staging before turning it on in production. you are the data controller for everything remediate produces.

what gets captured, by mode

screenshots (photo)

a png rasterized from the dom of the selected region.

includes: text, layout, css backgrounds, same-origin images. excludes: cross-origin images, iframes, video frames, canvas with cors-tainted content (these render blank). no permission prompt.

screen recordings (video)

an actual video stream of the captured surface, via getDisplayMedia. the user picks the surface in a native prompt: full screen, a window, or a tab. the user can pick any surface, including ones outside your app. they may capture other apps, other tabs, or their entire desktop.

desktop only. mobile safari has no api for this. requires https.

unlike sentry session replay or posthog session recording, this is a real video, not a dom mutation log. there is no per-element masking inside the video stream.

voice notes

raw audio from the user's default microphone, via getUserMedia. triggers a native mic permission prompt the first time. requires https. ambient sounds, other voices, anything within mic range will be captured.

annotations and nearbyText

clicking a dom element captures a css selector, dom path, bounding rect, classes, attributes, a subset of computed styles, and nearbyText, the visible text content within roughly 200px of the element.

nearbyText is the part to watch. if a user pins an element next to an order summary, the order total goes into the payload. if they pin a button next to "logged in as alex@example.com", the email goes into the payload.

text notes

whatever the user types. nothing else.

environment

every submission carries userAgent, language, timezone, viewport, screen size, and color scheme. sent on every submission.

metadata

only what you pass to the metadata prop. nothing implicit.

masking

remediate honors a single attribute everywhere it walks the dom:

<div data-remediate-mask>
  <p>account number: 4111-1111-1111-1111</p>
</div>

elements marked with data-remediate-mask:

  • are blacked out in screenshots before the bitmap is rendered
  • are excluded from nearbyText walks during annotation capture
  • have their attributes redacted in ElementCapture

this does not affect screen recordings. masking a real video stream is unreliable, so the only safe answer is "don't enable video on screens with sensitive data."

mask aggressively:

  • account numbers, payment info, ssns, government ids
  • email addresses and phone numbers in headers/profiles
  • internal ids that map back to a user
  • chat messages and email content
  • anything you would not email to support

defaults

remediate captures everything visible by default. it is not private-by-default.

this is intentional. the user has clicked "report a bug." they are consciously sending you what they see. but you remain responsible for what they are allowed to see. mask before you ship.

server-side handling

since you own the storage, you also own the disclosure. a defensible baseline:

  • encrypt at rest. payload json and blobs both. submissions contain pii by default.
  • set a retention window. 30, 60, 90 days, then delete. don't keep feedback forever.
  • scope access. not every engineer should be able to read every submission.
  • log who reads what. audit trail on the viewing side.
  • handle deletion requests. users can ask you to delete their feedback under gdpr or ccpa. since you own the storage, deletion is a query. make sure you can find every blob and every row by metadata.userId or whatever you key on.
  • don't forward raw payloads to third-party llms without the user's knowledge. summarize server-side first, or get explicit consent.
  • rate-limit the endpoint. nothing in the widget prevents a malicious client from posting forever.
  • validate. parse with zod or your validator of choice. don't trust the shape blindly even if it came from parseFeedback.

telling your users

remediate doesn't show a notice automatically. you should. somewhere visible the first time a user opens the widget, or in your privacy policy:

"when you submit feedback, we capture a screenshot of the page, any recording or voice note you make, and basic info about your browser. captured data is sent to our servers and used only to investigate and fix the issue you reported. we don't share it with third parties. you can request deletion at [contact link]."

adapt the copy. the goal is informed consent, not legalese.

the law

remediate is a client-side capture library. we don't host, store, or see your data. you do. that means you are the data controller for any data captured. you are responsible for compliance with gdpr, ccpa, hipaa, pci-dss, and any other regimes your users fall under.

this page is not legal advice. if you are capturing in a regulated context, talk to a lawyer.

what is not captured

  • network requests
  • console logs
  • cookies, localStorage, sessionStorage
  • canvas pixel data (annotations don't extract canvas contents)
  • contents of cross-origin iframes
  • contents of cross-origin images
  • anything that was not on screen when the user clicked capture

if you want any of these, you will do it yourself. metadata is the place.

Made by Parth Patel