summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/narr/sessions.rst9
-rw-r--r--docs/narr/viewconfig.rst9
-rw-r--r--docs/whatsnew-1.7.rst4
-rw-r--r--pyramid/tests/test_viewderivers.py11
-rw-r--r--pyramid/viewderivers.py4
5 files changed, 26 insertions, 11 deletions
diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst
index ad086268b..0e895ff81 100644
--- a/docs/narr/sessions.rst
+++ b/docs/narr/sessions.rst
@@ -411,15 +411,16 @@ Checking CSRF Tokens Automatically
.. versionadded:: 1.7
-:app:`Pyramid` supports automatically checking CSRF tokens on POST requests.
-Any other request may be checked manually. This feature can be turned on
-globally for an application using the ``pyramid.require_default_csrf`` setting.
+:app:`Pyramid` supports automatically checking CSRF tokens on requests with an
+unsafe method as defined by RFC2616. Any other request may be checked manually.
+This feature can be turned on globally for an application using the
+``pyramid.require_default_csrf`` setting.
If the ``pyramid.required_default_csrf`` setting is a :term:`truthy string` or
``True`` then the default CSRF token parameter will be ``csrf_token``. If a
different token is desired, it may be passed as the value. Finally, a
:term:`falsey string` or ``False`` will turn off automatic CSRF checking
-globally on every POST request.
+globally on every request.
No matter what, CSRF checking may be explicitly enabled or disabled on a
per-view basis using the ``require_csrf`` view option. This option is of the
diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst
index 40db5fbeb..3b8f0353a 100644
--- a/docs/narr/viewconfig.rst
+++ b/docs/narr/viewconfig.rst
@@ -195,10 +195,11 @@ Non-Predicate Arguments
``require_csrf``
- CSRF checks only affect POST requests. Any other request methods will pass
- untouched. This option is used in combination with the
- ``pyramid.require_default_csrf`` setting to control which request parameters
- are checked for CSRF tokens.
+ CSRF checks will affect any request method that is not defined as a "safe"
+ method by RFC2616. In pratice this means that GET, HEAD, OPTIONS, and TRACE
+ methods will pass untouched and all others methods will require CSRF. This
+ option is used in combination with the ``pyramid.require_default_csrf``
+ setting to control which request parameters are checked for CSRF tokens.
This feature requires a configured :term:`session factory`.
diff --git a/docs/whatsnew-1.7.rst b/docs/whatsnew-1.7.rst
index 83ece690e..b85e65ec1 100644
--- a/docs/whatsnew-1.7.rst
+++ b/docs/whatsnew-1.7.rst
@@ -39,14 +39,14 @@ Feature Additions
to security checks. See https://github.com/Pylons/pyramid/pull/2021
- Added a new setting, ``pyramid.require_default_csrf`` which may be used
- to turn on CSRF checks globally for every POST request in the application.
+ to turn on CSRF checks globally for every request in the application.
This should be considered a good default for websites built on Pyramid.
It is possible to opt-out of CSRF checks on a per-view basis by setting
``require_csrf=False`` on those views.
See :ref:`auto_csrf_checking` and
https://github.com/Pylons/pyramid/pull/2413
-- Added a ``require_csrf`` view option which will enforce CSRF checks on POST
+- Added a ``require_csrf`` view option which will enforce CSRF checks on
requests. If the CSRF check fails a ``BadCSRFToken`` exception will be
raised and may be caught by exception views (the default response is a
``400 Bad Request``). This option should be used in place of the deprecated
diff --git a/pyramid/tests/test_viewderivers.py b/pyramid/tests/test_viewderivers.py
index bd5b3f2de..4613762f5 100644
--- a/pyramid/tests/test_viewderivers.py
+++ b/pyramid/tests/test_viewderivers.py
@@ -1170,6 +1170,17 @@ class TestDeriveView(unittest.TestCase):
view = self.config._derive_view(inner_view, require_csrf='DUMMY')
self.assertRaises(BadCSRFToken, lambda: view(None, request))
+ def test_csrf_view_fails_on_bad_PUT_header(self):
+ from pyramid.exceptions import BadCSRFToken
+ def inner_view(request): pass
+ request = self._makeRequest()
+ request.method = 'PUT'
+ request.POST = {}
+ request.session = DummySession({'csrf_token': 'foo'})
+ request.headers = {'X-CSRF-Token': 'bar'}
+ view = self.config._derive_view(inner_view, require_csrf='DUMMY')
+ self.assertRaises(BadCSRFToken, lambda: view(None, request))
+
def test_csrf_view_uses_config_setting_truthy(self):
response = DummyResponse()
def inner_view(request):
diff --git a/pyramid/viewderivers.py b/pyramid/viewderivers.py
index 41102319d..e9ff09416 100644
--- a/pyramid/viewderivers.py
+++ b/pyramid/viewderivers.py
@@ -488,7 +488,9 @@ def csrf_view(view, info):
wrapped_view = view
if val:
def csrf_view(context, request):
- if request.method == 'POST':
+ # Assume that anything not defined as 'safe' by RFC2616 needs
+ # protection
+ if request.method not in {"GET", "HEAD", "OPTIONS", "TRACE"}:
check_csrf_token(request, val, raises=True)
return view(context, request)
wrapped_view = csrf_view