Skip to content

Commit

Permalink
Merge pull request from GHSA-pghf-347x-c2gj
Browse files Browse the repository at this point in the history
* Changes required to support v1.11.x branch

Pin requirements to work with python2.7.

Style corrections to get tox to pass.

Pinning requirements for tox.

Setup github test action for v1.X branch

Convert to current tox file.

Update requirements.

Django requires session middleware now.

Remove python3.4 from github actions. It's not supported.

Remove docs from tox.

Support PostgresJSON test.

Format code according to black and isort.

Skip tests that are invalid for old versions.

* Fix CVE-2021-30459 by creating signature from all data fields.

Backport of 1c6ba3c1302bf545f8356dcd26255ab7db1ec408

Create a signature based on all fields in the form and attach
to validate that the data being sent back is what the server
generated initially.

Force the values to a string for signing.

Remove hashing mechanism from forms.

* Bump to version 1.11.1
  • Loading branch information
tim-schilling authored Apr 14, 2021
1 parent c201ce3 commit bc08f69
Show file tree
Hide file tree
Showing 26 changed files with 827 additions and 287 deletions.
210 changes: 210 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
name: Test

on: [push, pull_request]

jobs:
mysql:
runs-on: ubuntu-latest
strategy:
fail-fast: false
max-parallel: 5
matrix:
python-version: ['2.7', '3.5', '3.6', '3.7']

services:
mariadb:
image: mariadb:10.3
env:
MYSQL_ROOT_PASSWORD: debug_toolbar
options: >-
--health-cmd "mysqladmin ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 3306:3306

steps:
- uses: actions/checkout@v2

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}

- name: Get pip cache dir
id: pip-cache
run: |
echo "::set-output name=dir::$(pip cache dir)"
- name: Cache
uses: actions/cache@v2
with:
path: ${{ steps.pip-cache.outputs.dir }}
key:
${{ matrix.python-version }}-v1-${{ hashFiles('**/setup.cfg') }}-${{ hashFiles('**/tox.ini') }}
restore-keys: |
${{ matrix.python-version }}-v1-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade tox tox-gh-actions
- name: Test with tox
run: tox
env:
DB_BACKEND: mysql
DB_USER: root
DB_PASSWORD: debug_toolbar
DB_HOST: 127.0.0.1
DB_PORT: 3306

- name: Upload coverage
uses: codecov/codecov-action@v1
with:
name: Python ${{ matrix.python-version }}

postgres:
runs-on: ubuntu-latest
strategy:
fail-fast: false
max-parallel: 5
matrix:
python-version: ['2.7', '3.5', '3.6', '3.7']

services:
postgres:
image: 'postgres:9.5'
env:
POSTGRES_DB: debug_toolbar
POSTGRES_USER: debug_toolbar
POSTGRES_PASSWORD: debug_toolbar
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v2

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}

- name: Get pip cache dir
id: pip-cache
run: |
echo "::set-output name=dir::$(pip cache dir)"
- name: Cache
uses: actions/cache@v2
with:
path: ${{ steps.pip-cache.outputs.dir }}
key:
${{ matrix.python-version }}-v1-${{ hashFiles('**/setup.cfg') }}-${{ hashFiles('**/tox.ini') }}
restore-keys: |
${{ matrix.python-version }}-v1-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade tox tox-gh-actions
- name: Test with tox
run: tox
env:
DB_BACKEND: postgresql
DB_HOST: localhost
DB_PORT: 5432

- name: Upload coverage
uses: codecov/codecov-action@v1
with:
name: Python ${{ matrix.python-version }}

sqlite:
runs-on: ubuntu-latest
strategy:
fail-fast: false
max-parallel: 5
matrix:
python-version: ['2.7', '3.5', '3.6', '3.7']

steps:
- uses: actions/checkout@v2

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}

- name: Get pip cache dir
id: pip-cache
run: |
echo "::set-output name=dir::$(pip cache dir)"
- name: Cache
uses: actions/cache@v2
with:
path: ${{ steps.pip-cache.outputs.dir }}
key:
${{ matrix.python-version }}-v1-${{ hashFiles('**/setup.cfg') }}-${{ hashFiles('**/tox.ini') }}
restore-keys: |
${{ matrix.python-version }}-v1-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade tox tox-gh-actions
- name: Test with tox
run: tox
env:
DB_BACKEND: sqlite3
DB_NAME: ":memory:"

