Skip to content

Task #2591: Hardening Cookies Flags - #2580

Merged
herzog0 merged 3 commits into
developfrom
julia/harden-cookie-flags
Aug 24, 2026
Merged

Task #2591: Hardening Cookies Flags#2580
herzog0 merged 3 commits into
developfrom
julia/harden-cookie-flags

Conversation

@julhoang

@julhoang julhoang commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Issue: #2591

Summary & Context

Session and CSRF cookies were being set without Secure or HttpOnly. This turns those flags on in every deployed environment, pins SameSite explicitly, and removes the one piece of our JavaScript that depended on reading the session cookie. manage.py check --deploy no longer reports security.W012, security.W015, or security.W016.

Changes

  • Set SESSION_COOKIE_SECURE and CSRF_COOKIE_SECURE to True in the existing non-local branch alongside SECURE_PROXY_SSL_HEADER, so local development still works over plain HTTP.
  • Set SESSION_COOKIE_HTTPONLY to True — it was explicitly False, an opt-out of Django's own default. CSRF_COOKIE_HTTPONLY was already on.
  • Set SESSION_COOKIE_SAMESITE and CSRF_COOKIE_SAMESITE to "Lax" explicitly. That matches Django's current default, so nothing changes today; it exists to stop a future default change or unrelated edit from silently loosening it. "Strict" is deliberately avoided — the social auth callback is a cross-site redirect back into the site and must still carry the session cookie.
  • Replace the client-side session-cookie check in templates/users/profile.html with a server-side {% if request.user.is_authenticated %} guard around the script. This has to ship in the same PR: the old script attached X-CSRFToken only if it could find config-sessionid in document.cookie, so turning on HttpOnly without this edit would have silently dropped the header and broken every htmx POST on the page. The guard preserves the original intent without reading a cookie; the token is still the server-rendered {{ csrf_token }}. This was the last place in our own JavaScript that read the session cookie.

‼️ Risks & Considerations ‼️

  • Verified: the Secure flag will not lock anyone out. Every one of the 20 hostnames across the production, stage and cppal-dev ALLOWED_HOSTS returns a 301 from http:// to https:// — checked live, no plain-HTTP origin anywhere. Enforced at the edge (Fastly, then a GCE Ingress FrontendConfig.redirectToHttps on production and a GKE Gateway redirect HTTPRoute on all three), not by Django.

    for h in boost.cppalliance.org www.boost.cppalliance.org boost.org www.boost.org \
             preview.boost.org www.preview.boost.org boost.io www.boost.io \
             stage.boost.cppalliance.org www.stage.boost.cppalliance.org \
             stage.boost.org www.stage.boost.org \
             stage2.boost.cppalliance.org www.stage2.boost.cppalliance.org \
             cppal-dev.boost.cppalliance.org www.cppal-dev.boost.cppalliance.org \
             cppal-dev2.boost.cppalliance.org www.cppal-dev2.boost.cppalliance.org \
             cppal-dev.boost.org www.cppal-dev.boost.org; do
      printf '%-40s ' "$h"
      curl -sS -o /dev/null -w '%{http_code} -> %{redirect_url}\n' "http://$h/" --max-time 12
    done
  • Existing sessions keep their old cookie attributes until the cookie is re-issued, so anyone already logged in stays on a non-HttpOnly, non-Secure cookie until they log out and back in. No action needed, but the flags aren't universally in effect the moment this deploys.

  • templates/users/profile.html only renders when the v3 waffle flag is off; the v3 profile templates take their CSRF token from {{ csrf_token }} and never read cookies.

  • The vendored boost-gecko search bundle ships Algolia's insights code, which can read and write an _ALGOLIA cookie. We pass it no insights configuration, and the write is gated on a useCookie option we never set, so no such cookie is created. Unrelated to the session cookie either way.

Peer-Testing Guidelines

  1. Pull the branch and confirm the v3 waffle flag is off — the changed template is the pre-v3 profile page.
  2. Go to http://localhost:8000/users/me/ and click Add New Commit Author Email Address, then the resend (↻) icon beside an unverified address. Both are htmx POSTs and should succeed rather than 403 — this is the path the removed cookie check would have broken.
  3. Submit the ordinary forms on the same page (Update Profile, Update Preferences, photo upload) to confirm standard CSRF still works.
  4. In DevTools → Application → Cookies, check config-sessionid shows HttpOnly and SameSite=Lax. Secure will be absent locally — expected, it's gated behind LOCAL_DEVELOPMENT.
  5. In the DevTools console, run document.cookie and confirm config-sessionid is no longer listed.
  6. To check the deployed config without deploying: docker compose exec -e LOCAL_DEVELOPMENT=False web python manage.py check --deploy should report no W012, W015, or W016.

Self-review Checklist

  • Tag at least one team member from each team to review this PR
  • Link this PR to the related GitHub Project ticket

Frontend

N/A

Summary by CodeRabbit

  • Security Enhancements
    • Improved protection for session and CSRF cookies.
    • Cookies now use safer browser handling and secure transmission in non-local environments.
    • Session cookies are no longer accessible to client-side scripts.
    • Authenticated requests now consistently include CSRF protection.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ea19d6ab-6f4e-461b-b7e7-94a6b61dd04b

📥 Commits

Reviewing files that changed from the base of the PR and between 81d95a1 and 3c9ab6e.

📒 Files selected for processing (1)
  • config/settings.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • config/settings.py

📝 Walkthrough

Walkthrough

The changes update Django cookie security settings and simplify HTMX CSRF header configuration for authenticated users on the profile page.

Changes

Cookie security and CSRF handling

Layer / File(s) Summary
Cookie security settings
config/settings.py
Session and CSRF cookies now use SameSite=Lax. Non-local environments enable secure cookies. Session cookies are now HttpOnly.
Profile CSRF configuration
templates/users/profile.html
The CSRF header is set for authenticated users without checking the config-sessionid cookie.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 3c9ab

The PR hardens session and CSRF cookie handling and updates the affected profile-page request flow; no actionable merge-blocking risk remains beyond normal checks and review.

Possibly related issues

  • Issue 2591: The changes implement the cookie security settings and profile-page HTMX CSRF handler fix described by the issue.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: hardening cookie security flags.
Description check ✅ Passed The description covers the issue, context, changes, risks, testing steps, and checklist; only the optional screenshots section is absent.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch julia/harden-cookie-flags

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.

@julhoang julhoang changed the title Hardening Cookies Flags Task #2591: Hardening Cookies Flags Aug 7, 2026
@julhoang
julhoang marked this pull request as ready for review August 7, 2026 19:05
@jlchilders11
jlchilders11 self-requested a review August 11, 2026 18:52

@jlchilders11 jlchilders11 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks good to me.

@ycanales
ycanales self-requested a review August 12, 2026 17:22
@ycanales

Copy link
Copy Markdown
Collaborator

Good call on the lax instead of strict to not have problems with allauth callbacks.
Looks good, thanks @julhoang !

@julhoang
julhoang force-pushed the julia/harden-cookie-flags branch from 81d95a1 to 3c9ab6e Compare August 14, 2026 18:52

@kattyode kattyode left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

QA Approved

@herzog0
herzog0 merged commit 8105c7c into develop Aug 24, 2026
5 checks passed
@herzog0
herzog0 deleted the julia/harden-cookie-flags branch August 24, 2026 17:18
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.

Task: Turn on the standard browser protections for our session and CSRF cookies

5 participants