Commit Graph

82 Commits

Author SHA1 Message Date
Abhimanyu Saharan
6d2ff60a82 fix(security): Stop logging raw trusted proxy entries 2026-03-07 23:47:00 +05:30
Abhimanyu Saharan
46bc9a02c6 fix(security): Keep short agent token prefixes in logs
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>
2026-03-07 23:43:32 +05:30
Abhimanyu Saharan
fb8a932923 fix(security): Close review follow-up gaps
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>
2026-03-07 23:40:50 +05:30
Hugh Brown
e80cf9f3c8 fix: suppress mypy no-untyped-call for redis.asyncio.from_url
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:35:10 +05:30
Hugh Brown
e053fd4a46 fix: share a single async Redis client per URL to avoid duplicate connection pools
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:35:10 +05:30
Hugh Brown
a30b94c887 fix: redact credentials from Redis URL in rate-limit error messages
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:35:10 +05:30
Hugh Brown
6af02f6b75 fix: align in-memory rate limiter to count blocked attempts like Redis
Always append the timestamp before checking the count so that sustained
spam extends the window, matching the Redis backend's zadd-before-zcard
semantics.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:35:10 +05:30
Hugh Brown
6b55b52a68 refactor: switch RedisRateLimiter to async redis.asyncio client
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>
2026-03-07 23:35:10 +05:30
Hugh Brown
0a749db2c4 Remove unused imports 2026-03-07 23:35:10 +05:30
Hugh Brown
dc25a9df6b fix: fail fast when RATE_LIMIT_BACKEND=redis but no Redis URL is configured
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:35:10 +05:30
Hugh Brown
f1bcf72810 feat: add trusted client-IP extraction from proxy headers
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>
2026-03-07 23:35:10 +05:30
Hugh Brown
77f73872eb fix: scope optional agent auth rate limiting to X-Agent-Token header only
Prevents normal user requests with Authorization: Bearer from being
throttled by the agent auth limiter in the shared require_user_or_agent
dependency path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:35:10 +05:30
Hugh Brown
fc9fc1661c feat: add Redis-backed rate limiter with configurable backend
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>
2026-03-07 23:35:10 +05:30
Hugh Brown
ce18fe4f0c fix: apply rate limiting to optional agent auth path
get_agent_auth_context_optional was not rate-limited, allowing
brute-force token guessing via routes that use require_user_or_agent.
Now applies agent_auth_limiter when a token is actually presented.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:35:10 +05:30
Hugh Brown
54279bf413 revert: restore truncated token_prefix in agent auth log messages
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>
2026-03-07 23:35:10 +05:30
Hugh Brown
b2fb8a082d feat: make webhook payload size limit configurable
Add WEBHOOK_MAX_PAYLOAD_BYTES setting (default 1 MB) so deployments
with larger webhook payloads can raise the limit via environment
variable instead of being hard-blocked at 1 MB.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:35:10 +05:30
Hugh Brown
cd70242043 docs: fix rate limiter docstrings to reflect sliding-window algorithm
The module and class docstrings incorrectly described the implementation
as a "token-bucket" limiter when it actually uses a sliding-window log
(deque of timestamps with pruning).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:35:10 +05:30
Hugh Brown
916dace3c8 Address ruff / formatting errors 2026-03-07 23:35:10 +05:30
Hugh Brown
62d2378bdc chore: simplify and harden security review changes
- Add prompt-injection fencing to _webhook_memory_content (was missing
  the --- BEGIN/END EXTERNAL DATA --- fence applied elsewhere)
- Wrap Content-Length parsing in try/except to avoid 500 on malformed
  header values
- Move _to_gateway_read below imports (was incorrectly placed between
  import blocks) and tighten transformer types
- Replace list-rebuild with deque.popleft in rate limiter for O(expired)
  amortized pruning instead of O(n) per call
- Make organization_id required in send_session_message to prevent
  fail-open cross-tenant check

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:35:10 +05:30
Hugh Brown
4960d8561b security: fix fail-open auth, streaming payload limit, and rate limiter memory leak
- 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>
2026-03-07 23:35:10 +05:30
Hugh Brown
94988deef2 security: add rate limiting to agent auth and webhook ingest
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>
2026-03-07 23:35:10 +05:30
Hugh Brown
8e145a2129 security: set sensible defaults for security response headers
X-Content-Type-Options, X-Frame-Options, and Referrer-Policy all
defaulted to empty (disabled). Set defaults to nosniff, DENY, and
strict-origin-when-cross-origin respectively. Operators can still
override or disable via environment variables.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:35:10 +05:30
Hugh Brown
4257c08ba9 security: stop logging token prefix on failed agent auth
The first 6 characters of invalid agent tokens were logged, leaking
partial credential information. Remove token_prefix from log messages
while preserving the request path for debugging.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:35:10 +05:30
Abhimanyu Saharan
532fbf1dc5 feat(config): make BASE_URL a required field and update related documentation 2026-03-05 01:36:07 +05:30
Abhimanyu Saharan
77870b0fc7 fix(agent): improve error handling for get_agent_soul method 2026-03-03 03:09:29 +05:30
Hanush H Nair
4c35cb03ad fix(backend): Return None instead of 401 when agent not found in get_agent_auth_context_optional 2026-02-27 23:19:40 +05:30
Abhimanyu Saharan
c0eb1a14fd Merge branch 'master' into fix/agent-auth-accept-bearer-in-optional-dep 2026-02-27 01:49:45 +05:30
Adam Grenier
3b20e799e2 fix: accept Authorization: Bearer in agent_auth_context_optional
The optional variant of get_agent_auth_context had accept_authorization=False,
which prevented agents using Authorization: Bearer from passing through the
ACTOR_DEP / BOARD_READ_DEP / TASK_DEP dependency chain.