- name: Upload coverage
uses: codecov/codecov-action@v1
with:
name: Python ${{ matrix.python-version }}

lint:
runs-on: ubuntu-latest
strategy:
fail-fast: false

steps:
- uses: actions/checkout@v2

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: 3.7

- name: Get pip cache dir
id: pip-cache
run: |
echo "::set-output name=dir::$(pip cache dir)"
- name: Cache
uses: actions/cache@v2
with:
path: ${{ steps.pip-cache.outputs.dir }}
key:
${{ matrix.python-version }}-v1-${{ hashFiles('**/setup.cfg') }}-${{ hashFiles('**/tox.ini') }}
restore-keys: |
${{ matrix.python-version }}-v1-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade tox
- name: Test with tox
run: tox -e style,readme

59 changes: 0 additions & 59 deletions .travis.yml

This file was deleted.

11 changes: 6 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
.PHONY: flake8 example test coverage translatable_strings update_translations

style:
isort -rc debug_toolbar example tests
black debug_toolbar example tests setup.py
flake8 debug_toolbar example tests
isort .
black --target-version=py27 .
flake8

style_check:
isort -rc -c debug_toolbar example tests
black --check debug_toolbar example tests setup.py
isort -c .
black --target-version=py27 --check .
flake8

flake8:
flake8 debug_toolbar example tests
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Here's a screenshot of the toolbar in action:
In addition to the built-in panels, a number of third-party panels are
contributed by the community.

The current version of the Debug Toolbar is 1.11. It works on Django ≥ 1.11.
The current version of the Debug Toolbar is 1.11.1. It works on Django ≥ 1.11.

Documentation, including installation and configuration instructions, is
available at https://django-debug-toolbar.readthedocs.io/.
Expand Down
20 changes: 19 additions & 1 deletion debug_toolbar/decorators.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import functools

from django.http import Http404
from django.http import Http404, HttpResponseBadRequest


def require_show_toolbar(view):
Expand All @@ -15,3 +15,21 @@ def inner(request, *args, **kwargs):
return view(request, *args, **kwargs)

return inner


def signed_data_view(view):
"""Decorator that handles unpacking a signed data form"""

@functools.wraps(view)
def inner(request, *args, **kwargs):
from debug_toolbar.forms import SignedDataForm

data = request.GET if request.method == "GET" else request.POST
signed_form = SignedDataForm(data)
if signed_form.is_valid():
return view(
request, *args, verified_data=signed_form.verified_data(), **kwargs
)
return HttpResponseBadRequest("Invalid signature")

return inner
55 changes: 55 additions & 0 deletions debug_toolbar/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import json
from collections import OrderedDict

from django import forms
from django.core import signing
from django.core.exceptions import ValidationError
from django.utils.encoding import force_str


class SignedDataForm(forms.Form):
"""Helper form that wraps a form to validate its contents on post.
class PanelForm(forms.Form):
# fields
On render:
form = SignedDataForm(initial=PanelForm(initial=data).initial)
On POST:
signed_form = SignedDataForm(request.POST)
if signed_form.is_valid():
panel_form = PanelForm(signed_form.verified_data)
if panel_form.is_valid():
# Success
Or wrap the FBV with ``debug_toolbar.decorators.signed_data_view``
"""

salt = "django_debug_toolbar"
signed = forms.CharField(required=True, widget=forms.HiddenInput)

def __init__(self, *args, **kwargs):
initial = kwargs.pop("initial", None)
if initial:
initial = {"signed": self.sign(initial)}
super(SignedDataForm, self).__init__(*args, initial=initial, **kwargs)

def clean_signed(self):
try:
verified = json.loads(
signing.Signer(salt=self.salt).unsign(self.cleaned_data["signed"])
)
return verified
except signing.BadSignature:
raise ValidationError("Bad signature")

def verified_data(self):
return self.is_valid() and self.cleaned_data["signed"]

@classmethod
def sign(cls, data):
# Sort the data by the keys to create a fixed ordering.
items = sorted(data.items(), key=lambda item: item[0])
return signing.Signer(salt=cls.salt).sign(
json.dumps(OrderedDict((key, force_str(value)) for key, value in items))
)
Loading

0 comments on commit bc08f69

Please sign in to comment.