Skip to content

Conversation

@alfredolopez80
Copy link

Summary

This PR contains comprehensive security remediations and code quality improvements for the Claude-Cowork Electron application. All planned fixes have been implemented and validated. No further changes are expected.

Commits Included

Commit Description
f768f45 Comprehensive code review fixes (HIGH + MEDIUM + LOW)
e25c168 Correct test assertion in sanitizeForLog test
0cf0cab Implement comprehensive security remediation (18 findings)

Security Fixes Implemented

HIGH Priority

  • H-003: Fixed memory leak in historyRequested Set - cleanup on session deletion
  • H-004: Implemented stable React keys with _clientId for message lists

MEDIUM Priority

  • M-005: IPC schema validation (CWE-20)
  • M-006: Message array limit (1000 max) to prevent memory exhaustion
  • M-007: IPC strict validation mode via CLAUDE_COWORK_STRICT_IPC env var
  • M-008: Timeout cleanup guard with isMountedRef pattern

LOW Priority

  • L-005: Configurable path cache TTL via CLAUDE_COWORK_PATH_CACHE_TTL_MS
  • L-006: Additional log injection tests (ANSI escape sequences, DEL character)

New Environment Variables

Variable Purpose Default
CLAUDE_COWORK_STRICT_IPC Block unknown IPC event types false
CLAUDE_COWORK_PATH_CACHE_TTL_MS Path validation cache TTL (ms) 60000
CLAUDE_COWORK_ALLOW_LOCAL_PROVIDERS Allow localhost/private IPs for SSRF bypass false
CLAUDE_COWORK_TOKEN_HANDLING Token passing mode (env-var, ipc, prompt) env-var

Files Changed

src/ui/App.tsx                    - H-004, M-008 fixes
src/ui/store/useAppStore.ts       - H-003, H-004 fixes  
src/ui/types.ts                   - EnrichedMessage type
src/electron/preload.cts          - M-005, M-007 fixes
src/electron/libs/session-store.ts - L-005 fix
src/electron/libs/provider-config.ts - Token encryption, SSRF protection
src/electron/libs/__tests__/provider-config.test.ts - L-006 tests

Validation Results

Tool Result
TypeScript ✅ PASSED
ESLint ✅ PASSED
Vitest (13 tests) ✅ PASSED
Codex CLI Gate Audit ✅ PASSED
Code Review (2 iterations) ✅ APPROVED
Security Audit (2 iterations) ✅ NO CRITICAL FINDINGS

Test Plan

  • TypeScript compilation passes
  • ESLint validation passes
  • Unit tests pass (13/13)
  • Electron app starts successfully in development mode
  • Codex CLI validation passes
  • Security audit confirms no regressions

Status

✅ COMPLETE - All planned security and code quality improvements have been implemented. No additional changes are planned for this PR.


🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

alfredolopez80 and others added 22 commits January 15, 2026 15:39
- Add provider configuration modal UI for managing custom LLM API providers
- Add backend support for providers list, save, delete operations via IPC handlers
- Add runner integration to use custom provider environment variables (baseUrl, authToken, models)
- Add Sidebar provider selector to switch between default Claude Code and custom providers
- Add Zustand store actions for providers state management
- Add comprehensive types for LlmProviderConfig, provider events, and client/server event extensions

Features:
- Configure custom API providers (name, baseUrl, authToken, models per tier)
- Select active provider per session via dropdown in Sidebar
- Custom providers override default ANTHROPIC_* environment variables
- Full CRUD operations for provider configurations

Custom Providers documentation added: CUSTOM_PROVIDERS.md
…ture

- Resolve merge conflict in runner.ts combining:
  - Main branch: enhancedEnv, claudeCodePath from util.ts
  - Feature: custom provider support via getProviderEnv()
- Merge order: enhancedEnv first, then custom provider env overrides
- Single instance lock to prevent multiple windows
- Window lifecycle handlers with proper cleanup
- Polling cleanup on window close
- New throttle/debounce utilities for performance
- File permissions 0o600 for providers.json

Co-Authored-By: Claude <noreply@anthropic.com>
- FASE 2: Increase polling interval to 2000ms for better performance
- FASE 3: Add try-catch error handling in app.ready with dialog alerts
- FASE 4: Create WindowManager singleton class for window lifecycle
- Add app.on("activate") handler for Mac reactivation
- Fix preload path validation in initialization

Co-Authored-By: Claude <noreply@anthropic.com>
- Add include section to tsconfig.json for proper TypeScript compilation
- Increase POLLING_INTERVAL from 500ms to 2000ms to reduce CPU usage
- Update Makefile with run_dev and run_prod targets for better flexibility
- Use NODE_ENV=production with direct electron binary path

Co-Authored-By: Claude <noreply@anthropic.com>
- Add include section to tsconfig.json for proper TypeScript compilation
- Update Makefile with run_dev and run_prod targets for better flexibility
- Use NODE_ENV=production with direct electron binary path

Co-Authored-By: Claude <noreply@anthropic.com>
- Add custom LLM providers support
- Add URL validation in ProviderModal
- Add Electron stability improvements
- Add provider-config utilities

Co-Authored-By: Claude <noreply@anthropic.com>
- Encrypt auth tokens using Electron nativeSafeStorage
- Add decryptSensitiveData and encryptSensitiveData functions
- Set restrictive file permissions (0o600)
- Mitigate CWE-200 (Exposure of Sensitive Information)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add path sanitization to prevent CWE-22 (Path Traversal)
- Improve SQL query parameterization
- Validate cwd before creating session

Co-Authored-By: Claude <noreply@anthropic.com>
- Add .claude/ directory to .gitignore
- Add default-providers.ts with MiniMax default provider config
- Include envOverrides for default provider settings

Co-Authored-By: Claude <noreply@anthropic.com>
## New Modules
- settings-manager.ts: Load and validate ~/.claude/settings.json with schema validation
- unified-commands.ts: Parse slash commands (/help, /exit, /status, /clear)
- unified-task-runner.ts: Task context management with system prompt stacking
- orchestrator-agent.ts: Central coordinator for skills, hooks, and commands

## Security Improvements (Codex Audit)
- Fix sanitizePath() to properly validate paths without destroying them
- Add cwd re-validation in updateSession() and loadSessions()
- Add schema validation for settings.json (CWE-20 compliance)
- Deep copy in getRawSettings() to prevent mutation
- Error handling in processInput() with structured events

## Permission System
- Add PermissionMode type (secure/free) to types.ts
- Implement permission-based tool execution in runner.ts
- Add parseAllowedTools() and isToolAllowed() utilities
- Support permissionMode in session creation and IPC handlers

## Architecture
- Initialize orchestratorAgent in main.ts startup
- Export initializeHandlers() for proper initialization order
- Add database migration for permission_mode column

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
PHASE 1: API Key Security (Token Vault Architecture)
- Add SafeProviderConfig type (no tokens in IPC)
- Add ProviderSavePayload for secure token handling
- Tokens NEVER leave main process except to subprocess
- Add loadProvidersSafe(), saveProviderFromPayload(), getProviderEnvById()
- Update runner.ts to use providerEnv instead of provider object
- Fix safeStorage import in provider-config.ts

PHASE 2: Theme System (Light/Dark Mode)
- Add ThemeContext with localStorage persistence
- Add ThemeSettings modal for color customization
- Add theme toggle button in Sidebar
- Add CSS variables and dark mode styles
- Dynamic sidebar and workspace colors

PHASE 3: Provider UX Improvements
- Add default provider templates: Anthropic, MiniMax, OpenRouter, GLM, AWS Bedrock
- Add descriptions for each provider
- Add getDefaultProviderTemplates() for UI display

Security: Tokens encrypted with Electron safeStorage, never sent to renderer

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix H2: Encryption failures now throw errors instead of silently storing plaintext tokens
- Fix H1: Add URL validation for provider baseUrl to prevent SSRF attacks (CWE-918)
- Add proper error handling in IPC provider.save handler
- Improve decryption with legacy token migration warnings
- Add GitHub Actions CI pipeline for lint and build verification

Security: Token encryption now fails fast, refusing to store unencrypted credentials.
SSRF prevention blocks internal IPs (127.x, 10.x, 172.16-31.x, 192.168.x, localhost).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix React hooks called after conditional returns (EventCard.tsx)
- Add proper types and eslint-disable for unavoidable any types
- Fix hooks rules violations by moving hooks before early returns
- Add eslint-disable for valid setState-in-effect patterns
- Clean up unused eslint-disable directives
- Add proper IPC event types in main.ts and types.d.ts

All 32 ESLint errors resolved. Only 4 non-blocking warnings remain.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
P0 Critical:
- Add ENC:v1: prefix for deterministic encrypted token detection
- Add CLAUDE_COWORK_ALLOW_LOCAL_PROVIDERS env var for localhost/dev

P1 High Priority:
- Add validateModelConfig() for provider models validation
- Fix sanitizePath() to allow valid quote characters in paths
- Add isValidHookConfig() for deep hook structure validation
- Mark resetInstance() as @internal with test environment warning

P2 Medium Priority:
- Add IPC rate limiting (100 req/min per event type)
- Add 5-minute timeout for pending permission requests
- Make CI ESLint conditional (fail on main, warn on PRs)

P3 Low Priority:
- Refactor loadProviders with readProvidersFile() helper
- Add JSDoc documentation to new functions
- Fix ESLint config to ignore dist-electron/dist-react
- Fix useMemo for messages in App.tsx
- Allow hook exports in eslint react-refresh rule

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Partial progress on SDK integration:

- Add settingSources to load ~/.claude/ configuration (user, project, local)
- Implement getCustomAgents() to convert activeSkills to SDK AgentDefinition
- Add getLocalPlugins() for loading enabled plugins from ~/.claude/plugins/
- Pass agents, plugins, and settingSources to SDK query() options

UI fixes included:
- Fix provider configuration flow (modal now pre-populates with selected provider)
- Fix theme toggle icon (now shows action icon, not current state)
- Optimize PromptInput performance with debounced height calculation

