Security hardening: add SECURITY.md + fix three MEDIUM findingsVerified
Adds a SECURITY.md tailored to Usher (pre-1.0 OpenID Provider library): supported versions, private reporting, and an explicit in-scope / integrator-responsibility boundary. Fixes three MEDIUM issues surfaced by an in-session security triage: * Login-throttle bypass (CWE-348/CWE-770): handle-authorize keyed the per-IP rate limit on hunchentoot:real-remote-addr, which returns the client-supplied X-Forwarded-For header. With in-process TLS the header is spoofable, so an attacker could rotate it per request to evade the throttle and its Argon2i CPU/memory cap. Add :trust-forwarded-for (default off) and a client-ip helper that uses the real socket peer unless a trusted proxy is configured. * Signing keys at rest (CWE-312/CWE-522): save-signing-keys wrote the RSA private key as plaintext JSON with default (world-readable) perms, contradicting the design's key-at-rest requirement. Always create the file mode 0600, and when :key-encryption-key is set (passphrase/octets from env/KMS, never the DB) encrypt the material with AES-256-GCM, key derived via PBKDF2-SHA256. Plaintext files still load; enabling a KEK re-encrypts on next save. * Reset/verify tokens never expired (CWE-640/CWE-613): password-reset and email-verification tokens had no expiry, so a leaked link stayed valid indefinitely. Embed an expiry in the stored credential value (no store schema change) via issue-cred-token/consume-cred-token; add :pw-reset-ttl (1h) and :email-verify-ttl (24h). Secrets remain stored hashed and compared in constant time; single-use semantics preserved. Full build and the 199-check test suite pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By:
Claude Opus 4.8 (1M context) <noreply@anthropic.com>