Overview
Broken Object Level Authorization (BOLA) can manifest in Flask applications when an endpoint allows users to modify configuration or objects they should not control. In the real-world CVE-2026-35464 scenario related to pyLoad, a non-admin user with SETTINGS and ADD permissions could modify a storage/config option (storage_folder) that influences where the server stores session data. The Flask session mechanism (via filesystem-backed storage) ended up executing a crafted pickle payload placed as a session file, due to improper authorization checks and the use of pickle-based storage. This led to arbitrary code execution when a request arrived with the corresponding session cookie. This CVE highlights how object-level permissions (which keys or paths a user can modify) and insecure session storage can combine to yield remote code execution. The fix introduced the ADMIN_ONLY_OPTIONS whitelist to block non-admins from altering critical configuration, but in the original scenario storage_folder was not included in that set, enabling exploitation as described. Refer to CVE-2026-35464 and the related fix commit c4cf995a2803bdbe388addfc2b0f323277efc0e1 for context.
Code Fix Example
Flask API Security Remediation
Vulnerable pattern:
from flask import Flask, request
from flask_session import Session
app = Flask(__name__)
app.config['SECRET_KEY'] = 'dev'
# Vulnerable: filesystem-backed sessions with a storage path that non-admins can modify
app.config['SESSION_TYPE'] = 'filesystem'
app.config['SESSION_FILE_DIR'] = '/tmp/pyload_sessions'
Session(app)
ADMIN_ONLY_OPTIONS = {'SECRET_KEY', 'SESSION_TYPE'} # storage_folder not included here (vulnerable)
def current_user_permissions():
return {'SETTINGS', 'ADD'} # user has SETTINGS and ADD
def is_admin():
return False
@app.route('/set_config', methods=['POST'])
def set_config():
key = request.form.get('key')
value = request.form.get('value')
if key in ADMIN_ONLY_OPTIONS and not is_admin():
return 'Forbidden', 403
# Vulnerability: non-admins can set STORAGE_FOLDER or other critical keys if not whitelisted
app.config[key] = value
return 'OK'
# Attack scenario: an attacker with SETTINGS/ADD changes STORAGE_FOLDER to a path under the session dir and drops a crafted pickle payload.
if __name__ == '__main__':
app.run()
Fixed pattern:
from flask import Flask, request
# Avoid server-side pickle-based sessions by using default client-side signed cookies
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secure-secret-key'
# Explicitly include STORAGE_FOLDER in admin-only keys to prevent non-admin modification
ADMIN_ONLY_OPTIONS = {'SECRET_KEY', 'SESSION_TYPE', 'SESSION_FILE_DIR', 'STORAGE_FOLDER'}
ALLOW_CONFIG_KEYS = {'APP_TITLE', 'LOG_LEVEL', 'WELCOME_MESSAGE'}
def is_admin():
return False
def can_modify(key):
if key in ADMIN_ONLY_OPTIONS and not is_admin():
return False
if key in ALLOW_CONFIG_KEYS or key not in ALLOW_CONFIG_KEYS and key in ADMIN_ONLY_OPTIONS:
return True
return False
@app.route('/set_config', methods=['POST'])
def set_config_fix():
key = request.form.get('key')
value = request.form.get('value')
if not key or not value:
return 'Bad Request', 400
if not can_modify(key):
return 'Forbidden', 403
app.config[key] = value
return 'OK'
if __name__ == '__main__':
app.run()