security

Read it before you run it.

Zidl is a script tag inside your app, which means it deserves the same scrutiny as any dependency. This page is what to check, and how to check it yourself.

Start with the honest version

A script running on your origin can, in principle, do anything your own code can do — read the DOM, read cookies your app can read, and make requests as your user. That is true of Zidl and it is true of every analytics tag, session recorder and feedback widget already on the page. Any vendor who tells you their script is incapable of harm is telling you something that is not true of how browsers work.

So the question worth asking is not "can it?" but "can I check what it does, and can it change under me afterwards?" Those two have concrete answers, and the rest of this page is them.

Check it yourself

The tag is one file at a public URL. There is no package, no post-install script, no build step and no transitive dependency tree — which means the entire attack surface is a file you can read in an afternoon.

curl -s https://cdn.zidl.io/embed.js > embed.js

Read it, diff it, run it through whatever review your team uses, and keep the copy. The loader is dependency-free ES5 and deliberately small — the heavy drawing canvas is fetched only when someone actually enters draw mode. See the developer notes for the architecture behind that.

Pin the version you reviewed

Every release is a frozen folder on the CDN. Releases are never edited in place, so the file you reviewed is byte-for-byte the file that runs — a new release is a new path, not new contents at an old one.

<script src="https://cdn.zidl.io/v/<version>/embed.js"></script>

Point at a version rather than the rolling loader and nothing changes under you until you change it. This is also what makes a rollback trivial on our side: repointing one small file rather than redeploying anything.

What leaves the browser, and when

This is the section a reviewer actually cares about, so it is worth being exact rather than reassuring. Zidl is local-first: work lives in IndexedDB in the browser, and nothing is transmitted until someone publishes a report.

MomentWhat crosses the network
The tag loadsThe script and its assets are fetched from the CDN. Nothing about your page is sent.
Someone clicks around your appNothing. The step buffer is held in the browser. It is not streamed anywhere, and if the tab closes it is gone.
Someone starts a reportStill nothing. The pin, the annotation and the trimmed steps are assembled locally.
Someone publishesThe report is sent to your board: the element and its source location, the route, the surface, the confirmed steps, and what the reporter typed into the title and description.

The consequence worth stating plainly: a published report is data your team chose to send, and it can contain whatever was on screen when it was filed. If your staging environment holds real customer records, a report filed against that screen can carry them. That is a property of any bug-reporting tool, and the control for it is the same as always — do not put production data in staging.

What it never captures

  • Passwords. The step recorder never records what was typed into a password field. The field is recorded as having been filled; the contents are not.
  • Images of your interface. Annotations are vector data rendered over the real product. No screenshot of your UI is copied to a server, which also means no accidental capture of whatever was alongside it on screen.
  • URL parameter values. Route grouping keeps parameter names and drops their values — /orders?tab,id. The screen is identified; the order number never enters the grouping.
  • Console and network traffic. Zidl reads neither. It is a real limitation of the product, and it is also a smaller blast radius than tools that do — see the Marker.io comparison, which is honest about the trade.

It is off in production by default

The tag names the hostnames it is allowed to run on. Ship the same markup to every environment; on any host you did not list, the loader does nothing.

index.html
<script
  src="https://cdn.zidl.io/embed.js"
  data-hosts="localhost,staging.yourapp.com"
  data-zidl-key="zk_your_key"
></script>

This is a deliberate default rather than a setting you have to remember. It also means the reviewed blast radius is your staging environment, not your production traffic — and source detection wants a development build anyway, so production is not where this product belongs.

How it is isolated from your app

  • Shadow DOM, both directions. The entire UI lives in a shadow root. No style of yours collides with any style of ours, and none of ours leaks into your page.
  • Nothing in your bundle. It is not imported, not compiled and not part of your build output. Removing it is deleting one line, after which no trace of it remains.
  • No global mutation you depend on. The loader runs standalone ES5 before anything else and does not require you to wrap a component, install a package, or change a build config.

For the person doing the review

If you have been handed this page and asked whether the tag is acceptable, this is the shortest path to an answer you can defend.

  • Fetch the file and read it. It is one dependency-free file, not a tree.
  • Pin the version you read, so what you approved is what ships.
  • Load your staging app with the tag and watch the network tab through a full report — idle, then filing, then publishing. Confirm the table above matches what you see.
  • Confirm data-hosts does not name a production hostname.
  • Decide separately whether your staging data is acceptable to have inside a filed report. That question is about your environment, not about Zidl.