Restore the existing short token-prefix logging behavior for agent auth failures while keeping the optional bearer-path rate-limit fix. Update tests and docs so the replacement branch reflects the intended logging policy.
Co-Authored-By: Claude <noreply@anthropic.com>
Rate-limit the optional agent bearer path after user auth resolution so mixed user/agent routes no longer leave an unthrottled PBKDF2 path. Stop logging token prefixes on agent auth failures and require a locally supplied token for backend/.env.test instead of committing one.
Update tests and docs to cover agent bearer fallback, configurable webhook signature headers, and the operator-facing security settings added by the hardening work.
Co-Authored-By: Claude <noreply@anthropic.com>
Use _env_file=None and explicit base_url so tests don't depend on
global env vars or .env file loading.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace sync redis.Redis with redis.asyncio to avoid blocking the
event loop during rate-limit checks. Make RateLimiter.is_allowed async
across both backends and update all call sites to await.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add get_client_ip() helper that inspects Forwarded and X-Forwarded-For
headers only when the direct peer is in TRUSTED_PROXIES (comma-separated
IPs/CIDRs). Replaces raw request.client.host in rate-limit and webhook
source_ip to prevent all traffic collapsing behind a reverse proxy IP.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add RedisRateLimiter using sorted-set sliding window alongside the
existing InMemoryRateLimiter. Users choose via RATE_LIMIT_BACKEND
(memory|redis) with RATE_LIMIT_REDIS_URL falling back to RQ_REDIS_URL.
Redis backend validates connectivity at startup and fails open on
transient errors during requests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The has_token boolean redaction requires coordinated frontend changes
(detail page, edit page, orval types). Revert to returning the raw
token for now; token redaction will be handled in a dedicated PR.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
A 6-character prefix of the token is standard practice for debugging
failed auth attempts and is not a security risk. Restored in both
required and optional auth paths, and removed the now-incorrect test
that asserted its absence.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
These two tests were exact subsets of the dedicated test_rate_limit.py
suite. Consolidating to a single file avoids maintenance drift.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- agent.py: Fail closed when gateway lookup returns None instead of
silently dropping the organization filter (cross-tenant board leak)
- board_webhooks.py: Read request body via streaming chunks so an
oversized payload is rejected before it is fully loaded into memory
- rate_limit.py: Add periodic sweep of expired keys to prevent
unbounded memory growth from inactive clients
- test_rate_limit.py: Add test for the new sweep behavior
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Agent token auth performed O(n) PBKDF2 operations per request with no
rate limiting, enabling CPU exhaustion attacks. Webhook ingest had no
rate limits either. Add an in-memory token-bucket rate limiter:
- Agent auth: 20 requests/minute per IP
- Webhook ingest: 60 requests/minute per IP
Includes unit tests for the rate limiter.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>