Skip to content

Conversation

@cfsmp3
Copy link
Collaborator

@cfsmp3 cfsmp3 commented Jan 19, 2026

Summary

Security fixes for two high-severity vulnerabilities identified in the security audit.

1. Secure Session Cookies

Problem: Session cookies were created without security flags, making them vulnerable to:

  • XSS attacks (JavaScript could read session cookies)
  • CSRF attacks (cookies sent on cross-site requests)
  • Man-in-the-middle attacks (cookies sent over HTTP)

Fix: Added secure cookie options in backend/main.go:

  • HttpOnly: true - Prevents JavaScript access
  • Secure: true (in production) - Cookies only sent over HTTPS
  • SameSite: Lax - CSRF protection while allowing OAuth redirects
  • MaxAge: 7 days - Reasonable session lifetime

2. WebSocket Origin Validation

Problem: WebSocket upgrader accepted connections from ANY origin:

CheckOrigin: func(r *http.Request) bool {
    return true
}

This allowed any website to establish WebSocket connections, enabling cross-site WebSocket hijacking.

Fix: Added checkWebSocketOrigin() function that:

  • Validates Origin header against ALLOWED_ORIGIN environment variable
  • Allows localhost origins in development mode (ENV != "production")
  • Falls back to same-origin check if no env var configured
  • Logs rejected connection attempts for monitoring

3. Updated Production Configuration

  • Added ENV variable documentation (set to "production" for secure mode)
  • Added ALLOWED_ORIGIN variable for WebSocket validation
  • Improved documentation of all environment variables

Files Changed

  • backend/main.go - Added secure session cookie options
  • backend/controllers/websocket.go - Added origin validation
  • production/example.backend.env - Added security configuration

Deployment Notes

After merging, update the VPS backend .env to include:

ENV="production"
ALLOWED_ORIGIN="https://taskwarrior-server.ccextractor.org"

Then rebuild and restart the backend container.

Test Plan

  • Verify session cookies have HttpOnly, Secure, SameSite flags (browser dev tools)
  • Verify WebSocket connects from allowed origin
  • Verify WebSocket rejects connections from other origins
  • Verify OAuth login still works (SameSite=Lax allows redirects)

🤖 Generated with Claude Code

Security fixes:
- Add Secure, HttpOnly, SameSite flags to session cookies
  - HttpOnly: prevents JavaScript access (XSS protection)
  - Secure: cookies sent only over HTTPS in production
  - SameSite=Lax: CSRF protection while allowing OAuth redirects

- Validate WebSocket origin against allowed origins
  - Check Origin header against ALLOWED_ORIGIN env var
  - Allow localhost in development mode
  - Fallback to same-origin check if no env var configured
  - Log rejected connection attempts

- Update example.backend.env with security settings
  - Add ENV=production for secure mode
  - Add ALLOWED_ORIGIN for WebSocket validation
  - Better documentation of all variables

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@github-actions
Copy link

Thank you for opening this PR!

Before a maintainer takes a look, it would be really helpful if you could walk through your changes using GitHub's review tools.

Please take a moment to:

  • Check the "Files changed" tab
  • Leave comments on any lines for functions, comments, etc. that are important, non-obvious, or may need attention
  • Clarify decisions you made or areas you might be unsure about and/or any future updates being considered.
  • Finally, submit all the comments!

More information on how to conduct a self review:
https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/reviewing-proposed-changes-in-a-pull-request

This helps make the review process smoother and gives us a clearer understanding of your thought process.

Once you've added your self-review, we'll continue from our side. Thank you!

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
// If no ALLOWED_ORIGIN configured, check if origin matches the request host
// This provides same-origin protection as fallback
host := r.Host
if strings.Contains(origin, host) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this might be easy to break.

xyz.abc.org
and
xyz.org would both have xyz as host

- Club empty origin check with development mode check as suggested
- Replace strings.Contains with proper URL parsing for exact host match
- In production, require Origin header (reject if missing)
- Use url.Parse() for safe hostname extraction and comparison

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@cfsmp3
Copy link
Collaborator Author

cfsmp3 commented Jan 19, 2026

Addressed both review comments in commit f284ff9:

  1. Clubbed empty origin check with development mode - Now the origin == "" check is inside the development mode block as suggested.

  2. Fixed the strings.Contains security issue - Replaced with proper URL parsing using net/url. Now does exact hostname comparison:

    • Parses the origin URL with url.Parse()
    • Extracts hostname with parsedOrigin.Hostname()
    • Compares exactly with request host (after stripping port)

Also added: In production mode, missing Origin header is now rejected (logged as warning).

Tested on VPS - login works, bad origins are rejected with 400.

@its-me-abhishek its-me-abhishek merged commit 8b9ca56 into main Jan 19, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants