Skip to main content

Threat Model

What IntentText defends against, what it deliberately does not, and where the trust boundaries are. This is a public summary for security reviewers and procurement; it pairs with the Trust & Integrity Specification (the normative crypto rules) and SECURITY.md (reporting).

Assets we protect

  1. Document integrity — proof that a sealed .it document has not changed.
  2. Signer identity — proof that a specific key holder signed specific content.
  3. Authority certification — a third party (UTS) vouching for an account/entity + time.
  4. Signing keys — the Ed25519 private keys (a user's desktop identity; the UTS intermediate; the offline UTS root).

Trust boundaries

BoundaryCrosses itNotes
The user's machinenothing, for local toolscore/CLI/desktop are fully offline
Browser ↔ page (verify portal)the dropped file stays in the page100% client-side
Client ↔ UTS serviceonly the content hash + account (API key)never the document body
UTS online (intermediate) ↔ offline rootonly ICA tokens (root signs intermediates)root private key never online

Adversaries & what stops them

A document tamperer (edits a sealed/signed/certified doc)

  • Mitigation: the content hash is recomputed on verification; any change to the body breaks the seal, the signature, and any certification, surfacing the broken tier. Hashing is NFC-normalized so only visual changes count, not encoding noise — and excludes styling/comments, so restyling is not tamper. The trust band verifies before it draws (integrity gate): a tampered document renders a red "SEAL BROKEN" stamp, never a clean seal.
  • Residual: none for integrity — tampering is always detectable by verification.

A signature/certification forger

  • Mitigation: signatures are Ed25519 over the content hash; a forged sign:/certify: line with a bogus signature fails verification. A real certification copied onto different content fails (the signature binds to that content's hash). A certify: UTS line signed by any key other than the trusted UTS key verifies as untrusted.
  • Residual: a plaintext sign:/approve: line with no key:+sig: is an on-record claim only — it is not proof and the UI labels it as such.

A malicious .it document (XSS / DoS against a viewer)

  • Mitigation: rendering escapes content; embedded SVG is sanitized (script / foreignObject / SMIL / on* / javascript: refs stripped) and Mermaid is escaped; merge-data is escaped in the issued PDF/HTML. The parser caps input size (10 MB), line count, per-line length, block count, and embed depth; the desktop caps file reads (64 MB). The verify portal sandboxes the preview in an isolated <iframe>. The desktop webview runs under a Content-Security-Policy.
  • Residual: type: iframe embeds may load external URLs (clickjacking/exfil surface); treat untrusted iframes with care.

A network attacker (UTS service)

  • Mitigation: the service refuses plaintext in production (HTTPS-only behind a trusted proxy); rate limiting per key/IP; admin auth; conservative security headers. Only the content hash + account ID transit — never the document.
  • Residual: depends on correct operator deployment (TLS termination, secret manager).

A database thief (UTS service)

  • Mitigation: the signing key is stored only as an AES-256-GCM envelope whose KEK lives in a secret manager (not the DB); API keys are stored only as SHA-256 hashes. A DB dump alone cannot forge certifications or recover usable keys.

A compromised UTS signing key

  • Mitigation: revocation — an operator can revoke a content hash or an entire signing key; /verify and the published /revocations list reflect it. The offline root can mint a fresh intermediate; the root private key is never online. (See INCIDENT-RESPONSE runbook.)
  • Residual / in progress: offline verifiers (verify portal, desktop) do not yet auto-pin the revocation list, and the list is not yet signed for offline tamper-evidence — both are tracked follow-ups. Until then, revocation is enforced at the service /verify.

A thief of a user's desktop signing key

  • Mitigation: the desktop private key is stored in the OS keychain (macOS Keychain / Windows Credential Manager), never in a file or the document.
  • Residual: an attacker with full control of an unlocked machine can use the key — as with any local credential. Code-signing + a keychain-access entitlement (planned) tighten this further.

Non-goals (explicitly out of scope)

  • Confidentiality of document contents at rest.it is plaintext; encrypt the storage/transport layer if needed.
  • Defending an already-compromised OS or a malicious local user with the keychain unlocked.
  • Proving a plaintext approval — only cryptographic signatures/certifications prove identity; plaintext sign:/approve: are records of intent.
  • Anti-coercion — we prove what was signed and by which key, not that the signer acted freely.

Privacy posture

No telemetry anywhere. The verify portal and all local tools make no network calls with document content. The only data leaving the machine is the SHA-256 hash sent to the UTS service when a user chooses to certify. See PRIVACY.md.