Watermark verifier

Paste a protected JavaScript file. If it carries a JSO watermark, this page extracts the embedded tag. Supply the HMAC key (or set it in JSO_WATERMARK_KEY in your own tooling) to validate the signature. Everything runs in your browser via SubtleCrypto. Nothing leaves the page — no upload, no JSO involvement, no server round-trip. Open DevTools · Network and confirm.

Both fields stay client-side. The key is held in DOM state only and never serialized off-page.

Paste a protected file and click Verify.

Input · protected JavaScript

Paste up to ~5 MB

Output · parsed marker

Awaiting input
// Parsed marker fields appear here after Verify is clicked.

What this verifies

  • Marker presence: scans for the /*! __jso_watermark_v1 */ block at any position in the file.
  • Tag readability: decodes the base64url tag back to its plaintext form (UTF-8).
  • Signature validity: when a key is supplied, recomputes HMAC-SHA256(key, tag) and compares against the embedded signature in constant time.

Identical semantics to jso-protector --verify-watermark. The wire format is documented at WireFormat.aspx and the Node + Python + .NET clients all share the same regex and HMAC rules — this page is the fourth reference implementation, written in vanilla browser JS.

Why client-side?

A watermark verifier you upload your protected files to is a verifier that can lie about the result. By doing the entire HMAC check in your browser via SubtleCrypto.sign(), the trust boundary is your browser process, not our infrastructure. This page sends zero bytes off your machine: open DevTools · Network before clicking Verify and confirm.

Next steps

  • Bulk-scan a directory tree: npx jso-protector --scan-watermarks dist/ --watermark-key $KEY
  • Stamp during build: npx jso-protector --watermark $TAG --watermark-key $KEY
  • Pair with signed release attestations for end-to-end build provenance.