Security model
flootypst executes Typst code supplied by the client. The threat model assumes the template author is untrusted.
What the compiler can and cannot do
| Capability | Status |
|---|---|
| Read files inside the request bundle | allowed |
Read host filesystem (/etc, etc.) | denied — virtual World |
Import @preview/... packages | denied — package resolver rejects everything |
| Network access during compile | none — compiler runs in a sandboxed child without it |
| Outlive the request | denied — PR_SET_PDEATHSIG, kill_on_drop, SIGKILL on timeout |
The Typst compiler runs in a child process (flootypst worker) so it can be hard-killed on timeout and so a runaway template cannot pin a parent thread.
SSRF protection (URL mode)
The URL-mode endpoint fetches caller-supplied URLs. Defenses:
- HTTPS-only by default. Non-HTTPS schemes are rejected at the URL-validation step (
require_https=true). - Custom DNS resolver. Resolution happens inside flootypst; any result that is loopback, private, link-local, multicast, broadcast, IPv6 ULA / link-local, the GCE/EC2 metadata IP
169.254.169.254, carrier-grade NAT, or reserved is dropped. If the entire resolution set is unsafe, the request is refused at connect time. This closes the typical DNS-rebinding window. - Optional host allowlist.
FLOOTYPST_HOST_ALLOWLISTaccepts a comma-separated list of patterns.*.googleapis.comis supported. When set, any URL whose host doesn’t match is rejected before DNS is even attempted. - No redirect following. A 3xx from an allowed host cannot bounce the request to a forbidden one.
- Size caps. Fetched bodies are streamed and aborted when they exceed
FLOOTYPST_MAX_FETCH_BYTES.
A typical production config locks the allowlist down to your storage host(s):
FLOOTYPST_HOST_ALLOWLIST=storage.googleapis.com
Resource limits
| Limit | Env var | Default | What happens on hit |
|---|---|---|---|
| Multipart body size | FLOOTYPST_MAX_BODY_BYTES | 32 MiB | 413 |
| Per-URL fetch size | FLOOTYPST_MAX_FETCH_BYTES | 32 MiB | 400 (“too large”) |
| Output PDF size | FLOOTYPST_MAX_OUTPUT_BYTES | 64 MiB | 413 |
| Compile time | FLOOTYPST_COMPILE_TIMEOUT_SECS | 10 s | 408 (worker SIGKILLed) |
| Fetch time | FLOOTYPST_FETCH_TIMEOUT_SECS | 15 s | 408 |
| Upload time | FLOOTYPST_UPLOAD_TIMEOUT_SECS | 30 s | 408 |
| Concurrent compiles | FLOOTYPST_MAX_CONCURRENT_COMPILES | host CPU count | 503 |
What is not included
- No auth on the API itself. flootypst is meant to sit behind your own gateway / mTLS / API-key layer.
- No rate limiting beyond the concurrency cap. Rate-limit upstream.
- No audit log of which templates rendered what. The service is stateless.