Add CSRF origin header validation to POST /api/contact endpoint #46

Closed
opened 2026-04-10 09:14:38 -04:00 by pook · 11 comments
Owner

PR #19 adds POST /api/contact with Resend email. Without CSRF protection, any malicious website can submit forms on behalf of authenticated users. Since this is an API endpoint, use origin header validation (no cookies = no token needed, but origin check prevents cross-site form submissions).

Implementation:

  1. Create src/middleware/csrfProtection.ts:
    • Export validateOrigin(req, res, next) middleware
    • Check req.headers.origin or req.headers.referer against allowed origins list from env var ALLOWED_ORIGINS (comma-separated)
    • For POST/PUT/DELETE: reject with 403 if origin is missing or not in allowlist
    • Skip for GET/HEAD/OPTIONS
  2. Apply middleware to POST /api/contact route
  3. Add test: POST without origin header returns 403, POST with valid origin passes through

Acceptance criteria:

  • POST /api/contact without Origin header returns 403 Forbidden
  • POST /api/contact with correct Origin header passes through
  • GET requests unaffected
  • ALLOWED_ORIGINS configurable via environment variable

Generated by CEO Planner (priority: 2)

PR #19 adds POST /api/contact with Resend email. Without CSRF protection, any malicious website can submit forms on behalf of authenticated users. Since this is an API endpoint, use origin header validation (no cookies = no token needed, but origin check prevents cross-site form submissions). Implementation: 1. Create `src/middleware/csrfProtection.ts`: - Export `validateOrigin(req, res, next)` middleware - Check `req.headers.origin` or `req.headers.referer` against allowed origins list from env var `ALLOWED_ORIGINS` (comma-separated) - For POST/PUT/DELETE: reject with 403 if origin is missing or not in allowlist - Skip for GET/HEAD/OPTIONS 2. Apply middleware to POST /api/contact route 3. Add test: POST without origin header returns 403, POST with valid origin passes through Acceptance criteria: - POST /api/contact without Origin header returns 403 Forbidden - POST /api/contact with correct Origin header passes through - GET requests unaffected - ALLOWED_ORIGINS configurable via environment variable --- *Generated by CEO Planner (priority: 2)*
Author
Owner

⚠️ Stale Task Alert — This task has been open for 6h with no associated PR.

Possible causes:

  • Worker failed to execute (check logs)
  • Claude CLI produced no changes
  • Task may be too complex for single-session execution

The CEO planner will re-evaluate this task. If it remains stale for 24h+, it will be closed and re-scoped.

— CEO Planner (automated)

⚠️ **Stale Task Alert** — This task has been open for 6h with no associated PR. Possible causes: - Worker failed to execute (check logs) - Claude CLI produced no changes - Task may be too complex for single-session execution The CEO planner will re-evaluate this task. If it remains stale for 24h+, it will be closed and re-scoped. *— CEO Planner (automated)*
Author
Owner

⚠️ Stale Task Alert — This task has been open for 6h with no associated PR.

Possible causes:

  • Worker failed to execute (check logs)
  • Claude CLI produced no changes
  • Task may be too complex for single-session execution

The CEO planner will re-evaluate this task. If it remains stale for 24h+, it will be closed and re-scoped.

— CEO Planner (automated)

⚠️ **Stale Task Alert** — This task has been open for 6h with no associated PR. Possible causes: - Worker failed to execute (check logs) - Claude CLI produced no changes - Task may be too complex for single-session execution The CEO planner will re-evaluate this task. If it remains stale for 24h+, it will be closed and re-scoped. *— CEO Planner (automated)*
Author
Owner

⚠️ Stale Task Alert — This task has been open for 7h with no associated PR.

Possible causes:

  • Worker failed to execute (check logs)
  • Claude CLI produced no changes
  • Task may be too complex for single-session execution

The CEO planner will re-evaluate this task. If it remains stale for 24h+, it will be closed and re-scoped.

— CEO Planner (automated)

⚠️ **Stale Task Alert** — This task has been open for 7h with no associated PR. Possible causes: - Worker failed to execute (check logs) - Claude CLI produced no changes - Task may be too complex for single-session execution The CEO planner will re-evaluate this task. If it remains stale for 24h+, it will be closed and re-scoped. *— CEO Planner (automated)*
Author
Owner

⚠️ Stale Task Alert — This task has been open for 7h with no associated PR.

Possible causes:

  • Worker failed to execute (check logs)
  • Claude CLI produced no changes
  • Task may be too complex for single-session execution

The CEO planner will re-evaluate this task. If it remains stale for 24h+, it will be closed and re-scoped.

— CEO Planner (automated)

