[Aikido] Fix 33 security issues in jinja2, flask, werkzeug and 2 more#19
Open
aikido-autofix[bot] wants to merge 1 commit intomasterfrom
Open
[Aikido] Fix 33 security issues in jinja2, flask, werkzeug and 2 more#19aikido-autofix[bot] wants to merge 1 commit intomasterfrom
aikido-autofix[bot] wants to merge 1 commit intomasterfrom
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Upgrade Jinja2, Flask, Werkzeug, and Flask-CORS to fix multiple sandbox escape RCE vulnerabilities and privilege escalation issues. This update includes breaking changes that require manual migration.
1. Python 2 to Python 3 incompatibility
Where affected:
requestbin/__init__.py:3- Usesfrom cStringIO import StringIO(Python 2 only)requestbin/filters.py:9,73,78,85,115- Useslongtype which doesn't exist in Python 3requestbin/filters.py:115- Usesunicodetype which doesn't exist in Python 3requestbin/models.py:58- Usesxrange()which doesn't exist in Python 3Impact: Code will fail with
ImportErrorandNameErroras these Python 2 constructs don't exist in Python 3. Flask 3.1.3, Werkzeug 3.1.6, and Jinja2 3.1.6 all require Python 3.8+.Remediation: Replace
cStringIO.StringIOwithio.BytesIO, replacelongwithint, replaceunicodewithstr, and replacexrangewithrange.2. Werkzeug
contrib.fixers.ProxyFixremovedWhere affected:
requestbin/__init__.py:42- Importsfrom werkzeug.contrib.fixers import ProxyFixImpact:
werkzeug.contribmodule was removed in Werkzeug 1.0+. This will cause anImportError.Remediation: Change import to
from werkzeug.middleware.proxy_fix import ProxyFix.3. Werkzeug
request.valuesbehavior change with GET requestsWhere affected:
requestbin/models.py:77- Usesinput.values[k]whereinputis a Flask/Werkzeug request objectImpact: In Werkzeug 2.0+,
request.valuesdoes not includeformdata for GET requests. Since the code iterates overinput.formand then accessesinput.values[k], this may cause unexpected behavior or KeyError if the request method is GET.Remediation: Use
input.form[k]directly instead ofinput.values[k]since the code is already iterating overinput.form.4. Flask
escapeimport locationWhere affected:
requestbin/views.py:2- ImportsescapefromflaskImpact: In Flask 2.2+,
escapeshould be imported frommarkuplib(MarkupSafe), not from Flask directly. While Flask may still provide it for backwards compatibility in 3.x, it's deprecated.Remediation: Change import to
from markupsafe import escape.All breaking changes by upgrading jinja2 from version 2.7 to 3.1.6 (CHANGELOG)
{% 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 toy).importstatement cannot end with a trailing comma.indentfilter will not indent blank lines by default.finalizefunction is only applied to the output of expressions (constant or not), not static template data.Undefinedwhen omitting theelseclause in a{{ 'foo' if bar }}expression, regardless of the environment'sundefinedclass.urlizefilter recognizesmailto:links and takesextra_schemesto recognize other schemes. URLs without a scheme are linked ashttps://instead ofhttp://.Undefined.__contains__(in) raises anUndefinedErrorinstead of aTypeError.\n,\r\nand\ras line breaks. Other characters are left unchanged.Environment(enable_async=True).WithExtensionandAutoEscapeExtensionnow built-in,contextfilter/contextfunctionreplaced bypass_context,evalcontextfilter/evalcontextfunctionreplaced bypass_eval_context,environmentfilter/environmentfunctionreplaced bypass_environment.Markupandescapeshould be imported from MarkupSafe.Contextsubclasses is no longer supported. Overrideresolve_or_missinginstead ofresolve.unicode_urlencodeis renamed tourl_quote.groupbyfilter is case-insensitive by default, matching other comparison filters.All breaking changes by upgrading flask from version 0.10.1 to 3.1.3 (CHANGELOG)
TEMPLATES_AUTO_RELOADconfig key.flask.templating.render_template_stringby default.send_filehas been removed.send_filenow fails loudly and doesn't fall back toapplication/octet-stream.JSONIFY_PRETTYPRINT_REGULARtoFalse.jsonifyreturns a compact format by default, and an indented format in debug mode.Flask.make_responseraisesTypeErrorinstead ofValueErrorfor bad response types.TRAP_BAD_REQUEST_ERRORSis enabled by default in debug mode.flask.ext,Flask.init_jinja_globals,Flask.error_handlers,Flask.request_globals_class,Flask.static_path,Request.module.Flask.loggerhas been simplified.LOGGER_NAMEandLOGGER_HANDLER_POLICYconfig was removed. The logger is always namedflask.app.Request.get_jsonno longer accepts arbitrary encodings. Incoming JSON should be encoded using UTF-8 per RFC 8259, but Flask will autodetect UTF-8, -16, or -32.SERVER_NAMEdoes not implicitly enable it. It can be enabled by passingsubdomain_matching=Trueto theFlaskconstructor.InternalServerErroror500will always be passed an instance ofInternalServerError. If they are invoked due to an unhandled exception, that original exception is now available ase.original_exceptionrather than being passed directly to the handler.Flask.loggertakes the same name asFlask.name(the value passed asFlask(import_name)). This reverts 1.0's behavior of always logging to"flask.app".script_infoto app factory functions;config.from_jsonis replaced byconfig.from_file(name, load=json.load);jsonfunctions no longer take anencodingparameter;safe_joinis removed;total_secondsis removed; The same blueprint cannot be registered with the same name; The test client'sas_tupleparameter is removed.send_fileparameters have been removed (download_namereplacesattachment_filename,max_agereplacescache_timeout,etagreplacesadd_etags);pathreplacesfilenameinsend_from_directory; TheRequestContext.gproperty returningAppContext.gis removed.LocalStack.before_first_requestis deprecated.pushandpopmethods of_app_ctx_stackand_request_ctx_stackare removed;FLASK_ENVenvironment variable,ENVconfig key, andapp.envproperty are removed;session_cookie_name,send_file_max_age_default,use_x_sendfile,propagate_exceptions, andtemplates_auto_reloadproperties onappare removed;JSON_AS_ASCII,JSON_SORT_KEYS,JSONIFY_MIMETYPE, andJSONIFY_PRETTYPRINT_REGULARconfig keys are removed;app.before_first_requestandbp.before_app_first_requestdecorators are removed;json_encoderandjson_decoderattributes on app and blueprint are removed;json.htmlsafe_dumpsandhtmlsafe_dumpfunctions are removed.blinker>=1.6.2is a required dependency.SESSION_COOKIE_DOMAINdoes not fall back toSERVER_NAME. The default is not to set the domain.host_matching=Trueorsubdomain_matching=Falseinteracts withSERVER_NAME. SettingSERVER_NAMEno longer restricts requests to only that domain.Request.trusted_hostsis checked during routing.All breaking changes by upgrading werkzeug from version 0.9.3 to 3.1.6 (CHANGELOG)
sslmodule instead ofOpenSSLfor the builtin server. OpenSSL contexts are not supported anymore, but insteadssl.SSLContextfrom the stdlib.wrappers.Request.methodis now always uppercase, eliminating inconsistencies of the WSGI environment.mimetypeparameters on request and response classes are now always converted to lowercase.generate_password_hashhave been changed to more secure ones.best_matchfor mime types.response.ageis parsed as atimedelta. Previously, it was incorrectly treated as adatetime.Authorization.qopis a string instead of a set, to comply with RFC 2617.Request.application.get_multion cache clients now returns lists all the time.MultiDictto capture all values for cookies with the same key.cookies[key]returns the first value rather than the last.MapandRulehave amerge_slashesoption to collapse multiple slashes into one, similar to how many HTTP servers behave. This is enabled by default.SharedDataMiddlewaredefaultfallback_mimetypeisapplication/octet-stream. If a filename looks like a text mimetype, theutf-8charset is added to it.datetimevalues are timezone-aware withtzinfo=timezone.utc.RequestandResponseclasses. Using the mixin classes is no longer necessary and will show a deprecation warning.Response.get_json()no longer caches the result, and thecacheparameter is removed.Response.freeze()generates anETagheader if one is not set. Theno_etagparameter is no longer used.Unauthorizedproduces oneWWW-Authenticateheader per value inwww_authenticate, rather than joining them into a single value.default_stream_factoryto match the order used when calling it.send_filesetsconditional=Trueandmax_age=Noneby default.Cache-Controlis set tono-cacheifmax_ageis not set, otherwisepublic.generate_password_hash. Increase PBKDF2 iterations to 260000 from 150000. Increase salt length to 16 from 8.Clientrequest methods always return an instance ofTestResponse. In addition to the normal behavior ofResponse, this class providesrequestwith the request that produced the response, andhistoryto track intermediate responses whenfollow_redirectsis used.__Secureprefixed cookies.LocalProxymatches 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, includingisinstance. Useissubclass(type(obj), LocalProxy)to check if an object is actually a proxy.LocalusesContextVaron Python 3.7+ instead ofthreading.local.request.valuesdoes not includeformfor GET requests.Map.build, list values do not filter outNoneor collapse to a single value. Passing aMultiDictdoes collapse single items.threadedorprocessesis enabled.append_slash_redirectis 308 instead of 301.Response.autocorrect_location_headeris disabled by default. TheLocationheader URL will remain relative, and exclude the scheme and domain, by default.Request.get_json()will raise a 400BadRequesterror if theContent-Typeheader is notapplication/json./it must set the class variablepart_isolating = False.Request.get_json()will raise a415 Unsupported Media Typeerror if theContent-Typeheader is notapplication/json, instead of a generic 400.part_isolatingdefaults toFalseif itsregexcontains a/.All breaking changes by upgrading flask-cors from version 3.0.2 to 6.0.0 (CHANGELOG)
All breaking changes by upgrading Flask-Cors from version 3.0.2 to 4.0.1 (CHANGELOG)
✅ 33 CVEs resolved by this upgrade
This PR will resolve the following CVEs:
xmlattrfilter can be abused to inject arbitrary HTML attributes, bypassing auto-escaping and enabling Cross-Site Scripting (XSS) attacks and potential attribute validation bypass.xmlattrfilter 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._punctuation_re regexallows 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.inoperator without proper cache control headers.