Restrictions (WIP):
- Agents/skills invocation (@agent, /skill) requires further SDK integration
- Command routing still uses native SDK subagents instead of custom definitions

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Resolved 3 conflicts:

1. src/electron/ipc-handlers.ts
   - Combined cleanupAllSessions() from upstream with initializeHandlers()
   - Now exports both functions for proper app lifecycle

2. src/electron/main.ts
   - Kept WindowManager architecture (better encapsulation)
   - Added cleanupAllSessions() calls on app quit events
   - Maintained single instance lock for preventing multiple windows

3. src/electron/test.ts
   - Combined both cleanup approaches (cleanupPolling + stopPolling)
   - Better error handling with try/catch in polling
   - activePollingInterval reference for reliable cleanup

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit implements all security fixes from the comprehensive review:

CRITICAL (1):
- SEC-001: Add sanitizeForLog() to prevent log injection (CWE-117)

HIGH (3):
- SEC-002: Add TokenHandlingMode with env-var/ipc/prompt options
- QUAL-001: Enhanced loadSessions() with error logging for invalid paths
- QUAL-002: Memory leak prevention with bounded pendingPermissions Map

MEDIUM (8):
- SEC-003: Model name validation with regex pattern
- SEC-004: Error message sanitization for sensitive data protection
- SEC-005: Atomic file writes with saveProvidersAtomic() (TOCTOU prevention)
- SEC-006: Environment variable locking for security config
- QUAL-003: IPC handlers refactoring with improved structure
- SIMP-001: resolveAuthToken() helper for code clarity
- SIMP-002: parseMessageRow() helper for JSON parsing
- ARCH-001: Credential provider interface for decoupling

LOW (6):
- SEC-007: Dynamic SDK path resolution in getClaudeCodePath()
- QUAL-004: Improved type annotations
- ARCH-002: Zod schema validation (partial)
- ARCH-005: UnifiedCommandParser improvements
- ARCH-006: Node version manager path handling
- SIMP-004: Dead code removal

Additional fixes from Codex CLI audit:
- CWE-22: Robust plugin path validation with realpathSync+relative
- CWE-117: Log sanitization for model names and cwd paths

All quality gates passed:
- TypeScript compilation: OK
- ESLint: OK (0 errors, 0 warnings)
- Tests: OK

Co-Authored-By: Claude <noreply@anthropic.com>
The test expected [ to be replaced but it's a valid ASCII character.
Added additional assertions to verify no control characters remain.

Co-Authored-By: Claude <noreply@anthropic.com>
HIGH Priority Fixes:
- H-003: Fix memory leak in historyRequested Set (useAppStore.ts)
  * Clean up Set entries when sessions are deleted
  * Prevents unbounded Set growth in long-running applications

- H-004: Implement stable React keys for message lists (App.tsx, types.ts)
  * Added EnrichedMessage type with stable _clientId field
  * Messages enriched with unique IDs at ingestion time (crypto.randomUUID)
  * getMessageKey() uses _clientId instead of array index
  * Eliminates React reconciliation issues on reorder/filter

MEDIUM Priority Fixes:
- M-007: IPC strict validation mode (preload.cts)
  * Added CLAUDE_COWORK_STRICT_IPC environment variable
  * When enabled, blocks unknown event types for enhanced security
  * Default: allow unknown types for forward compatibility

- M-008: Timeout cleanup guard (App.tsx)
  * Added isMountedRef to prevent state updates after unmount
  * Guards throttle timeout callbacks against stale updates

LOW Priority Fixes:
- L-005: Configurable path cache TTL (session-store.ts)
  * Added CLAUDE_COWORK_PATH_CACHE_TTL_MS environment variable
  * Allows high-security environments to reduce cache duration

- L-006: Additional log injection tests (provider-config.test.ts)
  * Added tests for ANSI escape sequences (ESC character)
  * Added tests for DEL character (0x7F)
  * Added complex multi-vector injection test

Validation:
- TypeScript: PASSED
- ESLint: PASSED
- Unit tests: 13/13 PASSED
- Codex CLI gate audit: PASSED

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements per-session permission configuration:
- Add PermissionMode type ("secure" | "free") to types.ts
- Add SESSION_PRESETS with 4 modes in useAppStore.ts
- Add UI selector in StartSessionModal with visual warnings
- Add Free Mode indicator in PromptInput component
- Backend integration: runner.ts bypasses permissions in "free" mode
- Pass permissionMode through IPC session.start payload
- Persist permissionMode in SQLite session table

Security notes:
- Free/Developer modes show prominent warnings
- AskUserQuestion always requires approval (even in free mode)
- Tool restrictions apply even in free mode via allowedTools

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add warning colors (--color-warning, warning-dark, warning-light)
- Increase modal width from max-w-lg to max-w-xl
- Improve preset button layout with consistent height (min-h-72px)
- Add border-2 for better visibility
- Improve spacing and padding for better readability
- Add shadow on selected state
- Fix icon shrinking issue with shrink-0

Co-Authored-By: Claude Opus 4.5 <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.

2 participants