dev_arc_aws/.kiro/specs/code-audit-fixes/tasks.md
Samuel James c9d7462c33
All checks were successful
CI / validate (pull_request) Successful in 7m7s
Add code-audit-fixes spec + audit steering
- Spec for fixing 13 Critical + High code audit issues
- requirements.md (14 requirements, EARS format)
- design.md (component fixes + 8 correctness properties)
- tasks.md (8 tasks, parallel execution waves)
- CloudFormation test deploy template planned
- code-audit.md steering file (all 40 issues documented)

Co-authored-by: Samuel James <ssamjame@amazon.com>
Co-authored-by: Kiro <noreply@kiro.dev>
2026-06-24 15:19:32 -04:00

7.9 KiB
Raw Blame History

Implementation Plan: Code Audit Fixes

Overview

Surgical fixes for 13 Critical + High audit issues across the ArchNest backend (Fastify 5 + TypeScript) and frontend (React 19 + TypeScript), plus a CloudFormation test deploy template. Each task targets a specific file with a minimal, correct patch. No new dependencies introduced.

Tasks

  • 1. Backend security hardening — input validation and auth

    • 1.1 Add path traversal prevention to backend/src/routes/files.ts

      • Add validatePath() function using posix.normalize() to reject absolute paths and .. traversal
      • Apply validation at the top of every handler that accepts a user-supplied path (list, content read, content write, mkdir, rename, delete, chmod, download, upload)
      • Return HTTP 400 with descriptive error on rejection
      • Requirements: 6.1, 6.2, 6.3, 6.4
    • 1.2 Fix agent token timing-safe comparison in backend/src/routes/agents.ts

      • Replace early-return on length mismatch with padded constant-time comparison
      • Pad both buffers to Math.max(a.length, b.length) before timingSafeEqual
      • Ensure ok: true only when both length AND content match
      • Same 401 response for all rejection cases
      • Requirements: 7.1, 7.2, 7.3
    • 1.3 Add session log integrationId validation in backend/src/routes/terminal.ts

      • Update sessionLogPath() to return null when integrationId is not a positive integer
      • Callers skip logging on null return
      • Requirements: 13.1, 13.2
    • 1.4 Add body size limit to data import in backend/src/routes/data.ts

      • Add bodyLimit: 10 * 1024 * 1024 to the POST /api/data/import route registration
      • Fastify returns 413 automatically when exceeded
      • Requirements: 8.1, 8.2
    • 1.5 Set CORS origin to fail-closed default in backend/src/server.ts

      • Change fallback from true to false when ARCHNEST_CORS_ORIGIN is not set
      • Log a warning at startup when env var is missing
      • Requirements: 10.1, 10.2, 10.3
    • * 1.6 Write property tests for path traversal, agent token, and integrationId validation

      • Property 3: Path Traversal Prevention — verify validatePath rejects all .. escape patterns and accepts valid relative paths
      • Property 4: Agent Token Comparison Correctness — verify ok: true iff presented === expected, never throws
      • Property 8: Integration ID Numeric Validation — verify sessionLogPath returns null for non-positive-integer values
      • Validates: Requirements 6.1, 6.2, 7.1, 7.2, 7.3, 13.1, 13.2
  • 2. Checkpoint — Backend security

    • Ensure all tests pass, ask the user if questions arise.
  • 3. WebSocket authentication refactor

    • 3.1 Implement first-message auth gate in backend/src/routes/terminal.ts

      • Add authenticated flag per connection
      • Require { type: 'auth', token } as first message; verify JWT
      • Reject all other message types before auth with error frame + close
      • Remove req.query.token usage from connect/list_tmux handlers
      • Requirements: 5.3, 5.4
    • 3.2 Implement first-message auth gate in backend/src/routes/docker.ts

      • Same pattern as terminal: auth-first protocol for Docker exec WebSocket
      • Verify existing JSON parse error handling remains intact (already correct per design)
      • Requirements: 5.3, 5.4, 12.1, 12.2
    • 3.3 Update frontend WebSocket connections in src/lib/TerminalSessionContext.tsx

      • Remove ?token= from WebSocket URL query string
      • Send { type: 'auth', token } as first message on ws.onopen
      • Apply same change to fetchTmuxSessions() WebSocket
      • Requirements: 5.1, 5.2
    • 3.4 Fix WebSocket session leak in src/lib/TerminalSessionContext.tsx

      • Guard ws.close() with readyState check (OPEN or CONNECTING)
      • Capture thisWs reference; in onclose, bail if s.ws !== thisWs
      • Requirements: 1.1, 1.2, 1.3
    • * 3.5 Write property test for WebSocket auth gate

      • Property 5: WebSocket Auth Gate Rejects Unauthenticated Messages
      • Verify no message type other than auth is processed before authentication
      • Validates: Requirements 5.3, 5.4
  • 4. Checkpoint — WebSocket auth

    • Ensure all tests pass, ask the user if questions arise.
  • 5. Backend — tmux validation and SSH cleanup verification

    • 5.1 Harden tmux session name usage in backend/src/routes/terminal.ts

      • Ensure validated name is single-quoted in shell command construction
      • Defense-in-depth: strip any ' (impossible given regex, but belt+suspenders)
      • Requirements: 2.1, 2.2, 2.3
    • 5.2 Verify container ref validation in backend/src/ssh/docker.ts

      • Confirm CONTAINER_REF_RE regex is ^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$
      • Confirm shQuote() is applied to all container ref interpolations
      • Confirm SSH cleanup in withSshClient finally block is present
      • If already correct (per design), add a code comment noting audit verification
      • Requirements: 3.1, 3.2, 3.3, 9.1, 9.2
    • * 5.3 Write property tests for tmux name validation and container ref validation

      • Property 1: tmux Session Name Validation Prevents Injection — verify only [A-Za-z0-9_-]{1,64} passes
      • Property 2: Container Reference Validation and Safe Escaping — verify regex and shQuote safety
      • Property 6: SSH Connection Cleanup Guarantee — verify withSshClient always calls .end()
      • Validates: Requirements 2.1, 2.3, 3.1, 3.3, 9.1, 9.2
  • 6. Frontend stability fixes

    • 6.1 Add .catch() to Sidebar promise in src/components/Sidebar.tsx

      • Append .catch(() => {}) to the api.listIntegrations() call
      • Ensure integrations state remains null on failure (shows "Checking…")
      • Requirements: 4.1, 4.2
    • 6.2 Create Error Boundary component at src/components/ErrorBoundary.tsx

      • React class component with getDerivedStateFromError + componentDidCatch
      • Fallback UI: centered message + gold "Reload Page" button on dark background
      • Log error to console
      • Requirements: 11.2, 11.3, 11.4
    • 6.3 Wrap Dashboard in ErrorBoundary in src/App.tsx

      • Import and wrap the top-level Dashboard component tree
      • Requirements: 11.1
    • * 6.4 Write unit tests for ErrorBoundary and Sidebar error handling

      • Verify ErrorBoundary renders fallback on child throw
      • Verify Sidebar swallows rejected promise without crashing
      • Validates: Requirements 4.1, 4.2, 11.1, 11.2, 11.3, 11.4
  • 7. CloudFormation test deploy template

    • 7.1 Create infra/test-deploy.yml CloudFormation template

      • Parameters: KeyPairName (KeyPair type), NotificationEmail (String)
      • Resources: SecurityGroup (SSH + HTTP/HTTPS), EC2 Instance (t4g.small, AL2023 ARM64, Docker + Compose via UserData), Budget alarm ($30/month, 80% threshold)
      • Outputs: PublicIP, InstanceId
      • Requirements: 14.1, 14.2, 14.3, 14.4, 14.5, 14.6
    • * 7.2 Write smoke test validating CloudFormation template structure

      • Verify required resource types, parameters, and outputs exist
      • Validate YAML parses correctly
      • Validates: Requirements 14.114.6
  • 8. Final checkpoint

    • Ensure all tests pass, ask the user if questions arise.

Notes

  • Tasks marked with * are optional and can be skipped for faster MVP
  • Each task references specific requirements for traceability
  • Components 3 (container ref), 9 (SSH cleanup), and 12 (JSON parse) are verified-already-correct per design — task 5.2 confirms with a code comment
  • The project uses TypeScript throughout (Fastify 5 backend, React 19 frontend)
  • No new dependencies are introduced; all fixes use Node.js built-ins and existing patterns

Task Dependency Graph

{
  "waves": [
    { "id": 0, "tasks": ["1.1", "1.2", "1.3", "1.4", "1.5", "6.1", "6.2", "7.1"] },
    { "id": 1, "tasks": ["1.6", "6.3", "6.4", "7.2"] },
    { "id": 2, "tasks": ["3.1", "3.2", "5.1", "5.2"] },
    { "id": 3, "tasks": ["3.3", "3.4", "3.5", "5.3"] }
  ]
}