Security

How Pressa protects your data and documents at every step of the compilation pipeline.

Ephemeral by Design

Pressa does not permanently store your documents. LaTeX source code is deleted immediately after compilation - it never persists on disk beyond the compilation process itself. The compiled PDF is stored temporarily and made available via a signed URL that expires after 24 hours. After expiry, the PDF is deleted. There is no document archive, no browsing history, and no way to retrieve expired files.

Per-Job Container Isolation

Every compile spawns its own ephemeral Docker container. The container runs the LaTeX compiler, writes the PDF to a workspace mounted from a unique per-job directory, and is destroyed when the compile finishes. No state persists between jobs. Each container has its own cgroup, so resource limits apply per job, not across the whole pipeline:

  • Memory cap (768 MB) - hard kill via the kernel OOM killer if exceeded
  • CPU cap (1.0 vCPU) - cgroup CPU quota limits one job's share of host CPU
  • PID cap (256 processes) - blocks fork-bomb-style payloads in milliseconds
  • --network=none - the container has no network interface, cannot make outbound connections
  • --read-only root filesystem with separate tmpfs mounts for /tmp (400 MB) and the home directory (50 MB)
  • --cap-drop=ALL and --security-opt=no-new-privileges - the container has no Linux capabilities and cannot escalate
  • -no-shell-escape flag prevents LaTeX from executing arbitrary shell commands
  • Wall-clock timeout per plan (15s Free, 30s Starter, 60s Pro, 120s Business). A Ruby watchdog sends SIGKILL via the Docker daemon if the container exceeds it.
  • Each job gets a unique UUID-named workspace directory, cleaned up immediately after compilation
  • Compiler whitelist: only pdflatex, xelatex, and lualatex (the latter on Pro and Business plans only) are accepted
  • -interaction=nonstopmode and -halt-on-error prevent interactive prompts

Input Validation

LaTeX is a powerful typesetting language, which also makes it a known attack vector. Unrestricted LaTeX compilation can read arbitrary files, execute shell commands, and cause denial of service. Pressa validates every request before compilation begins:

  • Per-plan input size limits - 30 KB on Free, 100 KB on Starter, 300 KB on Pro, 1 MB on Business; oversized requests are rejected before compilation begins
  • Compiler whitelist with plan gating - only pdflatex, xelatex, and lualatex are accepted; lualatex requires Pro or Business; all other values are rejected
  • Shell execution disabled - the -no-shell-escape flag blocks \write18 and similar commands
  • Per-plan compile timeout - 15 seconds on Free, scaling up to 120 seconds on Business; runaway compiles get SIGKILL via the Docker daemon
  • Job ID validation - UUIDs are validated against a strict regex pattern to prevent directory traversal

API Key Security

API keys are the primary authentication mechanism for the Pressa API. We treat them as sensitive credentials:

  • SHA-256 hashed storage - raw API tokens are never stored in the database; only their SHA-256 hash is persisted
  • One-time display - the raw token is shown exactly once at creation and cannot be retrieved again
  • pressa_ prefix - makes keys identifiable in secret scanners (GitHub, GitGuardian, etc.)
  • Instant revocation - compromised keys can be revoked immediately from the dashboard
  • Usage tracking - each key tracks request count and last-used timestamp for auditing

Account Security

User accounts are protected by multiple defensive layers:

  • Account lockout - accounts are locked after 5 failed login attempts and automatically unlock after 30 minutes
  • Cloudflare Turnstile - bot protection on login, registration, and password reset forms
  • Password requirements - minimum 8 characters, maximum 128 characters

Rate Limiting

All endpoints are protected by Rack::Attack rate limiting with per-IP tracking:

  • Compile API - 10 requests/minute (free), 60 requests/minute (Pro), per IP
  • General API - 100 requests/minute per IP across all API endpoints
  • Login throttling - 5 attempts per 20 seconds, tracked by both IP and email
  • Registration - 3 attempts per hour per IP
  • Password resets - 3 per hour per email, 5 per hour per IP

Throttled requests receive a 429 response with a Retry-After header.

Signed Download URLs

Generated PDFs are not publicly accessible. Each download URL contains an HMAC-SHA256 signature derived from the job ID and expiration timestamp, validated server-side on every request. Without a valid signature, the PDF cannot be retrieved. URLs expire after 24 hours, after which the PDF is permanently deleted.

Saved Template Storage

Users on paid plans may save LaTeX templates to their account for reuse. Unlike one-off compilations, template content persists in our database. We apply the same defensive layers:

  • Per-user access control - templates belong to a single user and are only retrievable via API keys owned by that user
  • 500 KB template size limit - the persisted template body itself is capped at 500 KB; at compile time the per-plan source size limit also applies
  • Same compilation safeguards - when a template is used for compilation, no-shell-escape, compiler whitelist, per-plan timeout, and per-job container limits all apply
  • Encrypted database backups - all database backups containing template content are encrypted at rest
  • Immediate deletion - templates are permanently deleted when you remove them or close your account

Encryption in Transit

All communication with the Pressa API is encrypted via HTTPS/TLS. This includes LaTeX source code uploads, PDF downloads, API key authentication, and all dashboard interactions. Plain HTTP connections are rejected.

What the CLI Sends

The Pressa CLI sends only what is needed for compilation:

  • Your LaTeX source code (the .tex file contents)
  • Your chosen compiler (pdflatex, xelatex, or lualatex)
  • Your API key (for authentication)

No telemetry, no file system scanning, no environment variables, no metadata beyond what is listed above.

MCP Server

The Pressa MCP server is a thin wrapper around the Pressa API. It runs locally inside your AI assistant (Claude, Cursor, etc.) and does not store any data on disk. It passes your LaTeX source to the API, receives the signed PDF URL, and returns it to your assistant. No local caching, no logs, no persistent state.

Open Source Transparency

Both the CLI and the MCP server are fully open source. You can audit every line of code that runs on your machine:

npm Provenance

All npm packages published by Pressa include provenance attestations. This cryptographically links each published package to its source commit and build workflow on GitHub Actions, so you can verify that the code you install matches the code in the repository.

Reporting Security Issues

If you discover a security vulnerability, please report it responsibly via email. Do not open a public GitHub issue for security concerns.

We aim to acknowledge reports within 48 hours and will work with you to understand and resolve the issue before any public disclosure.