Commit Graph

1051 Commits

Author SHA1 Message Date
Hugh Brown
3a0c67a656 Update backend/app/api/board_webhooks.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-07 23:35:10 +05:30
Hugh Brown
86229038eb Update backend/tests/test_security_fixes.py
Seems like a simpler fix.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-07 23:35:10 +05:30
Hugh Brown
149fde90c4 docs: document security hardening changes from security review
Add documentation for all user/operator-facing changes introduced by the
security review branch: rate limits, security headers, webhook HMAC
verification, payload size limits, gateway token redaction, non-root
containers, agent token logging, and prompt injection mitigation.

Updated: docs/reference/api.md, docs/reference/authentication.md,
docs/reference/configuration.md, docs/deployment/README.md,
docs/operations/README.md, docs/openclaw_gateway_ws.md, backend/README.md.
Created: docs/reference/security.md (consolidated security reference).

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
858575cf6c test: add comprehensive tests for all security fixes
Add 20 tests covering:
- require_user_actor: rejects agents and null users, passes valid users
- Webhook HMAC: rejects missing/invalid signatures, accepts valid ones,
  allows unsigned when no secret configured
- Prompt injection: sanitized skill name/URL, fenced external data in
  dispatch messages, system instructions precede data
- Security headers: verify nosniff, DENY, referrer-policy defaults
- Payload size: rejects oversized body and content-length
- Rate limiting: blocks after threshold, independent per-key
- Gateway token: has_token field present, token field absent
- Agent auth logs: no token_prefix in source

Also fix deprecated HTTP_413_REQUEST_ENTITY_TOO_LARGE status code.

