Hardening
Rowbird holds credentials to your databases and sends data out of them, so treat it like any system with production access. Most protections are on by default; this page lists them and the few settings that are yours to choose.
Checklist
- [ ] Serve it over HTTPS and set
ROWBIRD_BASE_URLto thehttps://URL. - [ ] Set
ROWBIRD_SETUP_TOKENbefore the first start on a reachable server. - [ ] Provide the master key from a secret (
ROWBIRD_MASTER_KEY_FILE) and keep a copy elsewhere. - [ ] Give each connection a database login that can only read, limited to the tables it needs.
- [ ] Set
ROWBIRD_TRUSTED_PROXIESto your proxy, and only your proxy. - [ ] Require 2FA for everyone, or use OIDC with your provider's 2FA.
- [ ] Protect
/metricswithROWBIRD_METRICS_TOKENif it is reachable from outside. - [ ] Consider
ROWBIRD_NETWORK_POLICY=block-private(below). - [ ] Schedule backups, upload them off the server, and test a restore.
Your databases
- Queries run in read-only transactions where the database supports it, with a server-side timeout and a row limit per connection.
- One statement per query unless the connection explicitly allows more (off by default). The check ignores literals and comments. SQL Server does not need
;between statements, so there the read-only login is what really protects you. - Parameters are always bound by the driver, never pasted into SQL.
- Rowbird warns when a connection's login can write.
- SQLite connections can only open files under
ROWBIRD_SQLITE_DIRS, read-only, and never Rowbird's own database. - SSH tunnels pin the server's host key on the first connection; a changed key is refused.
Secrets
Credentials are encrypted with AES-256-GCM under the master key and never returned by the API (it answers "configured": true). They are kept out of logs, error messages, exports (which write ${env:...} placeholders) and notifications.
Network policy
With ROWBIRD_NETWORK_POLICY=block-private, connections, channels (HTTP and SMTP) and AI providers cannot reach private (RFC 1918), loopback, link-local and cloud metadata addresses (169.254.169.254), IPv6 included. DNS is resolved once and the resolved address is checked, so a name cannot switch to a private address later. Use it when editors or admins should not be able to probe your internal network through Rowbird. It is open by default because most self-hosted databases live on private networks.
What Rowbird sends out
- Data goes only to the channels you configure.
- Files in messages: HTML is escaped, and CSV and Excel cells starting with
=,+,-,@, a tab or a carriage return are neutralized against formula injection. - Links are 256-bit random tokens stored as hashes, with an expiry (1 hour to 90 days), optional sign-in, revocation and a download log.
- Webhooks are signed with HMAC-SHA256; see Webhook payloads.
- AI providers receive the request and the database schema, never rows; excluded tables are left out entirely. The assistant is off until an admin configures it.
- No telemetry. The only call Rowbird makes on its own is the daily update check to
api.github.com, which you can turn off.
The web application
Strict Content Security Policy, X-Frame-Options: DENY, HSTS over HTTPS, HttpOnly and SameSite=Lax cookies, CSRF tokens on state-changing requests, and no CORS. Every data access is scoped in the storage layer and every API operation declares the role and scope it needs.
Security log
Sign-ins, 2FA and passkey changes, OIDC links, API keys, user and role changes, connection and channel changes, settings, imports and key rotations are recorded in Settings > Security for 365 days.
Reporting a vulnerability
Please write to security@rowbird.dev or use GitHub's private vulnerability reporting. See SECURITY.md.