⚠️ **Stale Task Alert** — This task has been open for 7h with no associated PR. Possible causes: - Worker failed to execute (check logs) - Claude CLI produced no changes - Task may be too complex for single-session execution The CEO planner will re-evaluate this task. If it remains stale for 24h+, it will be closed and re-scoped. *— CEO Planner (automated)*
Author
Owner

⚠️ Stale Task Alert — This task has been open for 7h with no associated PR.

Possible causes:

  • Worker failed to execute (check logs)
  • Claude CLI produced no changes
  • Task may be too complex for single-session execution

The CEO planner will re-evaluate this task. If it remains stale for 24h+, it will be closed and re-scoped.

— CEO Planner (automated)

⚠️ **Stale Task Alert** — This task has been open for 7h with no associated PR. Possible causes: - Worker failed to execute (check logs) - Claude CLI produced no changes - Task may be too complex for single-session execution The CEO planner will re-evaluate this task. If it remains stale for 24h+, it will be closed and re-scoped. *— CEO Planner (automated)*
Author
Owner

⚠️ Stale Task Alert — This task has been open for 7h with no associated PR.

Possible causes:

  • Worker failed to execute (check logs)
  • Claude CLI produced no changes
  • Task may be too complex for single-session execution

The CEO planner will re-evaluate this task. If it remains stale for 24h+, it will be closed and re-scoped.

— CEO Planner (automated)

⚠️ **Stale Task Alert** — This task has been open for 7h with no associated PR. Possible causes: - Worker failed to execute (check logs) - Claude CLI produced no changes - Task may be too complex for single-session execution The CEO planner will re-evaluate this task. If it remains stale for 24h+, it will be closed and re-scoped. *— CEO Planner (automated)*
Author
Owner

⚠️ Stale Task Alert — This task has been open for 8h with no associated PR.

Possible causes:

  • Worker failed to execute (check logs)
  • Claude CLI produced no changes
  • Task may be too complex for single-session execution

The CEO planner will re-evaluate this task. If it remains stale for 24h+, it will be closed and re-scoped.

— CEO Planner (automated)

⚠️ **Stale Task Alert** — This task has been open for 8h with no associated PR. Possible causes: - Worker failed to execute (check logs) - Claude CLI produced no changes - Task may be too complex for single-session execution The CEO planner will re-evaluate this task. If it remains stale for 24h+, it will be closed and re-scoped. *— CEO Planner (automated)*
Author
Owner

⚠️ Stale Task Alert — This task has been open for 8h with no associated PR.

Possible causes:

  • Worker failed to execute (check logs)
  • Claude CLI produced no changes
  • Task may be too complex for single-session execution

The CEO planner will re-evaluate this task. If it remains stale for 24h+, it will be closed and re-scoped.

— CEO Planner (automated)

⚠️ **Stale Task Alert** — This task has been open for 8h with no associated PR. Possible causes: - Worker failed to execute (check logs) - Claude CLI produced no changes - Task may be too complex for single-session execution The CEO planner will re-evaluate this task. If it remains stale for 24h+, it will be closed and re-scoped. *— CEO Planner (automated)*
Author
Owner

⚠️ Stale Task Alert — This task has been open for 8h with no associated PR.

Possible causes:

  • Worker failed to execute (check logs)
  • Claude CLI produced no changes
  • Task may be too complex for single-session execution

The CEO planner will re-evaluate this task. If it remains stale for 24h+, it will be closed and re-scoped.

— CEO Planner (automated)

⚠️ **Stale Task Alert** — This task has been open for 8h with no associated PR. Possible causes: - Worker failed to execute (check logs) - Claude CLI produced no changes - Task may be too complex for single-session execution The CEO planner will re-evaluate this task. If it remains stale for 24h+, it will be closed and re-scoped. *— CEO Planner (automated)*
Author
Owner

⚠️ Stale Task Alert — This task has been open for 9h with no associated PR.

Possible causes:

  • Worker failed to execute (check logs)
  • Claude CLI produced no changes
  • Task may be too complex for single-session execution

The CEO planner will re-evaluate this task. If it remains stale for 24h+, it will be closed and re-scoped.

— CEO Planner (automated)

⚠️ **Stale Task Alert** — This task has been open for 9h with no associated PR. Possible causes: - Worker failed to execute (check logs) - Claude CLI produced no changes - Task may be too complex for single-session execution The CEO planner will re-evaluate this task. If it remains stale for 24h+, it will be closed and re-scoped. *— CEO Planner (automated)*
Author
Owner

Closing stale duplicate — active replacement covers this scope.

Closing stale duplicate — active replacement covers this scope.
pook closed this issue 2026-04-10 18:00:56 -04:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
pook/vision-tech-solutions#46
No description provided.