Broken Authentication

Broken Authentication in Flask remediation guide [GHSA-6rmh-7xcm-cpxj]

[Updated May 2026] Updated GHSA-6rmh-7xcm-cpxj

Overview

Broken authentication can let an attacker impersonate users by forging or replaying session cookies. In Flask, the session cookie is signed with the app's SECRET_KEY; if this key is weak, default, or exposed in source control, an attacker can create a valid session that identifies as any user, potentially gaining access to privileged routes and data. This kind of abuse often remains undetected until a data breach or unauthorized admin actions are observed. In Flask apps this vulnerability typically manifests when developers hard-code a secret key (for example 'dev-key' or 'change-me'), fail to rotate keys, or rely on simple, client-side tokens rather than a robust authentication flow. The result is that possession or guessing of a token can bypass login checks, making access control unreliable. Remediation focuses on strong secret management and proper session handling: use a strong, environment-based SECRET_KEY, avoid hard-coded values, rotate keys, enable secure HttpOnly cookies, consider server-side sessions or Flask-Login for robust authentication, hash passwords, and enable CSRF protection. Regularly audit secrets and rotate keys after incidents.

Code Fix Example

Flask API Security Remediation
Vulnerable:
from flask import Flask, session, request, jsonify
app = Flask(__name__)
# Insecure: weak/default secret key and cookie-based auth relying on session signed cookie
app.secret_key = 'dev-key'

@app.route('/login', methods=['POST'])
def login():
    user = request.form.get('username')
    password = request.form.get('password')
    if user == 'admin' and password == 'password':
        session['user'] = user
        return jsonify({'ok': True})
    return jsonify({'error': 'unauthorized'}), 401

@app.route('/admin')
def admin():
    if session.get('user') != 'admin':
        return jsonify({'error': 'unauthorized'}), 401
    return jsonify({'secret': 'top-secret'})


Fixed:
import os
from flask import Flask, session, request, jsonify
from flask_login import LoginManager, login_user, login_required, UserMixin

app = Flask(__name__)
# Use a strong, environment-provided secret key; do not hard-code
app.secret_key = os.environ['FLASK_SECRET_KEY']

# Optional: enable Flask-Login for robust session management
login_manager = LoginManager()
login_manager.init_app(app)

class User(UserMixin):
    def __init__(self, id):
        self.id = id

@login_manager.user_loader
def load_user(user_id):
    return User(user_id)

@app.route('/login', methods=['POST'])
def login():
    user = request.form.get('username')
    password = request.form.get('password')
    if user == 'admin' and password == 'password':  # in real apps use hashed passwords
        user_obj = User(user)
        login_user(user_obj)  # regenerates session and marks it fresh
        return jsonify({'ok': True})
    return jsonify({'error': 'unauthorized'}), 401

@app.route('/admin')
@login_required
def admin():
    return jsonify({'secret': 'top-secret'})

CVE References

Choose which optional cookies to allow. You can change this any time.