Skip to content

[Aikido] Fix 17 security issues in jinja2, flask, werkzeug and 2 more#20

Open
aikido-autofix[bot] wants to merge 1 commit into
masterfrom
fix/aikido-security-update-packages-58966820-rdpg
Open

[Aikido] Fix 17 security issues in jinja2, flask, werkzeug and 2 more#20
aikido-autofix[bot] wants to merge 1 commit into
masterfrom
fix/aikido-security-update-packages-58966820-rdpg

Conversation

@aikido-autofix

@aikido-autofix aikido-autofix Bot commented Jul 1, 2026

Copy link
Copy Markdown

Upgrade Jinja2, Flask, and Werkzeug to fix sandbox escapes, privilege escalation, session cookie leakage, and path traversal vulnerabilities. This update includes breaking changes that require manual migration.

⚠️ Code affected by breaking changes.

⚠️ This codebase is currently running Python 2.7.13 (as specified in runtime.txt) and upgrading to the specified package versions will cause multiple breaking changes:

1. Python Version Incompatibility

  • Where your code is affected: Entire codebase, specifically runtime.txt (line 1), requestbin/__init__.py (line 3), requestbin/models.py (line 56)

  • Impact: Flask 2.0+ requires Python 3.6+, Werkzeug 2.0+ requires Python 3.6+, Jinja2 3.0+ requires Python 3.6+, and Flask-Cors 4.0+ requires Python 3.8+. The current Python 2.7.13 runtime is incompatible.

  • Remediation: Upgrade to Python 3.8 or higher and update all Python 2-specific code (cStringIO, xrange, print statements, etc.)

2. cStringIO Import (Python 2 only)

  • Where your code is affected: requestbin/__init__.py (line 3)

  • Impact: from cStringIO import StringIO will fail as cStringIO doesn't exist in Python 3.

  • Remediation: Replace from cStringIO import StringIO with from io import BytesIO or from io import StringIO depending on whether you need bytes or text

3. xrange (Python 2 only)

  • Where your code is affected: requestbin/models.py (line 56)

  • Impact: xrange doesn't exist in Python 3, causing a NameError.

  • Remediation: Replace xrange with range

4. werkzeug.contrib.fixers.ProxyFix Import

  • Where your code is affected: requestbin/__init__.py (line 41)

  • Impact: werkzeug.contrib module was removed in Werkzeug 1.0. ProxyFix moved to a new location.

  • Remediation: Change from werkzeug.contrib.fixers import ProxyFix to from werkzeug.middleware.proxy_fix import ProxyFix

5. flask.escape Import

  • Where your code is affected: requestbin/views.py (line 2)

  • Impact: escape was removed from Flask in version 2.0 and should be imported from MarkupSafe instead.

  • Remediation: Change from flask import escape to from markupsafe import escape (though the function is imported but never used in the code, so it can also be removed)

6. request.values Usage

  • Where your code is affected: requestbin/models.py (line 76)

  • Impact: In Werkzeug 2.0+, request.values does not include form data for GET requests, and the behavior has changed.

  • Remediation: Review the usage of input.values[k] and consider using input.form.getlist(k) or input.form[k] explicitly instead

7. app.debug Direct Assignment

  • Where your code is affected: requestbin/__init__.py (line 44)

  • Impact: While not strictly breaking, directly setting app.debug is deprecated in favor of using app.config['DEBUG'].

  • Remediation: Replace app.debug = config.DEBUG with app.config['DEBUG'] = config.DEBUG

All breaking changes by upgrading jinja2 from version 2.7 to 3.1.4 (CHANGELOG)

