security: harden API, prevent injection, and restrict access#1
Open
xtalax wants to merge 2 commits intoandrew-yangy:mainfrom
Open
security: harden API, prevent injection, and restrict access#1xtalax wants to merge 2 commits intoandrew-yangy:mainfrom
xtalax wants to merge 2 commits intoandrew-yangy:mainfrom
Conversation
- Restrict CORS to localhost origins only (was wildcard *) - Add request body size limits (1MB default, 8KB for input endpoints) to prevent memory exhaustion DoS - Fix path traversal in static file serving via path.resolve containment - Prevent AppleScript injection by validating TTY paths against /^\/dev\/ttys\d+$/ - Improve AppleScript escaping to handle newlines, carriage returns, tabs - Harden team name validation with strict allowlist regex [a-zA-Z0-9_-] plus defense-in-depth path containment check - Add input validation/truncation to event receiver (type, sessionId, message, timestamp format, metadata size) - Reject unexpected keys in config PATCH endpoint - Set restrictive file permissions (0o700 dirs, 0o600 files) on ~/.conductor/ config and database - Add security headers: X-Content-Type-Options, X-Frame-Options, CSP Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract security utilities (CORS, readBody, serveStatic) into
server/security.ts for testability. Extract sanitizeEventBody from
event-receiver.ts to enable DB-free unit testing.
New test files:
- server/security.test.ts (28 tests)
- CORS origin allowlist (allowed/blocked/missing origins)
- Security headers (CSP, X-Frame-Options, nosniff)
- readBody size limits (normal, chunked, empty, exact limit, overflow)
- serveStatic path traversal (../, internal .., SPA fallback, MIME types)
- server/actions/cleanup.test.ts (18 tests)
- Valid team deletion with hyphens/underscores/digits
- Path traversal prevention (../, /, ..)
- Special character rejection (spaces, semicolons, backticks,
dollar signs, null bytes, newlines, backslashes, unicode)
- server/hooks/event-receiver.test.ts (29 tests)
- Normal input passthrough
- Missing field defaults (type, sessionId, timestamp, message, project)
- Field truncation (type@128, sessionId@256, message@1024, project@256)
- Timestamp validation (valid ISO, invalid, empty, non-string)
- Metadata size limit (small preserved, >8KB dropped)
- Type coercion (non-string inputs default correctly)
All 136 tests pass (75 new + 61 existing).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Security hardening across the server codebase, addressing critical vulnerabilities found during audit:
*with explicit localhost origin allowlist, preventing any webpage from calling the APIreadBody()helper with configurable max size (1MB default, 8KB for input endpoints) to prevent memory exhaustion DoSserveStatic()now validates resolved path stays within dist directory viapath.resolvecontainment/^\/dev\/ttys\d+$/before interpolation into AppleScript strings\n,\r,\tin addition to\and"[a-zA-Z0-9_-]allowlist plus defense-in-depth resolved-path containment checkmacOS/browser~/.conductor/dir0o700, config/db files0o600X-Content-Type-Options: nosniff,X-Frame-Options: DENY,Content-Security-PolicyMotivation
The highest-impact finding: CORS
*+ zero authentication means any website visited while the server is running can send keystrokes to terminal panes viaPOST /api/actions/send-input. The CORS fix alone closes that attack surface from cross-origin contexts.Test coverage
75 new tests across 3 test files (136 total with existing 61):
server/security.test.ts(28 tests)readBodysize limits — normal read, chunked, empty body, exact limit, overflow rejectionserveStaticpath traversal —../blocked, internal..blocked, SPA fallback, correct MIME typesserver/actions/cleanup.test.ts(18 tests)../,/, bare.., dot-prefixed names$, null bytes, newlines, backslashes, unicodeserver/hooks/event-receiver.test.ts(29 tests)Refactoring for testability
server/security.ts(CORS, headers, readBody, serveStatic)sanitizeEventBodyfrom event-receiver.ts for DB-free unit testingnpm testscript topackage.json🤖 Generated with Claude Code