Skip to content

Security

Grimoire ships with two layers of hardening enabled by default: rate limiting on the endpoints that check credentials, and a set of security response headers. Neither requires configuration, but both can be tuned.

Auth rate limiting

The credential-checking endpoints are rate-limited per client IP to slow online password and invite-code brute-forcing:

  • /api/auth/login
  • /api/auth/setup
  • /api/auth/guest-login
  • /api/stats (API-key-guarded)

The default is 10/minute per IP; exceeding it returns HTTP 429.

VariableDefaultDescription
AUTH_RATE_LIMIT10/minuteA limits string such as 20/minute or 100/hour.
RATE_LIMIT_ENABLEDtrueSet to false to turn off auth rate limiting entirely.
TRUST_FORWARDED_FORtrueWhether to key on the X-Forwarded-For address.

Behind a reverse proxy

By default (TRUST_FORWARDED_FOR=true) the limiter keys on the left-most X-Forwarded-For address, so each real client, not the proxy, gets its own bucket. Make sure your proxy sets X-Forwarded-For.

Direct exposure

If Grimoire is exposed directly with no trusted proxy in front, set TRUST_FORWARDED_FOR=false. Otherwise a client could spoof X-Forwarded-For to sidestep the limit.

Multiple replicas

When VALKEY_URL is set, the limit counters are shared through Valkey, so the limit is enforced consistently across all workers and replicas. Without it, each process keeps its own in-memory counters. The limiter also falls back to in-memory automatically if Valkey becomes unreachable.

Security headers

Every response carries:

HeaderValue
Content-Security-PolicyScoped to what the SPA actually loads: own scripts, inline styles used by React, Google Fonts, and data:/blob: images for rendered pages. Includes frame-ancestors 'none'.
X-Content-Type-Optionsnosniff
X-Frame-OptionsDENY (matching the CSP frame-ancestors 'none')
Referrer-Policystrict-origin-when-cross-origin
Strict-Transport-SecurityEmitted only when the request is HTTPS: directly or via X-Forwarded-Proto: https from your TLS-terminating proxy, so it is never sent over plain HTTP.

These are on by default and require no configuration. If you terminate TLS at a reverse proxy, make sure it forwards X-Forwarded-Proto: https so HSTS is emitted correctly. See Reverse Proxy.

Released under the GNU GPL v3.0 License.