Version Description
2.8.0
Added a check for default arguments followed by non-default arguments. This change makes {% macro m(x, y=1, z) %} a syntax error. The previous behavior for this code was broken anyway (resulting in the default value being applied to y).
2.9.0
Corrected a long standing issue with operator precedence of math operations not being what was expected.
2.9.0
Change the logic for macro autoescaping to be based on the runtime autoescaping information at call time instead of macro define time.
2.9.0
Tests now no longer accept an arbitrary expression as first argument but a restricted one.
2.9.0
Greatly changed the scoping system to be more consistent with what template designers and developers expect. There is now no more magic difference between the different include and import constructs.
2.10.0
import statement cannot end with a trailing comma.
2.10.0
indent filter will not indent blank lines by default.
2.11.0
Drop support for Python 2.6, 3.3, and 3.4.
2.11.0
The environment's finalize function is only applied to the output of expressions (constant or not), not static template data.
2.11.0
Always return Undefined when omitting the else clause in a {{ 'foo' if bar }} expression, regardless of the environment's undefined class.
2.11.0
Compiling templates always writes UTF-8 instead of defaulting to the system encoding.
3.0.0
Drop support for Python 2.7 and 3.5.
3.0.0
Bump MarkupSafe dependency to >=1.1.
3.0.0
Remove code that was marked deprecated.
3.0.0
The urlize filter recognizes mailto: links and takes extra_schemes to recognize other schemes. URLs without a scheme are linked as https:// instead of http://.
3.0.0
Undefined.__contains__ (in) raises an UndefinedError instead of a TypeError.
3.0.0
Template rendering only treats \n, \r\n and \r as line breaks. Other characters are left unchanged.
3.0.0
Async support no longer requires Jinja to patch itself. It must still be enabled with Environment(enable_async=True).
3.1.0
Drop support for Python 3.6.
3.1.0
Remove previously deprecated code including WithExtension and AutoEscapeExtension now built-in, contextfilter/contextfunction replaced by pass_context, evalcontextfilter/evalcontextfunction replaced by pass_eval_context, environmentfilter/environmentfunction replaced by pass_environment.
3.1.0
Markup and escape should be imported from MarkupSafe.
3.1.0
Compiled templates from very old Jinja versions may need to be recompiled.
3.1.0
Legacy resolve mode for Context subclasses is no longer supported. Override resolve_or_missing instead of resolve.
3.1.0
unicode_urlencode is renamed to url_quote.
3.1.0
The groupby filter is case-insensitive by default, matching other comparison filters.

All breaking changes by upgrading flask from version 0.10.1 to 2.2.5 (CHANGELOG)

