Skip to content

[Backend] Add CORS Configuration and HTTPS Enforcement #160

Description

@devJaja

🎯 Objective

Add CORS configuration, HTTPS enforcement, and fix the hardcoded WebSocket URL to prevent security vulnerabilities in transport and origin control.


📁 Files to Modify

Action File Path Description
Modify backend/src/api/app.ts Add CORS middleware
Modify backend/src/config/index.ts Add ALLOWED_ORIGINS config
Modify backend/.env.example Document ALLOWED_ORIGINS
Modify frontend/src/hooks/useTaskMonitor.ts Fix hardcoded ws://localhost:3001

📁 Files to Create

Action File Path Description
Create backend/src/api/middleware/cors.ts CORS configuration factory

🔍 Current Vulnerabilities

1. No CORS (app.ts)

// CURRENT — cors dependency exists but is never used
// Package.json includes "cors" but no app.use(cors(...)) call
// Server accepts requests from ANY origin

2. No HTTPS enforcement

// Server listens on plain HTTP
// No HSTS headers
// No redirect middleware

3. Hardcoded WebSocket URL (useTaskMonitor.ts ~line 102)

// CURRENT — Hardcoded to localhost, plain WebSocket
const ws = new WebSocket('ws://localhost:3001/tasks/${taskId}/stream');

✅ Expected Fix

Backend: CORS Configuration

// backend/src/api/middleware/cors.ts
import cors from 'cors';

export function createCorsMiddleware() {
  const allowedOrigins = process.env.ALLOWED_ORIGINS?.split(',') || ['http://localhost:3000'];

  return cors({
    origin: (origin, callback) => {
      if (!origin || allowedOrigins.includes(origin)) {
        callback(null, true);
      } else {
        callback(new Error('Not allowed by CORS'));
      }
    },
    credentials: true,
    methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
    allowedHeaders: ['Content-Type', 'Authorization', 'walletpublickey', 'x-challenge', 'x-signature'],
  });
}

Backend: Mount in app.ts

import { createCorsMiddleware } from './middleware/cors';

app.use(createCorsMiddleware());

Frontend: Fix WebSocket URL (useTaskMonitor.ts)

// BEFORE
const ws = new WebSocket(`ws://localhost:3001/tasks/${taskId}/stream`);

// AFTER
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const host = import.meta.env.VITE_WS_HOST || window.location.host;
const ws = new WebSocket(`${protocol}//${host}/tasks/${taskId}/stream`);

📁 Reference Files

File Path Purpose
backend/package.json cors dependency already listed
backend/src/api/app.ts Express app setup
backend/src/config/index.ts Zod-based env config
backend/.env.example Environment template
frontend/src/hooks/useTaskMonitor.ts (line ~102) Hardcoded WebSocket URL
frontend/src/services/api.ts API base URL config reference

✅ Acceptance Criteria

  • Create backend/src/api/middleware/cors.ts with configurable origins
  • Mount CORS middleware in backend/src/api/app.ts
  • Add ALLOWED_ORIGINS to backend/src/config/index.ts
  • Document ALLOWED_ORIGINS in backend/.env.example
  • Fix WebSocket URL in frontend/src/hooks/useTaskMonitor.ts to use dynamic protocol
  • Add HSTS header middleware for production
  • Add test: verify CORS blocks unauthorized origins
  • Add test: verify CORS allows configured origins

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions