diff --git a/CVE-2018-1000656.patch b/CVE-2018-1000656.patch new file mode 100644 index 0000000000000000000000000000000000000000..c30fcd1f015edf43925461e396d3e9b9d42a1bbc --- /dev/null +++ b/CVE-2018-1000656.patch @@ -0,0 +1,148 @@ +diff --git a/flask/json.py b/flask/json.py +index 45ba3240..1ee0586e 100644 +--- a/flask/json.py ++++ b/flask/json.py +@@ -8,6 +8,7 @@ + :copyright: (c) 2012 by Armin Ronacher. + :license: BSD, see LICENSE for more details. + """ ++import codecs + import io + import uuid + from datetime import datetime +@@ -111,6 +112,49 @@ def _load_arg_defaults(kwargs): + kwargs.setdefault('cls', JSONDecoder) + + ++def detect_encoding(data): ++ """Detect which UTF codec was used to encode the given bytes. ++ ++ The latest JSON standard (:rfc:`8259`) suggests that only UTF-8 is ++ accepted. Older documents allowed 8, 16, or 32. 16 and 32 can be big ++ or little endian. Some editors or libraries may prepend a BOM. ++ ++ :param data: Bytes in unknown UTF encoding. ++ :return: UTF encoding name ++ """ ++ head = data[:4] ++ ++ if head[:3] == codecs.BOM_UTF8: ++ return 'utf-8-sig' ++ ++ if b'\x00' not in head: ++ return 'utf-8' ++ ++ if head in (codecs.BOM_UTF32_BE, codecs.BOM_UTF32_LE): ++ return 'utf-32' ++ ++ if head[:2] in (codecs.BOM_UTF16_BE, codecs.BOM_UTF16_LE): ++ return 'utf-16' ++ ++ if len(head) == 4: ++ if head[:3] == b'\x00\x00\x00': ++ return 'utf-32-be' ++ ++ if head[::2] == b'\x00\x00': ++ return 'utf-16-be' ++ ++ if head[1:] == b'\x00\x00\x00': ++ return 'utf-32-le' ++ ++ if head[1::2] == b'\x00\x00': ++ return 'utf-16-le' ++ ++ if len(head) == 2: ++ return 'utf-16-be' if head.startswith(b'\x00') else 'utf-16-le' ++ ++ return 'utf-8' ++ ++ + def dumps(obj, **kwargs): + """Serialize ``obj`` to a JSON formatted ``str`` by using the application's + configured encoder (:attr:`~flask.Flask.json_encoder`) if there is an +@@ -145,7 +189,10 @@ def loads(s, **kwargs): + """ + _load_arg_defaults(kwargs) + if isinstance(s, bytes): +- s = s.decode(kwargs.pop('encoding', None) or 'utf-8') ++ encoding = kwargs.pop('encoding', None) ++ if encoding is None: ++ encoding = detect_encoding(s) ++ s = s.decode(encoding) + return _json.loads(s, **kwargs) + + +diff --git a/flask/testsuite/helpers.py b/flask/testsuite/helpers.py +index 636f67fa..12e10d96 100644 +--- a/flask/testsuite/helpers.py ++++ b/flask/testsuite/helpers.py +@@ -15,6 +15,8 @@ import unittest + from logging import StreamHandler + from flask.testsuite import FlaskTestCase, catch_warnings, catch_stderr + from werkzeug.http import parse_cache_control_header, parse_options_header ++ ++from flask import json + from flask._compat import StringIO, text_type + + +@@ -29,6 +31,16 @@ def has_encoding(name): + + class JSONTestCase(FlaskTestCase): + ++ def test_detect_encoding(self): ++ values = (1, 't', True, False, None, [], [1,2,3], {}, {'foo': u'🐍'},) ++ encodings = ('utf-8', 'utf-8-sig', 'utf-16-le', 'utf-16-be', 'utf-16', 'utf-32-le', 'utf-32-be', 'utf-32',) ++ ++ for encoding in encodings: ++ for value in values: ++ data = json.dumps(value).encode(encoding) ++ self.assert_equal(json.detect_encoding(data), encoding) ++ self.assert_equal(json.loads(data),value) ++ + def test_json_bad_requests(self): + app = flask.Flask(__name__) + @app.route('/json', methods=['POST']) +@@ -38,18 +50,6 @@ class JSONTestCase(FlaskTestCase): + rv = c.post('/json', data='malformed', content_type='application/json') + self.assert_equal(rv.status_code, 400) + +- def test_json_body_encoding(self): +- app = flask.Flask(__name__) +- app.testing = True +- @app.route('/') +- def index(): +- return flask.request.get_json() +- +- c = app.test_client() +- resp = c.get('/', data=u'"Hällo Wörld"'.encode('iso-8859-15'), +- content_type='application/json; charset=iso-8859-15') +- self.assert_equal(resp.data, u'Hällo Wörld'.encode('utf-8')) +- + def test_jsonify(self): + d = dict(a=23, b=42, c=[1, 2, 3]) + app = flask.Flask(__name__) +diff --git a/flask/wrappers.py b/flask/wrappers.py +index 1a17824a..0d6f068d 100644 +--- a/flask/wrappers.py ++++ b/flask/wrappers.py +@@ -127,17 +127,10 @@ class Request(RequestBase): + if self.mimetype != 'application/json' and not force: + return None + +- # We accept a request charset against the specification as +- # certain clients have been using this in the past. This +- # fits our general approach of being nice in what we accept +- # and strict in what we send out. +- request_charset = self.mimetype_params.get('charset') ++ data = _get_data(self, cache) ++ + try: +- data = _get_data(self, cache) +- if request_charset is not None: +- rv = json.loads(data, encoding=request_charset) +- else: +- rv = json.loads(data) ++ rv = json.loads(data) + except ValueError as e: + if silent: + rv = None diff --git a/Flask-0.10.1.tar.gz b/Flask-0.10.1.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..f6a60a1d0c23f234fc94fb500b5a0cfc20bda710 Binary files /dev/null and b/Flask-0.10.1.tar.gz differ diff --git a/python-flask.spec b/python-flask.spec new file mode 100644 index 0000000000000000000000000000000000000000..011f79152f741633c2b5710a29b6771177df07e5 --- /dev/null +++ b/python-flask.spec @@ -0,0 +1,240 @@ +%if 0%{?fedora} > 12 +%global with_python3 1 +%else +%{!?python_sitelib: %global python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")} +%endif + +%global srcname Flask +%global srcversion 0.10.1 + +Name: python-flask +Version: 0.10.1 +Release: 5%{?dist} +Epoch: 1 +Summary: A micro-framework for Python based on Werkzeug, Jinja 2 and good intentions + +Group: Development/Libraries +License: BSD +URL: http://flask.pocoo.org/ +Source0: http://pypi.python.org/packages/source/F/Flask/%{srcname}-%{srcversion}.tar.gz +Patch0: CVE-2018-1000656.patch + +BuildArch: noarch +BuildRequires: python2-devel python-setuptools python-werkzeug python-sphinx +Requires: python-werkzeug + +%if 0%{?rhel} < 7 +BuildRequires: python-jinja2 +BuildRequires: python-itsdangerous +Requires: python-jinja2 +Requires: python-itsdangerous +%else +BuildRequires: python-jinja2 +BuildRequires: python-itsdangerous +Requires: python-jinja2 +Requires: python-itsdangerous +%endif + +%description +Flask is called a “micro-framework” because the idea to keep the core +simple but extensible. There is no database abstraction layer, no form +validation or anything else where different libraries already exist +that can handle that. However Flask knows the concept of extensions +that can add this functionality into your application as if it was +implemented in Flask itself. There are currently extensions for object +relational mappers, form validation, upload handling, various open +authentication technologies and more. + + +%package doc +Summary: Documentation for %{name} +Group: Documentation +Requires: %{name} = %{epoch}:%{version}-%{release} + +%description doc +Documentation and examples for %{name}. + +%if 0%{?with_python3} +%package -n python3-flask +Summary: A micro-framework for Python based on Werkzeug, Jinja 2 and good intentions +BuildRequires: python3-devel +BuildRequires: python3-setuptools +BuildRequires: python3-jinja2 +BuildRequires: python3-werkzeug +#BuildRequires: python3-sphinx +BuildRequires: python3-itsdangerous +Requires: python3-jinja2 +Requires: python3-werkzeug +Requires: python3-itsdangerous + +%description -n python3-flask +Flask is called a “micro-framework” because the idea to keep the core +simple but extensible. There is no database abstraction layer, no form +validation or anything else where different libraries already exist +that can handle that. However Flask knows the concept of extensions +that can add this functionality into your application as if it was +implemented in Flask itself. There are currently extensions for object +relational mappers, form validation, upload handling, various open +authentication technologies and more. + + +%package -n python3-flask-doc +Summary: Documentation for python3-flask +Group: Documentation +Requires: python3-flask = %{epoch}:%{version}-%{release} + +%description -n python3-flask-doc +Documentation and examples for python3-flask. +%endif + + +%prep +%setup -q -n %{srcname}-%{srcversion} +%patch0 -p1 +%{__sed} -i "/platforms/ a\ requires=['Jinja2 (>=2.4)']," setup.py + +%if 0%{?with_python3} +rm -rf %{py3dir} +cp -a . %{py3dir} +find %{py3dir} -name '*.py' | xargs sed -i '1s|^#!python|#!%{__python3}|' +%endif + + +%build +%{__python} setup.py build + +%if 0%{?with_python3} +pushd %{py3dir} +%{__python3} setup.py build +popd +%endif + + +%install +%{__python} setup.py install -O1 --skip-build --root %{buildroot} + +# Need to install flask in the setuptools "develop" mode to build docs +# The BuildRequires on Werkzeug, Jinja2 and Sphinx is due to this as well. +export PYTHONPATH=%{buildroot}%{python_sitelib} +%{__python} setup.py develop --install-dir %{buildroot}%{python_sitelib} +make -C docs html + +rm -rf %{buildroot}%{python_sitelib}/site.py +rm -rf %{buildroot}%{python_sitelib}/site.py[co] +rm -rf %{buildroot}%{python_sitelib}/easy-install.pth +rm -rf docs/_build/html/.buildinfo +rm -rf examples/minitwit/*.pyc +rm -rf examples/flaskr/*.pyc +rm -rf examples/jqueryexample/*.pyc + +%if 0%{?with_python3} +pushd %{py3dir} +%{__python3} setup.py install -O1 --skip-build --root %{buildroot} + +# Need to install flask in the setuptools "develop" mode to build docs +# The BuildRequires on Werkzeug, Jinja2 and Sphinx is due to this as well. +export PYTHONPATH=%{buildroot}%{python3_sitelib} +%{__python3} setup.py develop --install-dir %{buildroot}%{python3_sitelib} +#make -C docs html + +rm -rf %{buildroot}%{python3_sitelib}/site.py +rm -rf %{buildroot}%{python3_sitelib}/site.py[co] +rm -rf %{buildroot}%{python3_sitelib}/easy-install.pth +rm -rf %{buildroot}%{python3_sitelib}/__pycache__/site.cpython-33.pyc +rm -rf docs/_build/html/.buildinfo +rm -rf examples/minitwit/*.pyc +rm -rf examples/flaskr/*.pyc +rm -rf examples/jqueryexample/*.pyc +popd +%endif + + +%check +%{__python} setup.py test + +#if 0%{?with_python3} +#pushd %{py3dir} +#{__python3} setup.py test +#popd +#endif + + +%files +%doc AUTHORS LICENSE PKG-INFO CHANGES README +%{python_sitelib}/*.egg-info +%{python_sitelib}/*.egg-link +%{python_sitelib}/flask + +%files doc +%doc docs/_build/html examples + +%if 0%{?with_python3} +%files -n python3-flask +%doc AUTHORS LICENSE PKG-INFO CHANGES README +%{python3_sitelib}/*.egg-info +%{python3_sitelib}/*.egg-link +%{python3_sitelib}/flask + +%files -n python3-flask-doc +%doc docs/_build/html examples +%endif + + +%changelog +* Tue Mar 03 2020 Josh Boyer - 1:0.10.1-5 +- Fix CVE-2018-1000656 Denial of Service via crafted JSON (RHBZ #1810065) + +* Tue Apr 29 2014 Lokesh Mandvekar - 1:0.10.1-4 +- Rebuilt for RHEL 7 +- tests disabled + +* Mon Jul 29 2013 Haïkel Guémar - 1:0.10.1-3 +- fix wrong requires on sphinx (RHBZ #989361) + +* Sat Jul 20 2013 Ricky Elrod - 1:0.10.1-2 +- Nuke a Python3 specific file owned by python3-setuptools. + +* Sat Jun 15 2013 Haïkel Guémar - 1:0.10.1-1 +- upstream 0.10.1 + +* Thu Feb 14 2013 Fedora Release Engineering - 1:0.9-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Fri Aug 17 2012 Ricky Elrod - 0.9-5 +- Add epoch to subpackage Requires. + +* Wed Aug 8 2012 Ricky Elrod - 0.9-4 +- Fix changelog messup. + +* Wed Aug 8 2012 Ricky Elrod - 0.9-3 +- Unified spec for EL6 and Fedora + +* Sat Jul 21 2012 Fedora Release Engineering - 0.9.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Mon Jul 2 2012 Haïkel Guémar - 0.9.0-1 +- upstream 0.9 +- spec cleanups + +* Sun Jul 1 2012 Haïkel Guémar - 0.8.1-1 +- upstream 0.8.1 (minor bugfixes) + +* Wed Jan 25 2012 Haïkel Guémar - 0.8.0-1 +- upstream 0.8 + +* Sat Jan 14 2012 Fedora Release Engineering - 0.7.2-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Wed Nov 16 2011 Dan Young - 0.7.2-2 +- don't own easy-install.pth + +* Fri Jul 22 2011 Steve Milner - 0.7.2-1 +- update for upstream release + +* Thu Feb 24 2011 Dan Young - 0.6.1-2 +- fix rpmlint spelling warning +- BR python2-devel rather than python-devel +- run test suite in check + +* Tue Feb 22 2011 Dan Young - 0.6.1-1 +- Initial package