Version Description
0.11.0
Templates are no longer automatically reloaded outside of debug mode. This can be configured with the new TEMPLATES_AUTO_RELOAD config key.
0.11.0
Removed deprecated module functionality.
0.12.0
Mimetype guessing and ETag generation for file-like objects in send_file has been removed.
0.12.0
Mimetype guessing in send_file now fails loudly and doesn't fall back to application/octet-stream.
1.0.0
Python 2.6 and 3.3 are no longer supported.
1.0.0
Bump minimum dependency versions to the latest stable versions: Werkzeug >= 0.14, Jinja >= 2.10, itsdangerous >= 0.24, Click >= 5.1.
1.0.0
Change the default for JSONIFY_PRETTYPRINT_REGULAR to False.
1.0.0
Flask.make_response raises TypeError instead of ValueError for bad response types.
1.0.0
Set APPLICATION_ROOT to '/' by default.
1.0.0
TRAP_BAD_REQUEST_ERRORS is enabled by default in debug mode.
1.0.0
Removed error handler caching because it caused unexpected results for some exception inheritance hierarchies.
1.0.0
The following old deprecated code was removed: flask.ext, Flask.init_jinja_globals, Flask.error_handlers, Flask.request_globals_class, Flask.static_path, Request.module.
1.0.0
Flask.logger has been simplified. LOGGER_NAME and LOGGER_HANDLER_POLICY config was removed.
1.0.0
Blueprint view function names may not contain dots.
1.0.0
The development server uses threads by default.
1.0.0
Subdomain matching is disabled by default and setting SERVER_NAME does not implicitly enable it.
1.0.0
Request.get_json no longer accepts arbitrary encodings. Incoming JSON should be encoded using UTF-8 per RFC 8259, but Flask will autodetect UTF-8, -16, or -32.
1.1.0
Bump minimum Werkzeug version to >= 0.15.
1.1.0
Drop support for Python 3.4.
1.1.0
Error handlers for InternalServerError or 500 will always be passed an instance of InternalServerError. The original exception is now available as e.original_exception rather than being passed directly to the handler.
1.1.0
Flask.logger takes the same name as Flask.name (the value passed as Flask(import_name)). This reverts 1.0's behavior of always logging to "flask.app".
2.0.0
Drop support for Python 2 and 3.5.
2.0.0
Bump minimum versions of other Pallets projects: Werkzeug >= 2, Jinja2 >= 3, MarkupSafe >= 2, ItsDangerous >= 2, Click >= 8.
2.0.0
JSON support no longer uses simplejson.
2.0.0
When returning a (response, headers) tuple from a view, the headers replace rather than extend existing headers on the response.
2.0.0
send_file sets conditional=True and max_age=None by default. Cache-Control is set to no-cache if max_age is not set, otherwise public.
2.0.0
Set the default encoding to "UTF-8" when loading .env and .flaskenv files.
2.1.0
Drop support for Python 3.6.
2.1.0
Update Click dependency to >= 8.0.
2.1.0
Remove previously deprecated code: CLI does not pass script_info to app factory functions, config.from_json is replaced, json functions no longer take an encoding parameter, safe_join is removed, total_seconds is removed, the same blueprint cannot be registered with the same name, the test client's as_tuple parameter is removed.
2.2.0
Remove previously deprecated code: old names for send_file parameters have been removed, RequestContext.g property is removed.
2.2.0
Update Werkzeug dependency to >= 2.2.
2.2.0
The app and request contexts are managed using Python context vars directly rather than Werkzeug's LocalStack.
2.2.0
Remove the --eager-loading/--lazy-loading options from the flask run command. The app is always eager loaded the first time, then lazily loaded in the reloader.

All breaking changes by upgrading werkzeug from version 0.9.3 to 3.1.6 (CHANGELOG)