All 407 tests pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:35:10 +05:30
Hugh Brown
547965a5cb security: redact gateway tokens from API responses
Gateway tokens were returned as plaintext in GatewayRead API responses.
Replace the `token` field with a boolean `has_token` flag so the API
never exposes the plaintext token. The token remains in the database
for outbound gateway connections (full encryption would require key
management infrastructure).

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
8a30c82c6d security: remove hardcoded auth token from committed .env.test
The file contained a publicly known LOCAL_AUTH_TOKEN value that could
be used against misconfigured deployments. Replace with an empty value
and a comment showing how to generate a secure token. The test suite
continues to work via conftest.py which sets its own test-only token.

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
c7f8578f38 security: run Docker containers as non-root user
Both backend and frontend Dockerfiles ran all processes as root.
Add a dedicated appuser in each runtime stage so container processes
run with minimal privileges, limiting blast radius of any container
escape.

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
Hugh Brown
66da278673 security: require org-admin for gateway session message endpoint
send_gateway_session_message only required basic auth (AUTH_DEP) while
all other gateway endpoints required ORG_ADMIN_DEP. Any authenticated
user could send messages to any gateway session. Now requires org-admin
and verifies the board belongs to the caller's organization.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:35:10 +05:30
Hugh Brown
7ca4145aff security: add 1 MB payload size limit to webhook ingestion
The webhook ingest endpoint read the entire request body with no size
limit, enabling memory exhaustion attacks. Add a 1 MB limit checked
via both Content-Length header (early reject) and actual body size.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:35:10 +05:30
Hugh Brown
5d382ed67b security: mitigate prompt injection in agent instruction strings
User-controlled fields (skill name, source URL, webhook payloads) were
interpolated directly into agent instruction messages. Sanitize skill
fields by stripping newlines/control chars, and fence all external data
behind "BEGIN EXTERNAL DATA" / "BEGIN STRUCTURED DATA" delimiters with
explicit "do not interpret as instructions" markers. Move system
instructions above the data section so they cannot be overridden.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:35:10 +05:30
Hugh Brown
4d1dbb4098 security: add HMAC signature verification to webhook ingest
Webhook ingest endpoint was completely unauthenticated. Add an optional
`secret` field to BoardWebhook. When configured, inbound requests must
include a valid HMAC-SHA256 signature in X-Hub-Signature-256 or
X-Webhook-Signature headers. Uses hmac.compare_digest for timing safety.
Includes migration to add the secret column.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:35:10 +05:30
Hugh Brown
10848b98cb security: scope agent board listing to organization
Main agents (board_id=None) could list boards across all organizations.
Now resolves the agent's organization via its gateway and filters boards
by organization_id to prevent cross-tenant data leakage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:35:10 +05:30
Hugh Brown
c7692e30d3 security: rename misleading require_admin to require_user_actor
The function only checked that the caller was an authenticated user
(not an agent) but its name implied privilege enforcement. Rename to
require_user_actor and add docstring clarifying the distinction between
actor-type checks and privilege/role checks (require_org_admin, is_super_admin).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:35:10 +05:30
Abhimanyu Saharan
4b25094bb1 Merge pull request #228 from KennyDizi/master
fix: normalize deprecated `postgres://` URLs to `postgresql+psycopg://`
2026-03-07 23:27:37 +05:30
Abhimanyu Saharan
5037fab1d8 Merge branch 'master' into master 2026-03-07 23:20:04 +05:30
Abhimanyu Saharan
b32a9f5e66 fix(makefile): set BASE_URL for local environment in database migration commands 2026-03-07 23:19:54 +05:30
Abhimanyu Saharan
b12eaf30dc Merge branch 'master' into master 2026-03-07 23:13:41 +05:30
Abhimanyu Saharan
de9e73eb7a Merge pull request #226 from aronchick/security/bind-ports-to-localhost
security: bind redis and postgres ports to localhost only
2026-03-05 20:50:29 +05:30
Aaron Aronchick
08462b430f Merge master into security/bind-ports-to-localhost: keep localhost port binding and redis healthcheck 2026-03-05 13:32:32 +00:00
zoi-tdinh
b42c2eb73c fix: normalize deprecated postgres:// URLs to postgresql+psycopg:// 2026-03-05 20:11:46 +07:00
Abhimanyu Saharan
51f35d1978 Merge pull request #222 from abhi1693/installer-tests
feat(ci): harden installer smoke tests across linux and macos
2026-03-05 02:21:17 +05:30
Abhimanyu Saharan
ff643af934 fix(installer): set required backend env values in docker mode 2026-03-05 02:13:27 +05:30
Abhimanyu Saharan
359de2868d fix(ci): address installer workflow review feedback 2026-03-05 02:05:03 +05:30
Abhimanyu Saharan
d46480bd23 feat(ci): enhance installer smoke tests for macOS and Linux with improved readiness checks 2026-03-05 01:55:33 +05:30
Abhimanyu Saharan
ba6726a99c feat(ci): enhance installer workflow with OS matrix and conditional smoke tests 2026-03-05 01:39:38 +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
df7152dcad feat(docker): add watch mode for automatic frontend rebuilds in Docker 2026-03-05 00:54:09 +05:30
Abhimanyu Saharan
2b0d3ba386 Merge pull request #135 from abhi1693/feat/agent-webhook-payload-read
feat(agent): allow agents to read stored webhook payloads for backfill
2026-03-04 23:36:04 +05:30
Abhimanyu Saharan
3acc276d8d fix(agent): address webhook payload read review feedback 2026-03-04 23:26:31 +05:30
Abhimanyu Saharan
1d0b318fc9 lint: fix flake8 E304 after create_task decorator 2026-03-04 23:22:27 +05:30
Abhimanyu Saharan
3fc96baa10 feat(agent): add read-only webhook payload fetch endpoint for backfill 2026-03-04 23:22:27 +05:30
Abhimanyu Saharan
9ccb9aefd8 Merge pull request #134 from abhi1693/fix/blocked-transition-error-schema
Fix blocked-task error schema: include code field
2026-03-04 23:20:30 +05:30
Abhimanyu Saharan
f5e3b8923a test: assert blocked precondition in dependency-only update test 2026-03-04 23:09:56 +05:30
Abhimanyu Saharan
636c130a3b test: harden blocked-task regression tests per review 2026-03-04 23:01:24 +05:30
Abhimanyu Saharan
130947dcea test: format blocked-task schema regression assertions 2026-03-04 22:52:43 +05:30
Abhimanyu Saharan
6f7867872b test: fix import order for blocked dependency regression test 2026-03-04 22:50:47 +05:30
Abhimanyu Saharan
e9ce004e70 test: address PR review feedback for blocked-task schema 2026-03-04 22:46:44 +05:30
Abhimanyu Saharan
8b77eae0f2 Document blocked-task 409 error code in OpenAPI + add regression tests 2026-03-04 22:46:44 +05:30
Abhimanyu Saharan
2ae1c219f7 Merge pull request #131 from abhi1693/test/e2e-critical-flows
test(e2e): cover boards, approvals, packs critical flows
2026-03-04 22:40:57 +05:30
Abhimanyu Saharan
04d80c53ac Merge branch 'master' into test/e2e-critical-flows 2026-03-04 22:30:36 +05:30
Abhimanyu Saharan
b6aff9c796 test(e2e): align critical-flow specs with local auth CI 2026-03-04 22:29:47 +05:30
Abhimanyu Saharan
e567c3ca42 Merge pull request #119 from abhi1693/test/aec2903b-rtl-batch1
test(frontend): add UserMenu RTL coverage (batch 1)
2026-03-04 22:27:06 +05:30
Abhimanyu Saharan
39f314cd8c test(e2e): extract shared page test setup hooks 2026-03-04 22:26:40 +05:30
Abhimanyu Saharan
d1b08b4777 chore(e2e): remove gap analysis markdown doc 2026-03-04 22:26:15 +05:30