Set SESSION_COOKIE_SECURE to True so the cookie only travels over HTTPS, keep SESSION_COOKIE_HTTPONLY at its default of True, and set SESSION_COOKIE_SAMESITE to Lax. Leave SESSION_COOKIE_DOMAIN unset unless you need subdomains. Flask's defaults do not turn on Secure or SameSite for you.
The defaults, from Flask's configuration page
| Setting | Default | What it does |
|---|---|---|
| SESSION_COOKIE_HTTPONLY | True | Blocks JavaScript from reading the cookie |
| SESSION_COOKIE_SECURE | False | When True, browsers send it only over HTTPS |
| SESSION_COOKIE_SAMESITE | None | Restricts sending with requests from other sites |
| SESSION_COOKIE_DOMAIN | None | Unset means only the exact host receives it |
| PERMANENT_SESSION_LIFETIME | see docs | Cookie expiry, and signature age check, when session.permanent is true |
The page notes that Secure only makes sense if the application is served over HTTPS, and that SameSite can be Lax (recommended) or Strict.
A production block
app.config.update(
SESSION_COOKIE_SECURE=True,
SESSION_COOKIE_HTTPONLY=True,
SESSION_COOKIE_SAMESITE="Lax",
)
This is the same set Flask's security page shows under its Set-Cookie options section.
What each attribute protects against
Secure limits cookies to HTTPS traffic. Without it, a browser may send the session cookie over an unencrypted request, where someone on the network can read it.
HttpOnly protects the contents of the cookie from being read with JavaScript. If a page has a cross site scripting flaw, script cannot lift the session cookie, though it can still make requests as the user.
SameSite restricts how cookies are sent with requests from external sites. Flask's page explains that Lax prevents sending cookies with CSRF prone requests from external sites, such as submitting a form, while Strict prevents sending cookies with all external requests, including following regular links. Strict can feel broken: a user who clicks a link to your site from an email may arrive logged out.
Cookie domain and name
Flask says not setting SESSION_COOKIE_DOMAIN is more restricted and secure, because browsers then send the cookie only to the exact domain. Setting it to example.com also sends the cookie to every subdomain. Any subdomain with a weakness, or one run by another team, becomes a way to attack your sessions. The docs also warn that changing the domain after cookies exist can create a second cookie, and browsers may send both.
Signed, not encrypted
Remember that the Flask session cookie is signed, not encrypted, so users can read it. Keep sensitive values server side. See the SECRET_KEY post in this series for rotation.
Does SameSite replace CSRF tokens?
No. SameSite helps, but Flask's security page still describes CSRF as a risk for cookie based authentication and recommends tokens for requests that change data. Use a CSRF protection library for forms and unsafe API calls, and treat SameSite as an extra layer.
Check your site
- Load the site over HTTPS and inspect the Set-Cookie header in your browser's network tab.
- Confirm Secure, HttpOnly and SameSite appear on the session cookie.
- Confirm HTTP requests redirect to HTTPS and consider HSTS.
- Confirm the Domain attribute is absent unless you need it.
Try it yourself
Click through it at your own pace, or open it full screen. Look for how cookie attribute checks appear in a web scan.
Quick check
Is SESSION_COOKIE_SECURE on by default in Flask?
No. The default is False, so set it to True when you serve over HTTPS.
Should I use Strict instead of Lax?
Flask recommends Lax. Strict withholds the cookie on all external navigation, which can sign users out when they follow a link.
Safeguard's DAST scanning and compliance evidence automation can help check and record cookie settings. You can try a free scan.
Sources
Last reviewed: 19 October 2026.