# Security Zoijs is **secure by default**. The safe path is the only path you'll normally use — you have to go out of your way to do something dangerous, and several dangerous things are simply blocked. ## Threat model Untrusted data (user input, API responses, URL params, stored content) flows into your templates. The goal: that data can **never** become executable script, markup, an event handler, or a dangerous URL. The core guarantee: **dynamic values fill text and attribute *slots* only — they can never change a template's structure.** The template scanner keeps your static HTML and your `${}` values in separate channels and refuses to put a value where a tag name, attribute name, or raw-HTML sink would go. ## Safe rendering rules | What you write | What happens | Safe? | |---|---|---| | `${() => value}` in text | rendered as an **inert Text node** (escaped) | ✅ always | | `attr=${() => value}` | set via `setAttribute` (or property for `value`/`checked`) | ✅ | | URL attrs (`href`, `src`, `action`, `formaction`, `poster`, `ping`, `xlink:href`) | **scheme-checked** | ✅ unsafe schemes blocked | | `onclick=${fn}` | `addEventListener` with a **function reference** | ✅ strings ignored | ### Text is always escaped ```js html`
${() => userInput}
`; // userInput = "