This caused 401 on any agent route that resolves a board or task via the shared
ACTOR_DEP (e.g. PATCH /agent/boards/{id}/tasks/{id} and
POST /agent/boards/{id}/tasks/{id}/comments), even though the same token worked
fine on routes that use AGENT_CTX_DEP directly (accept_authorization=True).

Fix: set accept_authorization=True in get_agent_auth_context_optional so both
X-Agent-Token and Authorization: Bearer are accepted consistently.

Verified: PATCH and POST /comments now resolve board/task correctly when
Authorization: Bearer is used. No security regression — agent_token_hash
comparison rejects any non-agent bearer tokens.
2026-02-26 11:51:45 -08:00
Abhimanyu Saharan
58db8be117 fix(security): update security header names to lowercase and add tests 2026-02-25 03:39:49 +05:30
Abhimanyu Saharan
3f158940cd Merge branch 'master' into docs/backend-doc-pass 2026-02-25 03:32:14 +05:30
Simone
3fd5fe5f8c fix: make security headers configurable and add tests 2026-02-24 17:36:44 +01:00
Abhimanyu Saharan
24731667d4 feat: add gateway runtime compatibility checks and minimum version enforcement 2026-02-15 15:59:55 +05:30
Abhimanyu Saharan
efad1d4afc refactor: increase dispatch throttle duration for improved queue processing 2026-02-15 13:09:22 +05:30
Abhimanyu Saharan
7e76cd1f68 refactor: improve webhook processing with enhanced logging and retry mechanisms 2026-02-15 13:02:55 +05:30
Abhimanyu Saharan
f9b14af477 refactor: migrate webhook queue to RQ with updated configuration 2026-02-15 13:02:55 +05:30
Abhimanyu Saharan
9a49768b52 chore: centralize webhook scheduler interval config 2026-02-14 23:46:07 +00:00
Abhimanyu Saharan
130f2b36f0 fix: resolve mypy typing issues in webhook queue dispatch 2026-02-14 23:46:07 +00:00
Abhimanyu Saharan
f07b4d5ea4 feat: add RQ-based webhook dispatch queue and delayed worker 2026-02-14 23:46:07 +00:00
Abhimanyu Saharan
8e72b7e0bc feat(error_handling): improve error payload serialization for JSON compatibility 2026-02-12 20:10:30 +05:30
Abhimanyu Saharan
bf7b992cca docs(auth): clarify bearer parsing and Clerk claim extraction 2026-02-12 14:18:23 +00:00
Abhimanyu Saharan
e9e0d6960a docs(backend): clarify auth/error-handling via docstrings 2026-02-12 08:27:31 +00:00
Abhimanyu Saharan
571b4844d9 feat: update local authentication mode to require a non-placeholder token of at least 50 characters 2026-02-11 19:40:33 +05:30
Abhimanyu Saharan
06ff1a9720 feat: implement local authentication mode and update related components 2026-02-11 19:40:33 +05:30
Abhimanyu Saharan
8d0b2939a6 feat: enhance logging configuration and add request logging context 2026-02-11 16:49:43 +05:30
Abhimanyu Saharan
6bc38f4997 refactor: remove unused local agent workspace logic and simplify provisioning 2026-02-10 19:20:50 +05:30
Abhimanyu Saharan
01888062a6 refactor(auth): streamline authentication flow and enhance error logging 2026-02-10 18:40:42 +05:30
Abhimanyu Saharan
5c25c4bb91 chore(backend): upgrade deps and remove redis/rq 2026-02-10 16:05:49 +05:30
Abhimanyu Saharan
822b13e6eb refactor: enhance error handling and optimize user profile fetching logic 2026-02-10 00:50:43 +05:30
Abhimanyu Saharan
55d4c482bc refactor: implement user deletion functionality and enhance settings management 2026-02-10 00:17:06 +05:30
Abhimanyu Saharan
3326100205 refactor: update Clerk authentication integration and improve organization handling 2026-02-09 23:55:52 +05:30