Version Description
0.10.0
Use stdlib ssl module instead of OpenSSL for the builtin server. OpenSSL contexts are not supported anymore, but instead ssl.SSLContext from the stdlib.
0.10.0
wrappers.Request.method is now always uppercase, eliminating inconsistencies of the WSGI environment.
0.11.0
mimetype parameters on request and response classes are now always converted to lowercase.
0.11.0
Changed cache so that cache never expires if timeout is 0. This also fixes an issue with redis setex.
0.12.0
The defaults of generate_password_hash have been changed to more secure ones.
0.12.0
Change Accept datastructure to sort by specificity first, allowing for more accurate results when using best_match for mime types.
0.13.0
response.age is parsed as a timedelta. Previously, it was incorrectly treated as a datetime.
0.13.0
Authorization.qop is a string instead of a set, to comply with RFC 2617.
0.13.0
An exception is raised when an encoded cookie is larger than, by default, 4093 bytes.
0.14.0
HTTP exceptions are now automatically caught by Request.application.
0.14.0
get_multi on cache clients now returns lists all the time.
0.14.0
The built-in HTTP server will no longer close a connection in cases where no HTTP body is expected (204, 204, HEAD requests etc.)
0.14.0
Werkzeug will no longer send the content-length header on 1xx or 204/304 responses.
0.16.0
Request cookies are parsed into a MultiDict to capture all values for cookies with the same key. cookies[key] returns the first value rather than the last.
0.16.0
Map and Rule have a merge_slashes option to collapse multiple slashes into one, similar to how many HTTP servers behave. This is enabled by default.
0.16.0
Range requests that span an entire file respond with 206 instead of 200, to be more compliant with RFC 7233.
0.16.0
The SharedDataMiddleware default fallback_mimetype is application/octet-stream. If a filename looks like a text mimetype, the utf-8 charset is added to it.
1.0.0
Drop support for Python 3.4.
2.0.0
Drop support for Python 2 and 3.5.
2.0.0
All datetime values are timezone-aware with tzinfo=timezone.utc.
2.0.0
Merge all request and response wrapper mixin code into single Request and Response classes. Using the mixin classes is no longer necessary and will show a deprecation warning.
2.0.0
Response.get_json() no longer caches the result, and the cache parameter is removed.
2.0.0
Response.freeze() generates an ETag header if one is not set. The no_etag parameter is no longer used.
2.0.0
The response generated by Unauthorized produces one WWW-Authenticate header per value in www_authenticate, rather than joining them into a single value.
2.0.0
Switch the parameter order of default_stream_factory to match the order used when calling it.
2.0.0
send_file sets conditional=True and max_age=None by default. Cache-Control is set to no-cache if max_age is not set, otherwise public.
2.0.0
Update the defaults used by generate_password_hash. Increase PBKDF2 iterations to 260000 from 150000. Increase salt length to 16 from 8.
2.0.0
The test Client request methods always return an instance of TestResponse. In addition to the normal behavior of Response, this class provides request with the request that produced the response, and history to track intermediate responses when follow_redirects is used.
2.0.0
Cookie names are no longer unquoted. This was against RFC 6265 and potentially allowed setting __Secure prefixed cookies.
2.0.0
Use SHA-1 instead of MD5 for generating ETags and the debugger pin, and in some tests.
2.0.0
LocalProxy matches the current Python data model special methods, including all r-ops, in-place ops, and async. __class__ is proxied, so the proxy will look like the object in more cases, including isinstance. Use issubclass(type(obj), LocalProxy) to check if an object is actually a proxy.
2.0.0
Local uses ContextVar on Python 3.7+ instead of threading.local.
2.0.0
request.values does not include form for GET requests.
2.1.0
Drop support for Python 3.6.
2.1.0
Using gevent or eventlet requires greenlet>=1.0 or PyPy>=7.3.7.
2.1.0
When passing a dict of URL values to Map.build, list values do not filter out None or collapse to a single value. Passing a MultiDict does collapse single items.
2.1.0
The development server uses HTTP/1.1, which enables keep-alive connections and chunked streaming responses, when threaded or processes is enabled.
2.1.0
The default status code for append_slash_redirect is 308 instead of 301.
2.1.0
Response.autocorrect_location_header is disabled by default. The Location header URL will remain relative, and exclude the scheme and domain, by default.
2.1.0
Request.get_json() will raise a 400 BadRequest error if the Content-Type header is not application/json.
2.2.0
If a custom converter needs to match a / it must set the class variable part_isolating = False.
2.3.0
Drop support for Python 3.7.
2.3.0
Request.get_json() will raise a 415 Unsupported Media Type error if the Content-Type header is not application/json, instead of a generic 400.
2.3.0
A URL converter's part_isolating defaults to False if its regex contains a /.
...

All breaking changes by upgrading flask-cors from version 3.0.2 to 3.0.9 (CHANGELOG)

Version Description
3.0.3
If always_send=True, and '*' is in the allowed origins, and a request is made without an Origin header, no Access-Control-Allow-Origins header will now be returned (previously this header was sent, but this was a bug)

All breaking changes by upgrading Flask-Cors from version 3.0.2 to 3.0.9 (CHANGELOG)

Version Description
3.0.3
If always_send=True, and '*' is in the allowed origins, and a request is made without an Origin header, no Access-Control-Allow-Origins header will now be returned (previously this header was sent, but this was a bug)
✅ 17 CVEs resolved by this upgrade

This PR will resolve the following CVEs:

