This document describes Quilt's security model: what we trust, what we don't, and what you need to do to run Quilt safely in production.
┌─────────────────────────────────────────────────────────────────┐
│ Trust boundary │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Sheet │ ──────► │ Engine │ ──►│ Adapters │ │
│ │ (YAML file) │ │ (in-memory) │ │ (network) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ Trusted: author of the sheet │
│ Untrusted: anything that calls into the sheet │
└─────────────────────────────────────────────────────────────────┘
The author of a sheet is trusted. The author defines the cells, what they call, what they connect to. If the author is malicious, the sheet is malicious.
Anything that calls into the sheet (via the engine, via MCP, via the CLI) is treated as untrusted input. The engine validates context, never executes user code directly, and treats cell values as data.
- Run sheets you wrote yourself — full trust
- Run sheets from trusted authors (e.g. our examples) — full trust
- Expose a sheet via MCP stdio — safe (stdio is local IPC)
- Run sheets on a Raspberry Pi with sensor input — safe, sensors are local
- Use the CLI to inspect and run sheets — safe
- Expose a sheet via MCP over HTTP — needs auth, see below
- Multi-tenant deployment — needs cell-level permissions, see below
- Untrusted sheet sources — needs sandboxing, see below
- Program cells that call
runtime.set— can write to any cell, see below
- Don't load sheets from untrusted sources — a malicious sheet can call any API, run any program, access any sensor
- Don't expose MCP over HTTP without authentication — anyone on the network could call your cells
- Don't give program cells access to the filesystem without sandboxing — the program can read/write any file the engine can
| Area | Status | Notes |
|---|---|---|
| Schema validation | ✅ done | The parser validates cell structure |
| Caller context | ✅ done | Every call carries context |
| Type checking | ❌ not yet | Cell types are documented but not enforced |
| Capability-based permissions | ❌ not yet | CellDef.permissions is declared but ignored |
| WASM sandbox for program cells | ❌ not yet | Program cells run in the host process |
| HTTP auth for MCP | ❌ not yet | stdio only for now |
| Rate limiting | ❌ not yet | Caller has to implement |
| Audit log | getTraces() gives recent evaluations |
|
| Encrypted secrets | ❌ not yet | Use env vars |
Program cells are the most powerful — and most dangerous — cell type. They execute arbitrary JavaScript with access to the runtime. For production:
- Run the engine in a separate process or container — limits blast radius
- Use
worker_threadsorisolated-vm— true isolation - Whitelist allowed operations — reject filesystem access, network calls outside a known set
- Set resource limits — memory, CPU time, wall clock
The MVP runs program cells in the host process. This is fine for development and trusted deployments. For production, you must add sandboxing.
API cells can call any URL. To prevent abuse:
- Whitelist allowed hosts in your sheet
- Use env vars for secrets — never hardcode API keys
- Set rate limits at the network layer — e.g. with an API gateway
- Log all API calls —
getTraces()shows them
The MCP server exposes cells as tools. Anyone with MCP access can call any cell. To secure:
- stdio only by default — local IPC, no network exposure
- For HTTP transport, add authentication — bearer tokens, OAuth, etc.
- Filter cells by permission — only expose certain cells as tools
- Log every MCP call — for audit
Before loading a sheet from an untrusted source:
- Read the YAML — make sure it doesn't do anything you don't expect
- Check the
endpointfields — make sure it doesn't call unknown APIs - Check the
codefields — make sure program cells don't do dangerous things - Run in a sandboxed environment first — test in a container or VM
- WASM-based sandbox for program cells (v0.2)
- Capability-based permissions (v0.3)
- Signed sheets (v0.4) — only load sheets signed by trusted authors
- Encrypted secrets in YAML (v0.5) — don't put API keys in plain text
If you find a security issue, please email security@quilt.example.com (or open a private security advisory on GitHub).