# Security model

> What the HTML Clay server protects, how a trusted folder and a document program differ, the known limitations, and how to report a problem.

Source: https://htmlclay.com/docs/security/

HTML Clay only saves files you chose: a file you opened yourself, or a file inside a folder you have trusted. A page can only read inside the folder you opened it from; anything outside that pauses and asks. [`SECURITY.md`](SECURITY.md) explains the model, what each protection covers, and the current known limitations.

## The exact safety boundary

**A page saves only into its own file by default.** Inside a trusted folder, HTML Clay files can change other files in that folder, including files added later. Untrust the folder and that permission ends.

**Document programs require separate approval.** An approved program runs with your account's permissions and can read or change files your account can access. The file server's restrictions do not sandbox that program. Only approve programs you trust.

**The file server does not serve files outside your home folder.** It also refuses dotfiles, its settings and its backups. A missing file and a refused file return the same response.

**The file server runs locally.** HTML Clay checks for a new version at startup without sending file contents. AI editing sends selected HTML, your request and any included context to your local agent, which may contact its model provider. Other approved programs can also make network requests.

The full model, including the risks it accepts, is written down in [SECURITY.md](https://github.com/panphora/htmlclay/blob/main/SECURITY.md).

## Two security boundaries

HTML Clay has two different security boundaries. Keep them separate:

1. **The HTML Clay server limits what a page can read and save through HTML Clay.** A page normally changes only itself. A trusted folder is the exception: every HTML Clay file in it can read named files in the folder and can acquire the save capability for every other HTML Clay file in it.
2. **A registered helper program runs as you.** It has your access to files, processes, environment variables, and the network. HTML Clay decides whether to start the program. It does not sandbox the program or constrain what the program does after it starts.

A document is not the program being approved. A document asks for a helper by a short name. You select the program when it is registered, and the stored document decision points to that program's local ID. HTML Clay does not let the document supply an executable path or command line, but the document supplies the request on the program's standard input. The program must treat every request as hostile input.

## What HTML Clay itself protects

These protections apply to requests handled by HTML Clay. They are not a sandbox around registered programs.

- **Only files you choose can be saved through HTML Clay.** That choice takes two forms: a file you open yourself, and any HTML Clay file inside a folder you have trusted. Everything else, including a file reached by a link, an iframe, or a typed URL, is served read only and never gets a save token.
- **A page can only read through HTML Clay inside the folder it was opened from.** A request outside that folder pauses and asks you, in a dialog HTML Clay draws itself, to widen reads to one named folder.
- **Each project gets its own origin.** HTML Clay listens on one local port and serves each trusted folder at its own hostname, such as `htmlclay.localhost`. Each folder containing an opened loose file, and each loose file in your home folder, also gets its own hostname. The browser therefore treats unrelated projects as different sites, with separate storage.
- **Save tokens ride only on real navigations.** A silent background `fetch()` of another file receives no save token. Getting a sibling's token requires a visible top level document navigation.
- **The read only banner cannot select another file.** Its single use code resolves on the server to the exact file that was served. The code expires after ten minutes and dies on first use.
- **Always refused, trusted or not:** anything outside your home folder, dotfiles and dot-directories such as `.env`, `.git`, and `.ssh`, HTML Clay's own settings and version history, and directory listings.
- **Other websites cannot drive the server.** It listens only on loopback, validates the `Host` header, rejects cross site browser requests, and requires same origin browser attestation on routes that save, restore, upload, relay live updates, or change folder permissions.
- **Permission prompts are native.** Page content cannot draw, restyle, or click them.
- **Reads are judged by the file actually opened.** HTML Clay checks the real path reported for the open handle, so swapping a symlink during a request cannot redirect the read into its own settings or version history.
- **A refused read reveals no target path.** Out of scope denials use one fixed response and are decided before checking whether the requested file exists.
- **JSON data routes use the same read checks.** The `?data=` and `/_/api/` routes cannot reach a file an ordinary request could not, never supply a save token, and strip any token that was written to disk.
- **JSON writes are content only and follow save rules.** `POST /_/api/` writes only to a file HTML Clay could already save: one you opened, or an HTML Clay file in a trusted folder. A browser page must present that file's own save token, so a silent background `fetch()` still cannot write a sibling. The write cannot add script: event handlers, `javascript:`, `vbscript:` and `data:` URLs, HTML through `@innerHTML` or `@outerHTML`, and anything inside `<script>`, `<style>` or `<template>` are refused, and a refused write writes nothing. A local program needs no token, as it could already write the file directly.

## Known limitations

1. **A trusted folder trusts everything in it.** A hostile file can read that tree, send data away, overwrite sibling HTML Clay files, and reach a sibling's approved helper after acquiring its token through a visible navigation.
2. **A page can steer a read permission prompt.** It chooses the requested path. Read the full path before allowing it. Page steered trust refuses your main personal folders and everything inside them. You can still choose a folder deliberately from the tray.
3. **The Windows prompts still need native verification.** They are covered by tests and fail closed when a dialog process fails, but they have not run on Windows for this release. The Linux zenity and kdialog prompts were exercised under Xvfb.
4. **Mixed capitalization across mounted filesystems is not fully handled.** HTML Clay detects the rule used by the home filesystem. A mounted filesystem with the opposite rule can still be compared incorrectly.
5. **Unicode equivalent folder names can briefly produce duplicate trusted entries.** Load normalization merges entries that the operating system reports as the same directory, but two equivalent spellings added during one run can coexist until restart. Remove every duplicate row if you see one.
6. **kdialog shows program and folder choices as a list.** With kdialog and no zenity, the permission prompts are radiolists whose first row is Deny, and program management's first row is No change, because kdialog's Return always picks the highlighted row.
7. **Hard links are not a boundary against a local attacker.** Someone who can already create hard links inside your home folder can link files into an allowed tree. That attacker already has local file access.
8. **Inside a folder you allowed or trusted, a page can tell which files exist.** That follows from read access.
9. **A hostile page can cause repeated prompts for invented folders.** Allowing an invented folder grants nothing. Denying suppresses that branch for the session, but the page can invent other names.
10. **A fresh helper subscription may not recover a missed outcome.** Terminal result retention is bounded. Do not automatically repeat a helper request merely because its result was lost, since the program may already have completed side effects.

## Reporting a problem

Email david@storylog.com with what you found and how to reproduce it. Please do not open a public issue for a security problem until it is fixed.