Issue Severity           Description
CVE-2016-10745
HIGH
[jinja2] In Pallets Jinja before 2.8.1, str.format allows a sandbox escape.
CVE-2014-1402
HIGH
[jinja2] The default configuration for bccache.FileSystemBytecodeCache in Jinja2 before 2.7.2 does not properly create temporary files, which allows local users to gain privileges via a crafted .cache file with a name starting with _jinja2 in /tmp.
CVE-2019-10906
HIGH
[jinja2] In Pallets Jinja before 2.10.1, str.format_map allows a sandbox escape.
CVE-2014-0012
MEDIUM
[jinja2] FileSystemBytecodeCache in Jinja2 2.7.2 does not properly create temporary directories, which allows local users to gain privileges by pre-creating a temporary directory with a user's uid. NOTE: this vulnerability exists because of an incomplete fix for CVE-2014-1402.
CVE-2024-34064
MEDIUM
[jinja2] The xmlattr filter fails to properly sanitize attribute keys, allowing injection of special characters (/, >, =) that enable XSS attacks when user-controlled keys are rendered in XML/HTML attributes.
CVE-2020-28493
LOW
[jinja2] A ReDoS vulnerability in the urlize filter's _punctuation_re regex allows attackers to cause denial of service through specially crafted input with multiple wildcards. Mitigation includes using Markdown for user content formatting or implementing request timeouts and memory limits.
CVE-2023-30861
HIGH
[flask] A caching proxy vulnerability allows session cookies to be cached and sent to unintended clients when specific conditions align, including permanent sessions, no session access during requests, and missing cache-control headers. This can lead to information disclosure or session hijacking depending on application behavior and proxy configuration.
CVE-2019-1010083
MEDIUM
[flask] The Pallets Project Flask before 1.0 is affected by: unexpected memory usage. The impact is: denial of service. The attack vector is: crafted encoded JSON data. The fixed version is: 1. NOTE: this may overlap CVE-2018-1000656.
CVE-2019-14322
HIGH
[werkzeug] In Pallets Werkzeug before 0.15.5, SharedDataMiddleware mishandles drive names (such as C:) in Windows pathnames.
CVE-2019-14806
MEDIUM
[werkzeug] Pallets Werkzeug before 0.15.3, when used with Docker, has insufficient debugger PIN randomness because Docker containers share the same machine id.
CVE-2023-25577
MEDIUM
[werkzeug] The multipart form data parser accepts unlimited parts without restriction, allowing attackers to cause denial of service through excessive CPU and memory consumption. Sending crafted multipart requests to endpoints accessing form/file data can exhaust worker processes and trigger out-of-memory conditions.
CVE-2024-34069
MEDIUM
[werkzeug] The debugger can be exploited for remote code execution if an attacker tricks a developer into visiting a controlled domain and entering the debugger PIN, then guesses a URL that triggers the debugger. This bypasses localhost-only protections.
CVE-2016-10516
MEDIUM
[werkzeug] A cross-site scripting (XSS) vulnerability in the debugger's render_full function allows remote attackers to inject arbitrary web script or HTML through exception messages. This enables attackers to execute malicious code in users' browsers when viewing debug information.
CVE-2026-27199
MEDIUM
[werkzeug] A path traversal vulnerability in the safe_join function allows Windows device names (like NUL) as filenames when preceded by path segments, causing file read operations to hang indefinitely when serving files through send_from_directory on Windows systems. This bypasses previous security filtering that didn't account for multi-segment paths.
CVE-2020-28724
MEDIUM
[werkzeug] Open redirect vulnerability in werkzeug before 0.11.6 via a double slash in the URL.
CVE-2020-25032
MEDIUM
[flask-cors] An issue was discovered in Flask-CORS (aka CORS Middleware for Flask) before 3.0.9. It allows ../ directory traversal to access private resources because resource matching does not ensure that pathnames are in a canonical format.
AIKIDO-2024-10084
MEDIUM
[Flask-Cors] A log injection vulnerability allows attackers to inject fake log entries by sending requests with CRLF sequences in the path, enabling log file corruption and covering attack tracks when debug logging is enabled.

@aikido-autofix aikido-autofix Bot added the security Label created by Aikido AutoFix label Jul 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

security Label created by Aikido AutoFix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants