Hello community,
here is the log from the commit of package python-django-debreach for
openSUSE:Leap:15.2 checked in at 2020-02-23 16:47:20
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Leap:15.2/python-django-debreach (Old)
and /work/SRC/openSUSE:Leap:15.2/.python-django-debreach.new.26092 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-django-debreach"
Sun Feb 23 16:47:20 2020 rev:3 rq:776569 version:2.0.1
Changes:
--------
---
/work/SRC/openSUSE:Leap:15.2/python-django-debreach/python-django-debreach.changes
2020-01-15 15:48:37.527432250 +0100
+++
/work/SRC/openSUSE:Leap:15.2/.python-django-debreach.new.26092/python-django-debreach.changes
2020-02-23 16:47:21.278307162 +0100
@@ -1,0 +2,12 @@
+Wed Oct 30 12:04:59 UTC 2019 - Tomáš Chvátal <[email protected]>
+
+- Update to 2.0.1:
+ * Drop python2 support upstream
+ * Various tests and description fixes
+
+-------------------------------------------------------------------
+Fri Oct 18 20:24:18 UTC 2019 - Dirk Mueller <[email protected]>
+
+- switch to python3 only (Django 2.x)
+
+-------------------------------------------------------------------
Old:
----
django-debreach-1.5.2.tar.gz
New:
----
django-debreach-2.0.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-django-debreach.spec ++++++
--- /var/tmp/diff_new_pack.pMrlNY/_old 2020-02-23 16:47:21.622307824 +0100
+++ /var/tmp/diff_new_pack.pMrlNY/_new 2020-02-23 16:47:21.622307824 +0100
@@ -17,19 +17,18 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
+%define skip_python2 1
Name: python-django-debreach
-Version: 1.5.2
+Version: 2.0.1
Release: 0
Summary: Middleware to protect against the BREACH attack in Django
License: BSD-2-Clause
-Group: Development/Languages/Python
-URL: http://github.com/lpomfrey/django-debreach
+URL: https://github.com/lpomfrey/django-debreach
Source:
https://files.pythonhosted.org/packages/source/d/django-debreach/django-debreach-%{version}.tar.gz
BuildRequires: %{python_module Django}
BuildRequires: %{python_module setuptools}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
-BuildRequires: python python3
Requires: python-Django
BuildArch: noarch
%python_subpackages
++++++ django-debreach-1.5.2.tar.gz -> django-debreach-2.0.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-debreach-1.5.2/PKG-INFO
new/django-debreach-2.0.1/PKG-INFO
--- old/django-debreach-1.5.2/PKG-INFO 2018-08-31 15:32:05.000000000 +0200
+++ new/django-debreach-2.0.1/PKG-INFO 2019-10-10 11:09:54.000000000 +0200
@@ -1,7 +1,7 @@
Metadata-Version: 1.1
Name: django-debreach
-Version: 1.5.2
-Summary: Adds middleware and context processors to give some protection
against the BREACH attack in Django.
+Version: 2.0.1
+Summary: Adds middleware to give some added protection against the BREACH
attack in Django.
Home-page: http://github.com/lpomfrey/django-debreach
Author: Luke Pomfrey
Author-email: [email protected]
@@ -14,14 +14,9 @@
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Framework :: Django
-Classifier: Framework :: Django :: 1.8
-Classifier: Framework :: Django :: 1.11
-Classifier: Framework :: Django :: 2.0
+Classifier: Framework :: Django :: 2.2
Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: Implementation :: CPython
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-debreach-1.5.2/README.rst
new/django-debreach-2.0.1/README.rst
--- old/django-debreach-1.5.2/README.rst 2016-08-13 13:15:42.000000000
+0200
+++ new/django-debreach-2.0.1/README.rst 2019-10-10 09:58:23.000000000
+0200
@@ -4,6 +4,12 @@
Basic/extra mitigation against the `BREACH attack <http://breachattack.com/>`_
for Django projects.
+django-debreach provides additional protection to Django's built in CSRF
+token masking by randomising the content length of each response. This is
+acheived by adding a random string of between 12 and 25 characters as a
+comment to the end of the HTML content. Note that this will only be applied to
+responses with a content type of ``text/html``.
+
When combined with rate limiting in your web-server, or by using something
like `django-ratelimit <http://django-ratelimit.readthedocs.org/>`_, the
techniques here should provide at least some protection against the BREACH
@@ -20,89 +26,13 @@
:target: https://coveralls.io/r/lpomfrey/django-debreach?branch=master
:alt: Coverage
-Installation
-------------
+Installation & Usage
+--------------------
Install from PyPI using::
$ pip install django-debreach
-Add to your `INSTALLED_APPS`::
-
- INSTALLED_APPS = (
- ...
- 'debreach',
- ...
- )
-
-Configuration
--------------
-
-CSRF token masking (for Django < 1.10)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Django 1.10+ provides built-in support for masking CSRF tokens so you should
-use that. Including the middleware in a Django 1.10 project will raise an
-``ImproperlyConfigured`` exception.
-
-To mask CSRF tokens in the template add the
-``debreach.context_processors.csrf`` context processor to the end of your
-`TEMPLATE_CONTEXT_PROCESSORS`::
-
- TEMPLATE_CONTEXT_PROCESSORS = (
- ...
- 'debreach.context_processors.csrf',
- )
-
-And add the ``debreach.middleware.CSRFCryptMiddleware`` to your middleware,
-*before* ``django.middleware.csrf.CSRFMiddleware``::
-
- MIDDLEWARE_CLASSES = (
- 'debreach.middleware.CSRFCryptMiddleware',
- ...
- 'django.middleware.csrf.CSRFMiddleware',
- ...
- )
-
-This works by xor-ing the CSRF token when it is added to the template,
-so that ``{% csrf_token %}`` now produces a hidden field with a value that is
-``"<random-string>$<actual-csrf-token-xor-ed-with-random-string>"``.
-Then, when the form is POSTed, the middleware xors the CSRF token back into
-it's original form. This ensures that the CSRF content is never the same
-between requests. If you are passing the token using the ``X-CSRFToken``
-header (e.g. using XHR) that header will also be processed in the same way.
-
-Note that values that are unchanged by django-debreach, or rather, don't
-contain a delimiting ``$``, will be left unmodified. The middleware will
-also not operate on views marked as being exempt from CSRF protection
-using the ``django.views.decorators.csrf.csrf_exempt`` decorator.
-
-CSRF protection using csrf_protect
-""""""""""""""""""""""""""""""""""
-
-If you don't use the CSRF middleware from django but, instead, apply the
-``django.views.decorators.csrf.csrf_protect`` decorator to selected
-views, and don't want to use the ``debreach.middleware.CSRFCryptMiddleware``,
-then you can use the ``debreach.decorators.csrf_decrypt`` decorator.
-
-To use the ``debreach.decorators.csrf_decrypt`` decorator simply wrap
-your CSRF protected view with the decorator, like so::
-
- @csrf_protect
- @csrf_decrypt
- def view(request, *args, **kwargs):
- return HttpResponse('')
-
-
-Content length modification
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-django-debreach also enables you to counter the BREACH attack by randomising
the
-content length of each response. This is acheived by adding a random string of
-between 12 and 25 characters as a comment to the end of the HTML content. Note
-that this will only be applied to responses with a content type of
-``text/html``.
-
To enable content length modification for all responses, add the
``debreach.middleware.RandomCommentMiddleware`` to the *start* of your
middleware, but *after* the ``GzipMiddleware`` if you are using that.::
@@ -127,3 +57,9 @@
then it may be easier to not use the middleware, but to selectively apply the
``debreach.decorators.append_random_comment`` decorator to the views you want
protected.
+
+Python 2 and Django < 2.0 support
+---------------------------------
+
+Version 2.0.0 drops all support for Python 2 and Django < 2.0. If you need
+support for those versions continue using ``django-debreach>=1.5.2,<2.0``.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-debreach-1.5.2/debreach/__init__.py
new/django-debreach-2.0.1/debreach/__init__.py
--- old/django-debreach-1.5.2/debreach/__init__.py 2018-08-31
15:31:47.000000000 +0200
+++ new/django-debreach-2.0.1/debreach/__init__.py 2019-10-10
11:08:57.000000000 +0200
@@ -1,10 +1,8 @@
# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
from distutils import version
-__version__ = '1.5.2'
+__version__ = '2.0.1'
version_info = version.StrictVersion(__version__).version
default_app_config = 'debreach.apps.DebreachConfig'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-debreach-1.5.2/debreach/apps.py
new/django-debreach-2.0.1/debreach/apps.py
--- old/django-debreach-1.5.2/debreach/apps.py 2016-01-10 17:05:37.000000000
+0100
+++ new/django-debreach-2.0.1/debreach/apps.py 2019-10-10 09:55:51.000000000
+0200
@@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
from django.apps import AppConfig
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-debreach-1.5.2/debreach/context_processors.py
new/django-debreach-2.0.1/debreach/context_processors.py
--- old/django-debreach-1.5.2/debreach/context_processors.py 2016-08-13
12:47:13.000000000 +0200
+++ new/django-debreach-2.0.1/debreach/context_processors.py 1970-01-01
01:00:00.000000000 +0100
@@ -1,36 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.core.signing import b64_encode
-from django.middleware.csrf import get_token
-from django.utils.crypto import get_random_string
-from django.utils.encoding import force_bytes, force_text
-from django.utils.functional import lazy
-from django.utils.six import text_type
-
-from debreach.utils import xor
-
-
-def csrf(request):
- """
- Context processor that provides a CSRF token, or the string 'NOTPROVIDED'
- if it has not been provided by either a view decorator or the middleware
- """
- def _get_val():
- token = get_token(request)
- if token is None:
- # In order to be able to provide debugging info in the
- # case of misconfiguration, we use a sentinel value
- # instead of returning an empty dict.
- return 'NOTPROVIDED'
- else:
- token = force_bytes(token, encoding='latin-1')
- key = force_bytes(
- get_random_string(len(token)),
- encoding='latin-1'
- )
- value = b64_encode(xor(token, key))
- return force_text(b'$'.join((key, value)), encoding='latin-1')
- _get_val = lazy(_get_val, text_type)
-
- return {'csrf_token': _get_val()}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-debreach-1.5.2/debreach/decorators.py
new/django-debreach-2.0.1/debreach/decorators.py
--- old/django-debreach-1.5.2/debreach/decorators.py 2016-08-13
12:50:35.000000000 +0200
+++ new/django-debreach-2.0.1/debreach/decorators.py 2019-10-10
11:08:27.000000000 +0200
@@ -1,12 +1,9 @@
# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
from functools import wraps
-import django
-from django.utils.decorators import available_attrs, decorator_from_middleware
+from django.utils.decorators import decorator_from_middleware
-from debreach.middleware import CSRFCryptMiddleware, RandomCommentMiddleware
+from debreach.middleware import RandomCommentMiddleware
append_random_comment = decorator_from_middleware(RandomCommentMiddleware)
@@ -27,14 +24,4 @@
response = view_func(*args, **kwargs)
response._random_comment_exempt = True
return response
- return wraps(view_func, assigned=available_attrs(view_func))(wrapped_view)
-
-
-if django.VERSION < (1, 10):
- csrf_decrypt = decorator_from_middleware(CSRFCryptMiddleware)
- append_random_comment.__name__ = str('append_random_comment')
- append_random_comment.__doc__ = '''
- Performs the function of the CSRFCryptMiddleware, xor-ing the crypted CSRF
- token back into its original form. Using both, or using the decorator
- multiple times is harmless and efficient.
- '''
+ return wraps(view_func)(wrapped_view)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-debreach-1.5.2/debreach/middleware.py
new/django-debreach-2.0.1/debreach/middleware.py
--- old/django-debreach-1.5.2/debreach/middleware.py 2018-08-24
14:55:16.000000000 +0200
+++ new/django-debreach-2.0.1/debreach/middleware.py 2019-10-10
09:54:15.000000000 +0200
@@ -1,87 +1,28 @@
# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
import logging
import random
-import django
-from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation
-from django.core.signing import b64_decode
from django.utils.crypto import get_random_string
-from django.utils.encoding import force_bytes, force_text
-from django.utils.six import binary_type, string_types
-
-from debreach.utils import xor
-
-try:
- from django.utils.deprecation import MiddlewareMixin
-except ImportError:
- class MiddlewareMixin(object):
- pass
+from django.utils.deprecation import MiddlewareMixin
+from django.utils.encoding import force_str
log = logging.getLogger(__name__)
-class CSRFCryptMiddleware(object):
-
- def __init__(self, *args, **kwargs):
- if django.VERSION >= (1, 10):
- raise ImproperlyConfigured(
- "Django 1.10 and above provides it's own CSRF mechanism to "
- "mitigate the BREACH attack, please remove the "
- "{}.{} middleware."
- .format(self.__module__, self.__class__.__name__)
- )
-
- def _decode(self, token):
- key, value = force_bytes(token, encoding='latin-1').split(b'$', 1)
- return force_text(xor(b64_decode(value), key), encoding='latin-1')
-
- def process_view(self, request, view, view_args, view_kwargs):
- if getattr(view, 'csrf_exempt', False):
- return None
- if request.POST.get('csrfmiddlewaretoken') \
- and '$' in request.POST.get('csrfmiddlewaretoken'):
- try:
- post_was_mutable = request.POST._mutable
- POST = request.POST.copy()
- token = POST.get('csrfmiddlewaretoken')
- POST['csrfmiddlewaretoken'] = self._decode(token)
- POST._mutable = post_was_mutable
- request.POST = POST
- except:
- log.exception('Error decoding csrfmiddlewaretoken')
- raise SuspiciousOperation(
- 'csrfmiddlewaretoken has been tampered with')
- if request.META.get('HTTP_X_CSRFTOKEN') \
- and '$' in request.META.get('HTTP_X_CSRFTOKEN'):
- try:
- META = request.META.copy()
- token = META.get('HTTP_X_CSRFTOKEN')
- META['HTTP_X_CSRFTOKEN'] = self._decode(token)
- request.META = META
- except:
- log.exception('Error decoding csrfmiddlewaretoken')
- raise SuspiciousOperation(
- 'X-CSRFToken header has been tampered with')
- return None
-
-
class RandomCommentMiddleware(MiddlewareMixin):
def process_response(self, request, response):
- str_types = string_types + (binary_type,)
if not getattr(response, 'streaming', False) \
and response.get('Content-Type', '').startswith('text/html') \
and response.content \
- and isinstance(response.content, str_types) \
+ and isinstance(response.content, (bytes, str)) \
and not getattr(response, '_random_comment_exempt', False) \
and not getattr(response, '_random_comment_applied', False):
comment = '<!-- {0} -->'.format(
get_random_string(random.choice(range(12, 25))))
response.content = '{0}{1}'.format(
- force_text(response.content), comment)
+ force_str(response.content), comment)
response._random_comment_applied = True
if response.has_header('Content-Length'):
response['Content-Length'] = str(len(response.content))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-debreach-1.5.2/debreach/models.py
new/django-debreach-2.0.1/debreach/models.py
--- old/django-debreach-1.5.2/debreach/models.py 2016-01-10
17:05:37.000000000 +0100
+++ new/django-debreach-2.0.1/debreach/models.py 1970-01-01
01:00:00.000000000 +0100
@@ -1 +0,0 @@
-# -*- coding: utf-8 -*-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-debreach-1.5.2/debreach/tests.py
new/django-debreach-2.0.1/debreach/tests.py
--- old/django-debreach-1.5.2/debreach/tests.py 2017-12-21 18:33:54.000000000
+0100
+++ new/django-debreach-2.0.1/debreach/tests.py 2019-10-10 09:56:08.000000000
+0200
@@ -1,124 +1,21 @@
# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
import os
-import re
import unittest
-import django
-from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation
from django.http import HttpResponse
from django.test import TestCase
from django.test.client import RequestFactory
-from django.utils.crypto import get_random_string
-from django.utils.encoding import force_text
-from django.views.decorators.csrf import csrf_exempt
+from django.urls import reverse
+from django.utils.encoding import force_str
-from debreach.context_processors import csrf
from debreach.decorators import append_random_comment, random_comment_exempt
-from debreach.middleware import CSRFCryptMiddleware, RandomCommentMiddleware
-
-
-try:
- from django.urls import reverse
-except ImportError:
- from django.core.urlresolvers import reverse
-
-
-try:
- unichr
-except NameError:
- pass
-else:
- chr = unichr
+from debreach.middleware import RandomCommentMiddleware
def test_view(request):
return HttpResponse()
-class TestCSRFCryptMiddleware(TestCase):
-
- if django.VERSION < (1, 10):
-
- def test_not_encoded(self):
- request = RequestFactory().post(
- '/', {'csrfmiddlewaretoken': 'abc123'}
- )
- middleware = CSRFCryptMiddleware()
- middleware.process_view(request, test_view, (), {})
- self.assertEqual(request.POST.get('csrfmiddlewaretoken'), 'abc123')
-
- def test_encoded(self):
- request = RequestFactory().post(
- '/',
- {'csrfmiddlewaretoken': 'aBcDeF$ACAAdVd1'}
- )
- middleware = CSRFCryptMiddleware()
- middleware.process_view(request, test_view, (), {})
- self.assertEqual(request.POST.get('csrfmiddlewaretoken'), 'abc123')
-
- def test_mutable_status(self):
- request = RequestFactory().post(
- '/',
- {'csrfmiddlewaretoken': 'aBcDeF$ACAAdVd1'}
- )
- request.POST._mutable = False
- middleware = CSRFCryptMiddleware()
- middleware.process_view(request, test_view, (), {})
- self.assertFalse(request.POST._mutable)
- request = RequestFactory().post(
- '/',
- {'csrfmiddlewaretoken': 'aBcDeF$ACAAdVd1'}
- )
- request.POST._mutable = True
- middleware = CSRFCryptMiddleware()
- middleware.process_view(request, test_view, (), {})
- self.assertTrue(request.POST._mutable)
-
- def test_header_not_encoded(self):
- request = RequestFactory().post('/', HTTP_X_CSRFTOKEN='abc123')
- middleware = CSRFCryptMiddleware()
- middleware.process_view(request, test_view, (), {})
- self.assertEqual(request.META.get('HTTP_X_CSRFTOKEN'), 'abc123')
-
- def test_header_encoded(self):
- request = RequestFactory().post(
- '/', HTTP_X_CSRFTOKEN='aBcDeF$ACAAdVd1',
- )
- middleware = CSRFCryptMiddleware()
- middleware.process_view(request, test_view, (), {})
- self.assertEqual(request.META.get('HTTP_X_CSRFTOKEN'), 'abc123')
-
- def test_tampering(self):
- request = RequestFactory().post(
- '/', {'csrfmiddlewaretoken': '123456$abc'})
- middleware = CSRFCryptMiddleware()
- with self.assertRaises(SuspiciousOperation):
- middleware.process_view(request, test_view, (), {})
-
- def test_header_tampering(self):
- request = RequestFactory().post('/', HTTP_X_CSRFTOKEN='123456$abc')
- middleware = CSRFCryptMiddleware()
- with self.assertRaises(SuspiciousOperation):
- middleware.process_view(request, test_view, (), {})
-
- def test_csrf_exempt(self):
- # This is an odd test. We're testing that, when a view is
- # csrf_exempt, process_view will bail without performing any
- # processing.
- request = RequestFactory().post('/', HTTP_X_CSRFTOKEN="aB$AHM")
- middleware = CSRFCryptMiddleware()
- middleware.process_view(request, csrf_exempt(test_view), (), {})
- self.assertEqual("aB$AHM", request.META['HTTP_X_CSRFTOKEN'])
-
- else:
-
- def test_middleware_raises_improperly_configured(self):
- with self.assertRaises(ImproperlyConfigured):
- CSRFCryptMiddleware()
-
-
class TestRandomCommentMiddleware(TestCase):
def test_noop_on_wrong_content_type(self):
@@ -160,7 +57,7 @@
request = RequestFactory().get('/')
middleware = RandomCommentMiddleware()
response = middleware.process_response(request, response)
- self.assertNotEqual(force_text(response.content), force_text(html))
+ self.assertNotEqual(force_str(response.content), force_str(html))
def test_exemption(self):
html = '''<html>
@@ -172,7 +69,7 @@
request = RequestFactory().get('/')
middleware = RandomCommentMiddleware()
response = middleware.process_response(request, response)
- self.assertEqual(force_text(response.content), html)
+ self.assertEqual(force_str(response.content), html)
def test_missing_content_type(self):
request = RequestFactory().get('/')
@@ -204,9 +101,9 @@
request = RequestFactory().get('/')
response = test_view(request)
- self.assertNotEqual(force_text(response.content), html)
- self.assertIn('<!-- ', force_text(response.content))
- self.assertIn(' -->', force_text(response.content))
+ self.assertNotEqual(force_str(response.content), html)
+ self.assertIn('<!-- ', force_str(response.content))
+ self.assertIn(' -->', force_str(response.content))
def test_random_comment_exempt(self):
html = '''<html>
@@ -223,26 +120,6 @@
self.assertTrue(response._random_comment_exempt)
-class TestContextProcessor(TestCase):
-
- def test_csrf(self):
- request = RequestFactory().get('/')
- request.META['CSRF_COOKIE'] = 'abc123'
- context = csrf(request)
- self.assertTrue(force_text(context['csrf_token']))
- self.assertNotEqual(force_text(context['csrf_token']), 'abc123')
-
- @unittest.skipUnless(
- django.VERSION < (1, 9),
- 'The CSRF token is always present in Django 1.9+'
- )
- def test_no_token_csrf(self):
- request = RequestFactory().get('/')
- context = csrf(request)
- self.assertTrue(force_text(context['csrf_token']))
- self.assertEqual(force_text(context['csrf_token']), 'NOTPROVIDED')
-
-
@unittest.skipUnless(
'test_project' in os.environ.get('DJANGO_SETTINGS_MODULE', ''),
'Not running in test_project'
@@ -252,74 +129,3 @@
def test_adds_comment(self):
resp = self.client.get(reverse('home'))
self.assertFalse(resp.content.endswith(b'</html>'))
-
- if django.VERSION < (1, 10):
- def test_crypt_csrf_token(self):
- resp = self.client.get(reverse('test_form'))
- m = re.search(
- r'value=\'(.*\$.*)\'',
- force_text(resp.content),
- re.MULTILINE | re.DOTALL
- )
- self.assertEqual(len(m.groups()), 1)
- token = m.groups()[0].strip()
- post_resp = self.client.post(
- reverse('test_form'),
- {'csrfmiddlewaretoken': token, 'message': 'Some rubbish'}
- )
- self.assertRedirects(post_resp, reverse('home'))
-
- def test_crypt_csrf_header(self):
- resp = self.client.get(reverse('test_form'))
- m = re.search(
- r'value=\'(.*\$.*)\'',
- force_text(resp.content),
- re.MULTILINE | re.DOTALL
- )
- self.assertEqual(len(m.groups()), 1)
- token = m.groups()[0].strip()
- post_resp = self.client.post(
- reverse('test_form'),
- {'message': 'Some rubbish'},
- X_CSRFTOKEN=token,
- )
- self.assertRedirects(post_resp, reverse('home'))
-
- def test_round_trip_loop(self):
- '''
- Checks a wide range of input tokens and keys
- '''
- for _ in range(1000):
- request = RequestFactory().get('/')
- csrf_token = get_random_string(32)
- request.META['CSRF_COOKIE'] = csrf_token
- token = force_text(csrf(request)['csrf_token'])
- request = RequestFactory().post(
- '/', {'csrfmiddlewaretoken': token})
- middleware = CSRFCryptMiddleware()
- middleware.process_view(request, test_view, (), {})
- self.assertEqual(
- force_text(request.POST.get('csrfmiddlewaretoken')),
- force_text(csrf_token)
- )
-
- def test_round_trip_loop_header(self):
- '''
- Checks a wide range of input tokens and keys
- '''
- for _ in range(1000):
- request = RequestFactory().get('/')
- csrf_token = get_random_string(32)
- request.META['CSRF_COOKIE'] = csrf_token
- token = csrf(request)['csrf_token']
- request = RequestFactory().post(
- '/',
- HTTP_X_CSRFTOKEN=force_text(token),
- HTTP_X_REQUESTED_WITH='XMLHttpRequest'
- )
- middleware = CSRFCryptMiddleware()
- middleware.process_view(request, test_view, (), {})
- self.assertEqual(
- force_text(request.META.get('HTTP_X_CSRFTOKEN')),
- force_text(csrf_token)
- )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-debreach-1.5.2/debreach/utils.py
new/django-debreach-2.0.1/debreach/utils.py
--- old/django-debreach-1.5.2/debreach/utils.py 2016-01-10 17:05:37.000000000
+0100
+++ new/django-debreach-2.0.1/debreach/utils.py 1970-01-01 01:00:00.000000000
+0100
@@ -1,13 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.utils.encoding import force_bytes
-from django.utils.six import binary_type
-
-
-def xor(s, pad):
- '''XOR a given string ``s`` with the one-time-pad ``pad``'''
- from itertools import cycle
- s = bytearray(force_bytes(s, encoding='latin-1'))
- pad = bytearray(force_bytes(pad, encoding='latin-1'))
- return binary_type(bytearray(x ^ y for x, y in zip(s, cycle(pad))))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/django-debreach-1.5.2/django_debreach.egg-info/PKG-INFO
new/django-debreach-2.0.1/django_debreach.egg-info/PKG-INFO
--- old/django-debreach-1.5.2/django_debreach.egg-info/PKG-INFO 2018-08-31
15:32:05.000000000 +0200
+++ new/django-debreach-2.0.1/django_debreach.egg-info/PKG-INFO 2019-10-10
11:09:53.000000000 +0200
@@ -1,7 +1,7 @@
Metadata-Version: 1.1
Name: django-debreach
-Version: 1.5.2
-Summary: Adds middleware and context processors to give some protection
against the BREACH attack in Django.
+Version: 2.0.1
+Summary: Adds middleware to give some added protection against the BREACH
attack in Django.
Home-page: http://github.com/lpomfrey/django-debreach
Author: Luke Pomfrey
Author-email: [email protected]
@@ -14,14 +14,9 @@
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Framework :: Django
-Classifier: Framework :: Django :: 1.8
-Classifier: Framework :: Django :: 1.11
-Classifier: Framework :: Django :: 2.0
+Classifier: Framework :: Django :: 2.2
Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: Implementation :: CPython
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/django-debreach-1.5.2/django_debreach.egg-info/SOURCES.txt
new/django-debreach-2.0.1/django_debreach.egg-info/SOURCES.txt
--- old/django-debreach-1.5.2/django_debreach.egg-info/SOURCES.txt
2018-08-31 15:32:05.000000000 +0200
+++ new/django-debreach-2.0.1/django_debreach.egg-info/SOURCES.txt
2019-10-10 11:09:53.000000000 +0200
@@ -5,12 +5,9 @@
setup.py
debreach/__init__.py
debreach/apps.py
-debreach/context_processors.py
debreach/decorators.py
debreach/middleware.py
-debreach/models.py
debreach/tests.py
-debreach/utils.py
django_debreach.egg-info/PKG-INFO
django_debreach.egg-info/SOURCES.txt
django_debreach.egg-info/dependency_links.txt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-debreach-1.5.2/docs/index.rst
new/django-debreach-2.0.1/docs/index.rst
--- old/django-debreach-1.5.2/docs/index.rst 2016-08-13 13:15:42.000000000
+0200
+++ new/django-debreach-2.0.1/docs/index.rst 2019-10-10 09:58:23.000000000
+0200
@@ -4,6 +4,12 @@
Basic/extra mitigation against the `BREACH attack <http://breachattack.com/>`_
for Django projects.
+django-debreach provides additional protection to Django's built in CSRF
+token masking by randomising the content length of each response. This is
+acheived by adding a random string of between 12 and 25 characters as a
+comment to the end of the HTML content. Note that this will only be applied to
+responses with a content type of ``text/html``.
+
When combined with rate limiting in your web-server, or by using something
like `django-ratelimit <http://django-ratelimit.readthedocs.org/>`_, the
techniques here should provide at least some protection against the BREACH
@@ -20,89 +26,13 @@
:target: https://coveralls.io/r/lpomfrey/django-debreach?branch=master
:alt: Coverage
-Installation
-------------
+Installation & Usage
+--------------------
Install from PyPI using::
$ pip install django-debreach
-Add to your `INSTALLED_APPS`::
-
- INSTALLED_APPS = (
- ...
- 'debreach',
- ...
- )
-
-Configuration
--------------
-
-CSRF token masking (for Django < 1.10)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Django 1.10+ provides built-in support for masking CSRF tokens so you should
-use that. Including the middleware in a Django 1.10 project will raise an
-``ImproperlyConfigured`` exception.
-
-To mask CSRF tokens in the template add the
-``debreach.context_processors.csrf`` context processor to the end of your
-`TEMPLATE_CONTEXT_PROCESSORS`::
-
- TEMPLATE_CONTEXT_PROCESSORS = (
- ...
- 'debreach.context_processors.csrf',
- )
-
-And add the ``debreach.middleware.CSRFCryptMiddleware`` to your middleware,
-*before* ``django.middleware.csrf.CSRFMiddleware``::
-
- MIDDLEWARE_CLASSES = (
- 'debreach.middleware.CSRFCryptMiddleware',
- ...
- 'django.middleware.csrf.CSRFMiddleware',
- ...
- )
-
-This works by xor-ing the CSRF token when it is added to the template,
-so that ``{% csrf_token %}`` now produces a hidden field with a value that is
-``"<random-string>$<actual-csrf-token-xor-ed-with-random-string>"``.
-Then, when the form is POSTed, the middleware xors the CSRF token back into
-it's original form. This ensures that the CSRF content is never the same
-between requests. If you are passing the token using the ``X-CSRFToken``
-header (e.g. using XHR) that header will also be processed in the same way.
-
-Note that values that are unchanged by django-debreach, or rather, don't
-contain a delimiting ``$``, will be left unmodified. The middleware will
-also not operate on views marked as being exempt from CSRF protection
-using the ``django.views.decorators.csrf.csrf_exempt`` decorator.
-
-CSRF protection using csrf_protect
-""""""""""""""""""""""""""""""""""
-
-If you don't use the CSRF middleware from django but, instead, apply the
-``django.views.decorators.csrf.csrf_protect`` decorator to selected
-views, and don't want to use the ``debreach.middleware.CSRFCryptMiddleware``,
-then you can use the ``debreach.decorators.csrf_decrypt`` decorator.
-
-To use the ``debreach.decorators.csrf_decrypt`` decorator simply wrap
-your CSRF protected view with the decorator, like so::
-
- @csrf_protect
- @csrf_decrypt
- def view(request, *args, **kwargs):
- return HttpResponse('')
-
-
-Content length modification
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-django-debreach also enables you to counter the BREACH attack by randomising
the
-content length of each response. This is acheived by adding a random string of
-between 12 and 25 characters as a comment to the end of the HTML content. Note
-that this will only be applied to responses with a content type of
-``text/html``.
-
To enable content length modification for all responses, add the
``debreach.middleware.RandomCommentMiddleware`` to the *start* of your
middleware, but *after* the ``GzipMiddleware`` if you are using that.::
@@ -127,3 +57,9 @@
then it may be easier to not use the middleware, but to selectively apply the
``debreach.decorators.append_random_comment`` decorator to the views you want
protected.
+
+Python 2 and Django < 2.0 support
+---------------------------------
+
+Version 2.0.0 drops all support for Python 2 and Django < 2.0. If you need
+support for those versions continue using ``django-debreach>=1.5.2,<2.0``.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-debreach-1.5.2/setup.py
new/django-debreach-2.0.1/setup.py
--- old/django-debreach-1.5.2/setup.py 2017-12-21 18:53:44.000000000 +0100
+++ new/django-debreach-2.0.1/setup.py 2019-10-10 10:15:28.000000000 +0200
@@ -50,8 +50,8 @@
version=version,
url='http://github.com/lpomfrey/django-debreach',
license='BSD',
- description='Adds middleware and context processors to give some '
- 'protection against the BREACH attack in Django.',
+ description='Adds middleware to give some added protection against the '
+ 'BREACH attack in Django.',
author='Luke Pomfrey',
author_email='[email protected]',
packages=find_packages(exclude=('test_project', 'docs')),
@@ -67,14 +67,9 @@
'License :: OSI Approved :: BSD License',
'Operating System :: OS Independent',
'Framework :: Django',
- 'Framework :: Django :: 1.8',
- 'Framework :: Django :: 1.11',
- 'Framework :: Django :: 2.0',
+ 'Framework :: Django :: 2.2',
'Programming Language :: Python',
- 'Programming Language :: Python :: 2',
- 'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
- 'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: Implementation :: CPython',