# 05. Fix CORS origin trust from unvalidated APP_URL env var meta: id: security-fixes-05 feature: security-fixes priority: P1 depends_on: [] tags: [implementation, tests-required, medium-severity] objective: - Validate APP_URL before trusting it as a CORS origin to prevent arbitrary origin injection deliverables: - APP_URL validation in CORS middleware at `web/src/middleware.ts` - Domain pattern validation for environment-sourced CORS origins - Unit tests for CORS origin validation steps: 1. Examine the CORS middleware at `web/src/middleware.ts:22-30` 2. Create a `validateCorsOrigin(origin: string): boolean` function that: - Parses the origin URL and validates the hostname format - Rejects wildcard patterns (`*`), empty origins, and non-HTTP(S) schemes - Optionally checks against a known domain allowlist 3. Add validation of `process.env.APP_URL` before adding it to `allowedOrigins` 4. Add a fallback: if APP_URL is missing or invalid, log a warning and exclude it from allowed origins 5. Consider adding a `VALID_CORS_ORIGINS` env var for explicit allowlist configuration tests: - Unit: `validateCorsOrigin` accepts `https://app.kordant.com` (valid HTTPS origin) - Unit: `validateCorsOrigin` rejects `*` (wildcard) - Unit: `validateCorsOrigin` rejects `evil.com` (missing scheme) - Unit: `validateCorsOrigin` rejects empty string and whitespace - Unit: `validateCorsOrigin` rejects `http://localhost:9999` if not in the allowlist (configurable) - Integration: CORS middleware does not add invalid APP_URL to allowed origins acceptance_criteria: - APP_URL is validated before being added to CORS allowed origins - Invalid or missing APP_URL is excluded with a warning logged - Wildcard origins are rejected - Legitimate HTTPS origins are accepted - No regression in existing CORS behavior for localhost and configured domains validation: - `cd web && bun test` — all tests pass - Set `APP_URL=evil.com` and verify it is not added to allowed origins - Set `APP_URL=https://app.kordant.com` and verify it is accepted notes: - Finding p8-005: The current code trusts `process.env.APP_URL` without any validation - If APP_URL is set at deployment time (e.g., in a Docker env file), the risk is lower but still present if the deployment pipeline is compromised - Consider using a structured env var like `CORS_ORIGINS=https://app.kordant.com,https://admin.kordant.com` instead