Feature: Add CSRF protection for state-changing operations #8

Closed
opened 2026-03-10 03:46:19 +00:00 by Mark · 1 comment
Owner

Issue

The API lacks CSRF protection for state-changing operations, making it vulnerable to cross-site request forgery attacks.

Location

  • All POST/PUT/DELETE endpoints
  • Session management operations
  • User management endpoints

Current Implementation

Only API key authentication, no CSRF tokens.

Risk

  • Malicious sites could perform actions on behalf of logged-in users
  • Session hijacking via XSS + CSRF combination

Proposed Solution

  1. Implement double-submit cookie pattern
  2. Add CSRF token endpoint
  3. Require CSRF token for all state-changing operations
  4. Use SameSite cookies

Acceptance Criteria

  • Add CSRF token generation endpoint
  • Implement double-submit cookie validation
  • Require CSRF tokens for POST/PUT/DELETE
  • Update frontend to include CSRF tokens
  • Set SameSite=Strict on cookies

Priority: Medium
Type: Security/Feature

## Issue The API lacks CSRF protection for state-changing operations, making it vulnerable to cross-site request forgery attacks. ## Location - All POST/PUT/DELETE endpoints - Session management operations - User management endpoints ## Current Implementation Only API key authentication, no CSRF tokens. ## Risk - Malicious sites could perform actions on behalf of logged-in users - Session hijacking via XSS + CSRF combination ## Proposed Solution 1. Implement double-submit cookie pattern 2. Add CSRF token endpoint 3. Require CSRF token for all state-changing operations 4. Use SameSite cookies ## Acceptance Criteria - [ ] Add CSRF token generation endpoint - [ ] Implement double-submit cookie validation - [ ] Require CSRF tokens for POST/PUT/DELETE - [ ] Update frontend to include CSRF tokens - [ ] Set SameSite=Strict on cookies **Priority:** Medium **Type:** Security/Feature
Author
Owner

GSD VERIFY phase failed after 3 attempts.
═══ Gate: verify-passed (devforge#8) ═══
Mode: Tier 1 (functional only)

GATE OK: All gates up to 'implement' pass
── Tier 1: Functional ────────────────────────────────
Running tests...
❌ Tests failed (exit 1)
 FAIL  services/web/src/utils/terminalUtils.test.ts > terminalUtils > decodeTerminalMessage > should return empty Uint8Array for Blob input in sync decoder
 FAIL  services/web/src/utils/terminalUtils.test.ts > terminalUtils > debug mode > should return false when debug is not enabled
 FAIL  services/web/src/utils/terminalUtils.test.ts > terminalUtils > debug mode > should return true when debug is enabled
 FAIL  services/web/src/utils/terminalUtils.test.ts > terminalUtils > debug mode > should disable debug mode
ReferenceError: localStorage is not defined
 ❯ services/web/src/utils/terminalUtils.test.ts:12:5
 10|  beforeEach(() => {
 11|  vi.restoreAllMocks();
 12|  localStorage.clear();
 |  ^
 13|  });
 14| 

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/9]⎯

 Test Files  4 failed | 1 passed (5)
 Tests  6 failed | 4 passed (10)
 Start at  02:14:21
 Duration  643ms (transform 495ms, setup 0ms, import 135ms, tests 11ms, environment 1ms)
Running linter...
✅ Lint clean
⚠️ No type checker discovered
Previous test count: unknown

❌ GATE FAIL: verify-passed
- Tests failed with exit code 1
GATE FAIL: verify — blocked at 2026-05-21T09:14:23Z
Class: test-failure
Evidence: Verification failed: 1 failures
Git tag: devforge#8-gate-verify-fail-17424555cd2c (use gate-retry after fixing)

GSD VERIFY phase failed after 3 attempts. ═══ Gate: verify-passed (devforge#8) ═══ Mode: Tier 1 (functional only) GATE OK: All gates up to 'implement' pass ── Tier 1: Functional ──────────────────────────────── Running tests... ❌ Tests failed (exit 1)  FAIL  services/web/src/utils/terminalUtils.test.ts > terminalUtils > decodeTerminalMessage > should return empty Uint8Array for Blob input in sync decoder  FAIL  services/web/src/utils/terminalUtils.test.ts > terminalUtils > debug mode > should return false when debug is not enabled  FAIL  services/web/src/utils/terminalUtils.test.ts > terminalUtils > debug mode > should return true when debug is enabled  FAIL  services/web/src/utils/terminalUtils.test.ts > terminalUtils > debug mode > should disable debug mode ReferenceError: localStorage is not defined  ❯ services/web/src/utils/terminalUtils.test.ts:12:5  10|  beforeEach(() => {  11|  vi.restoreAllMocks();  12|  localStorage.clear();  |  ^  13|  });  14|  ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/9]⎯  Test Files  4 failed | 1 passed (5)  Tests  6 failed | 4 passed (10)  Start at  02:14:21  Duration  643ms (transform 495ms, setup 0ms, import 135ms, tests 11ms, environment 1ms) Running linter... ✅ Lint clean ⚠️ No type checker discovered Previous test count: unknown ❌ GATE FAIL: verify-passed - Tests failed with exit code 1 GATE FAIL: verify — blocked at 2026-05-21T09:14:23Z Class: test-failure Evidence: Verification failed: 1 failures Git tag: devforge#8-gate-verify-fail-17424555cd2c (use gate-retry after fixing)
Mark closed this issue 2026-06-09 04:10:16 +00:00
Sign in to join this conversation.
No description provided.