# Security Policy > **In plain English:** SearchBox runs entirely on your own computer. It > doesn't send your files or activity anywhere, has no ads or tracking, and > works offline. Anything you put in the **vault** is encrypted with your > password — strong enough that the files can't be read without it. During > setup, you'll download a **recovery key** — save it somewhere safe. If you > forget your password, the recovery key lets you reset it and keep accessing > your vault. Without the recovery key, vault files **cannot** be recovered. > > The rest of this page is the technical detail and how to report a security > issue. ## Supported versions | Version | Supported | |---------|-----------| | 0.3.x | ✅ Current release (Rust rewrite) | | ≤ 2.x | ❌ Python-era, unsupported | ## Architecture SearchBox runs entirely on the user's own machine. It opens no outbound network connections by default — Meilisearch runs as a local sidecar and Ollama is only contacted when the user explicitly enables it. Both the app's web server and the Meilisearch sidecar bind to loopback (`127.0.0.1`) only, so neither the UI/API nor the full-text index (which holds the extracted text of every indexed file) is reachable from the local network. Set `SEARCHBOX_HOST=0.0.0.0` to deliberately opt into LAN access. The Meilisearch master key is a private, per-install random value generated on first run — never a shared default. ### Data privacy - All processing happens on your infrastructure. - No telemetry, no analytics, no phone-home. ### Encryption - **Vault:** AES-256-GCM with a per-file Data-Encryption Key (DEK), 12-byte random nonce, authenticated tag. - **Key derivation:** PBKDF2-HMAC-SHA256, 600 000 iterations, random 16-byte salt stored once in `vault_config`. - **KEK lifecycle:** derived from the admin password at login and held only in process memory, sealed under a per-process key that is regenerated on each start. Only the *sealed* form is written to the session store, so a copied data directory never yields a usable key. The vault re-locks on restart; Settings → Vault Security shows an **Unlock** prompt to re-derive the key from your password without logging out. - **DEK wrapping:** each file's DEK is AES-256-GCM-wrapped under the KEK; the wrapped blob is stored in `encrypted_files`. ### Authentication - Passwords hashed with **argon2id** via the `argon2` crate. - **Login is rate-limited:** repeated failures lock an account's logins (and the vault-unlock endpoint) for a cooldown that grows with each failure, slowing online guessing. A successful login clears it. - Sessions managed by `tower-sessions` with the SQLite store. - Cookies are `HttpOnly`, `SameSite=Lax`; flip `with_secure(true)` in `src/main.rs` when serving over HTTPS. - **qBittorrent password** is encrypted at rest (AES-256-GCM under a per-install key kept outside the database), so a leaked database alone can't reveal it. ### Input validation - Parameterised SQLx queries everywhere — no raw string concatenation in SQL. - `url_for` and file-serving paths are rooted at known directories; no path traversal entry points exposed. - SSRF guard on Ollama URL configuration — only `http://` / `https://` schemes accepted. - Meilisearch configuration validates the binary path (must be a file, basename must contain `meilisearch`). ### CSRF State-changing endpoints require a CSRF token. A 32-byte random token is generated per session and surfaced to the browser via a `` tag and hidden form fields. Requests echo it back through the `X-CSRFToken` header (JSON/`fetch` routes) or a `csrf_token` form field (login/setup); the server compares it against the session token in constant time and rejects mismatches with `403`. This sits on top of `HttpOnly`, `SameSite=Lax` session cookies. ### Updates The opt-in in-app updater downloads the new MSI over TLS from GitHub Releases and verifies its SHA-256 against the published `.sha256` sidecar before running the installer, refusing on mismatch. This is an integrity check — installers are intentionally unsigned (no paid certificate), so TLS plus the checksum, not a code signature, establish trust. ### Dependency auditing CI runs `cargo audit` against the [RustSec](https://rustsec.org) advisory database on every push and pull request, failing on security vulnerabilities. Known-unreachable transitive advisories are documented and ignored in `.cargo/audit.toml`. ## Reporting a vulnerability **Do NOT open a public GitHub issue.** Email `security@sourcebox.dev` with a description of the issue, reproduction steps, and potential impact. Include your preferred contact channel. Expected timeline: 48-hour acknowledgement, 30-day target fix, 90-day maximum disclosure window. We credit reporters in the release notes unless asked not to. ### Out of scope - Denial-of-service attacks - Social engineering - Physical access - Bugs in upstream dependencies (report those upstream) ## Dependencies worth watching - **Rust crates:** monitor [rustsec.org](https://rustsec.org) advisories for `axum`, `tokio`, `sqlx`, `tower-sessions`, `reqwest`, `argon2`, `aes-gcm`, `pdf-extract`, `scraper`. - **Meilisearch:** runs as a sidecar. Track its releases. - **Ollama (optional):** only contacted when configured. ## Deployment hardening ### Bind address SearchBox binds `127.0.0.1` by default. Only set `SEARCHBOX_HOST=0.0.0.0` if you intend to expose it on a network — and if you do, put it behind a reverse proxy that adds TLS. The Meilisearch master key is generated automatically (random, per-install); you don't need to set one. ### Terminate TLS upstream Put SearchBox behind Caddy / nginx with Let's Encrypt. Don't serve port 8080 directly to the public internet. ### Restrict index sources In Docker, only mount the directories you want indexed, read-only: ```yaml volumes: - /home/me/Documents:/home/me/Documents:ro ``` ### Vault password - Choose a strong admin password — it's the only thing between an attacker with filesystem access and the vault contents. - **Save your recovery key.** During setup, SearchBox generates a random 256-bit recovery key and wraps it under your password-derived key. Store this recovery key somewhere safe (password manager, encrypted USB, safe). - **Lost password + lost recovery key = lost vault.** The recovery key is the only way to reset your password. Without it, vault files cannot be recovered. - **Recovery key lifecycle:** The recovery key is generated once at setup. It can be regenerated at any time from Settings (which invalidates the old one). The recovery key is never stored on disk — only a version wrapped under your password-derived KEK. --- **Last updated:** June 2026 (v0.3.17 — loopback binding, sealed in-memory KEK, login rate-limiting, encrypted qBittorrent password, update checksums, CI audit)