Security overview
Clausery's security model is short because its architecture is short: there is no server side. This page is written for the person at your firm who has to sign off on new tools.
Architecture
- The product is a set of static files (HTML, CSS, JavaScript) served from a web host. There is no backend, database, API or account system operated by us.
- All processing (reading .docx templates, evaluating answers, generating documents, encrypting storage) happens in the browser's JavaScript engine.
- Data at rest is in the browser's IndexedDB, scoped to the site origin and the browser profile.
- The app only requests its own static files (code, sample templates, the intake-form runtime) from the site that serves it; it never uploads or posts anything, and it makes no request to any third party. The service worker caches those files for offline use and only handles same-origin requests.
What we can see
Nothing about your documents. The host serving the static files (GitHub Pages for the public instance) sees ordinary web-server traffic: the IP address and browser of whoever loads the app. The app has no analytics, cookies, tracking pixels or third-party scripts; the marketing website only counts anonymous page views (see the privacy policy). Fonts are system fonts.
Cryptography
- Encrypted workspace: AES-256-GCM with a random 96-bit nonce per record; key derived from the passphrase with PBKDF2-SHA256 (600,000 iterations, 128-bit random salt). Implemented with the browser's WebCrypto API only.
- License keys: Ed25519 signatures over the license payload, verified with a public key embedded in the app. No license server.
Browser hardening
- Content Security Policy:
default-src 'self', no inline scripts, no remote scripts,connect-src 'self' https://api.lemonsqueezy.com(the second origin is used only to check a license key bought online),object-src 'none',form-action 'none'. - Referrer policy
no-referrerin the app. The app page is markednoindex. - Exported intake forms carry a CSP of
default-src 'none'with inline-only script and style, so they cannot make network requests even when hosted. - Expressions in templates are evaluated by a purpose-built interpreter, never by
eval; identifiers resolve only against the answers object.
Threat model
| Threat | Position |
|---|---|
| Breach of the vendor | Not applicable: we hold no customer data. |
| Interception in transit | Not applicable to documents: they are never transmitted. The app itself is served over HTTPS. |
| Compromised or shared device | The primary risk. Mitigations: encrypted workspace with auto-lock, backups stored on managed storage, standard device security. |
| Malicious template | A .docx is parsed as XML by an open-source library; no macros run. Templates cannot execute code or make requests. |
| Supply chain (the app's code) | Dependencies are pinned and bundled into the repository; the deploy is the repository content. No CDN scripts at runtime. Self-hosting lets you freeze a reviewed version. |
Verify it
- Open the app, then open the browser's developer tools → Network. Import a template, draft and generate. Every request is a GET for one of Clausery's own files on the same site (for example
samples/…docxwhen you pick a sample); none carries your data, and none goes to another domain. After the app is installed these are answered by the service worker cache. - Disconnect from the network. Everything continues to work.
- Read the source: it is served unminified except for two built files: the bundled document library (
vendor/docs.js, upstream versions listed in Settings → About) and the intake-form runtime (vendor/intake-runtime.js, built fromsrc/intake/runtime.jsand the app's own modules), which is what exported intake forms contain.
Reporting a vulnerability
Report it privately with GitHub's private vulnerability reporting, not in a public issue. We aim to acknowledge within two business days. Please do not test against other people's deployments. The full policy is in SECURITY.md.