Skip to content

security: harden network surface, filesystem, and hub IPC#9

Open
BRlin-o wants to merge 2 commits into
lis186:mainfrom
BRlin-o:security/surface-fs-hardening
Open

security: harden network surface, filesystem, and hub IPC#9
BRlin-o wants to merge 2 commits into
lis186:mainfrom
BRlin-o:security/surface-fs-hardening

Conversation

@BRlin-o

@BRlin-o BRlin-o commented Apr 17, 2026

Copy link
Copy Markdown

Summary

Security hardening for network/shared deployment scenarios. Part 1 of 3 PRs from the audit in #7.

Network surface reduction

  • Bind 127.0.0.1 by default — previously 0.0.0.0, exposing proxy + dashboard to the entire network. Add HOST env for opt-in LAN access.
  • Request body cap — 50 MB default (CCXRAY_MAX_BODY_MB), returns 413 on exceed. Prevents OOM via large POST.
  • Per-IP SSE limit — max 8 concurrent connections per IP (CCXRAY_SSE_MAX_PER_IP). Prevents connection exhaustion.
  • HTTP timeoutsheadersTimeout=60s, requestTimeout=120s, keepAliveTimeout=5s. Mitigates slowloris.
  • Log injection sanitize — strip ANSI escapes and control chars from logged request URLs/methods.

Filesystem hardening

  • File permissions — log files 0o600, directories 0o700. Hub lockfile and log also 0o600.
  • Path traversal guardsafeJoin() rejects ../, /, \, null bytes; verifies resolved path stays within base dir.

Hub IPC isolation

  • Loopback-only/_api/hub/* restricted to 127.0.0.1 / ::1 / ::ffff:127.0.0.1. Non-local requests get 403.
  • Input validationpid must be positive int ≤ 2²², cwd must be string ≤ 4096 chars, body capped at 1 KB.
  • /_api/health remains open (pure liveness probe, no sensitive info).

npm audit

  • npm audit fix — bumps basic-ftp to resolve HIGH CRLF injection in @aws-sdk transitive dep.

Breaking change

Server now binds 127.0.0.1 by default. Users accessing ccxray from other machines on the LAN need to set HOST=0.0.0.0.

Test plan

  • 236 tests pass, 0 failures
  • New tests: storage-path-traversal.test.js (7 cases), fs-mode.test.js (4 cases), hub-loopback.test.js (12 cases)
  • Manual: npx ccxray claude starts and proxies correctly
  • Manual: dashboard loads, entries display, SSE streaming works
  • npm audit --audit-level=high → 0 vulnerabilities

Ref: #7

🤖 Generated with Claude Code

BRlin-o and others added 2 commits April 17, 2026 12:16
Network surface reduction (Phase 0):
- Bind 127.0.0.1 by default; add HOST env for opt-in network access
- Cap request body at 50 MB (CCXRAY_MAX_BODY_MB); return 413 on exceed
- Per-IP SSE connection limit (default 8, CCXRAY_SSE_MAX_PER_IP)
- HTTP timeouts: headersTimeout=60s, requestTimeout=120s, keepAliveTimeout=5s
- Sanitize ANSI/control chars in logged request URLs (log injection)
- Extract readBodyCapped() helper for safe body accumulation

Filesystem hardening (Phase 1):
- Log files 0o600, log directories 0o700; chmod on existing paths
- safeJoin() rejects path traversal (../, /, \, null bytes)
- Hub lockfile and log written with 0o600

Hub localhost-only + validation (Phase 2):
- /_api/hub/* restricted to loopback IPs (127.0.0.1, ::1, ::ffff:127.0.0.1)
- /_api/health remains open (pure liveness, no sensitive info)
- Register/unregister validate pid (int, 0 < n ≤ 2²²) and cwd (string, ≤ 4096)
- Hub body cap 1 KB for control endpoints

BREAKING: Server now binds 127.0.0.1 only. Set HOST=0.0.0.0 for LAN access.

Closes lis186#7 (partial)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bumps basic-ftp to patched version, resolving HIGH severity
CRLF injection in @aws-sdk transitive dependency.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant