Skip to content

[Security] Fix session cookie flags and strip internal errors from API responses#460

Closed
advikdivekar wants to merge 1 commit into
GitMetricsLab:mainfrom
advikdivekar:security/session-cookie-error-leakage-447
Closed

[Security] Fix session cookie flags and strip internal errors from API responses#460
advikdivekar wants to merge 1 commit into
GitMetricsLab:mainfrom
advikdivekar:security/session-cookie-error-leakage-447

Conversation

@advikdivekar
Copy link
Copy Markdown
Contributor

Problem

This PR addresses two independent but related HIGH-severity vulnerabilities in the backend.

1 — Session cookie missing security attributes (backend/server.js lines 19–23)

The express-session config had no cookie block, so the resulting connect.sid cookie carried none of the standard security flags:

  • No httpOnlydocument.cookie returned the raw session ID from the browser console, meaning any XSS gadget or compromised npm package could exfiltrate it and achieve full account takeover.
  • No secure — the cookie was transmitted over plain HTTP, allowing a network observer on shared Wi-Fi or a transparent proxy to capture and replay it.
  • No sameSite — cross-site requests (e.g. an <img> on a third-party page targeting /api/auth/logout) automatically carried the session cookie, enabling CSRF on all current and future authenticated endpoints.

2 — Raw MongoDB error internals returned in 500 responses (backend/routes/auth.js lines 29 and 44)

Both 500 error handlers returned err.message verbatim:

  • Signup catch: { message: 'Error creating user', error: err.message } — a duplicate-key violation exposes the full MongoDB error string including collection name, index name, and key value: E11000 duplicate key error collection: githubTracker.users index: email_1 dup key: { email: "..." }.
  • Logout catch: { message: 'Logout failed', error: err.message } — any session store error leaks internal implementation details.

This fingerprints the database engine, collection structure, and index naming, narrowing the attack surface for further exploitation.

Changes

backend/server.js

  • Added cookie block to the express-session configuration:
    • httpOnly: true — session ID invisible to JavaScript in all environments
    • secure: process.env.NODE_ENV === 'production' — HTTPS-only in production, HTTP allowed in local dev
    • sameSite: 'strict' — cross-site requests never carry the cookie
    • maxAge: 24 * 60 * 60 * 1000 — 24-hour session expiry

backend/routes/auth.js

  • Line 29: removed error: err.message from the signup 500 response
  • Line 44: removed error: err.message from the logout 500 response

Both handlers now return only the generic message string — no internal state is disclosed.

Why this approach fixes the root cause

The cookie flags operate at the browser level before any application logic runs — they cannot be bypassed by an attacker who has already obtained a gadget in the page without the httpOnly flag. Stripping err.message from 500 responses is a boundary decision: internal errors belong in server-side logs, not in API responses visible to callers.

Steps to test

  1. Start the backend (npm start in backend/).
  2. POST /api/auth/login with valid credentials. Open DevTools → Application → Cookies — confirm connect.sid shows HttpOnly and SameSite=Strict.
  3. In the browser console, run document.cookie — confirm connect.sid is not present.
  4. Trigger a duplicate-key 500 on signup (register the same email twice after removing the pre-check temporarily) — confirm the response body contains only { "message": "Error creating user" } with no MongoDB error string.
  5. Set NODE_ENV=production and restart — confirm the Secure flag now appears on the cookie.

Edge cases covered

  • Development (HTTP localhost) — secure is false so login still works without HTTPS.
  • Production — secure: true enforces HTTPS-only cookie transmission.
  • Any XSS gadget — httpOnly: true blocks cookie access in all environments.
  • Duplicate-key or any other MongoDB 500 — only the generic message is returned.
  • Logout session-store failure — only the generic message is returned.

Regression check

No route logic, validators, passport config, or tests were changed. Session serialization/deserialization in passportConfig.js is untouched. The cookie attribute additions are transparent to all code that reads from req.session or req.user.

Please review and merge this under GSSoC 2026.

Session cookie had no security attributes: no httpOnly meant JS could
read the session ID via document.cookie; no secure meant it travelled
over plain HTTP; no sameSite meant cross-site requests carried it,
enabling CSRF. Added httpOnly, secure (production-gated), sameSite
strict, and a 24-hour maxAge to the express-session cookie config.

Both 500 handlers in routes/auth.js returned err.message verbatim,
leaking MongoDB internals (collection name, index names, key values)
to callers on any trigger-able error. Removed the error field from
both responses so only the generic message is returned.

Fixes GitMetricsLab#447
@netlify
Copy link
Copy Markdown

netlify Bot commented May 23, 2026

Deploy Preview for github-spy ready!

Name Link
🔨 Latest commit 3854d73
🔍 Latest deploy log https://app.netlify.com/projects/github-spy/deploys/6a11bf3af9b5e90008e32e68
😎 Deploy Preview https://deploy-preview-460--github-spy.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 23, 2026

Warning

Review limit reached

@advikdivekar, we couldn't start this review because you've used your available PR reviews for now.

Your plan currently allows 1 review/hour. Refill in 43 minutes.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more review capacity refills, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a7035a72-3332-4005-ab3d-16af070ea4d3

📥 Commits

Reviewing files that changed from the base of the PR and between 373dde2 and 3854d73.

📒 Files selected for processing (2)
  • backend/routes/auth.js
  • backend/server.js
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@mehul-m-prajapati
Copy link
Copy Markdown
Collaborator

dont need this as we will rewrite whole backend

@advikdivekar
Copy link
Copy Markdown
Contributor Author

@mehul-m-prajapati why was my code not merged? did i make any mistakes in my code? please let me know

@mehul-m-prajapati
Copy link
Copy Markdown
Collaborator

@advikdivekar : Because you are trying to farm points by doing small PRs, your all changes can be done in one PR.

Moreover, these changes were already done, so its not required for now

@advikdivekar
Copy link
Copy Markdown
Contributor Author

@advikdivekar : Because you are trying to farm points by doing small PRs, your all changes can be done in one PR.

Moreover, these changes were already done, so its not required for now

I raised them as separate issues so went for separate PRs as well but I'll make sure to not follow that practice from here on, apologies from my end, I'll make sure it doesn't happen and make meaningful PRs no matter how many issues I have raised.
I do want to work on this project ahead, requesting you to provide me with opportunities even ahead of time in GSSoC 2026, I'll even share the verification of the working changes in the codebase before raising any PR of any sort.
Apologies from my end, please provide me with opportunities further ahead of time in this project under GSSoC 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants