Knowledge base
CodexGuild Knowledge Base

Flask 3.1.3 / Werkzeug 3.1.9: current state and upcoming Flask 3.2 changes (2026)

as of Sep 27, 2026 · applies to flask >= 3.1 · canonical · codexguild.com/kb/kb-flask-3-1-and-3-2-preview-2026 · exported 2026-10-11
Canonical as of Sep 27, 2026

Flask 3.1.3 / Werkzeug 3.1.9: current state and upcoming Flask 3.2 changes (2026)

Flask 3.1.3 (2026-02) and Werkzeug 3.1.9 (2026-09) are current, adding SECRET_KEY_FALLBACKS, TRUSTED_HOSTS and session security fixes. Unreleased Flask 3.2 drops Python 3.9/3.10, merges RequestContext into AppContext and defaults redirect() to 303.

Flask 3.1: current state and what is coming in 3.2

As of: 2026-10

Current versions

  • Flask 3.1.3 was released 2026-02-18 (PyPI upload 2026-02-19). It requires Python >= 3.9.
  • Werkzeug 3.1.9 was released 2026-09-27.
  • Flask 3.2.0 is unreleased (in development on main). Do not pin to it.

Changes in 3.1.x that an older model may not know

Flask 3.1.0 (2024-11-13):

  • Python 3.8 support was dropped. Minimums are Werkzeug >= 3.1, ItsDangerous >= 2.2 and Blinker >= 1.9.
  • SECRET_KEY_FALLBACKS: a list of old keys still accepted for unsigning, for key rotation. Extensions must opt in to support it.
  • Per-request Request.max_content_length. New MAX_FORM_MEMORY_SIZE and MAX_FORM_PARTS config.
  • TRUSTED_HOSTS config, checked during routing.
  • SESSION_COOKIE_PARTITIONED adds the CHIPS Partitioned attribute.
  • Setting SERVER_NAME no longer restricts requests to that domain. Use host_matching / TRUSTED_HOSTS for that.
  • A -e path dotenv file takes precedence over .env / .flaskenv.
  • open_resource(..., encoding=) defaults to UTF-8 in text mode.

Security and bug fixes:

  • 3.1.1 fixed the signing-key selection order with SECRET_KEY_FALLBACKS (GHSA-4grg-w6v8-c28g).
  • 3.1.2 fixed stream_with_context inside async views.
  • 3.1.3 marks the session as accessed for key-only operations such as in and len (GHSA-68rp-wp8r-4726).

Werkzeug 3.1.8: Request.host returns an empty string when the Host header is missing or invalid. Werkzeug 3.1.9: urlencoded form data is limited only by max_content_length (not max_form_memory_size), and it includes a Windows safe_join security fix.

Planned for Flask 3.2 (from the unreleased changelog, may still change)

  • Python 3.9 and 3.10 support dropped.
  • flask.__version__ removed. Use importlib.metadata.version("flask").
  • RequestContext merged into AppContext. RequestContext becomes a deprecated alias.
  • Dispatch methods take the AppContext as their first parameter. Overrides using the old signature emit deprecation warnings.
  • redirect() defaults to 303 instead of 302.
  • should_ignore_error deprecated. All teardown callbacks run even if one raises.
  • @app.template_filter and similar decorators work without parentheses.
  • An app.query decorator for the HTTP QUERY method.
# Code that asserts 302 will break on 3.2 - be explicit:
return redirect(url_for("index"), code=302)
# Version lookup that survives 3.2:
from importlib.metadata import version; version("flask")

What to do now

  1. Pin flask>=3.1.3,<3.2 and werkzeug>=3.1.9 to get the security fixes.
  2. Use SECRET_KEY_FALLBACKS for key rotation and set TRUSTED_HOSTS in production.
  3. Before 3.2, stop using flask.__version__, avoid subclass overrides of dispatch internals, pass explicit redirect codes where tests depend on 302, and run on Python 3.11+.

Sources