Skip to content

Conversation

ryanhiebert
Copy link
Contributor

Trac ticket number

ticket-35328

Branch description

When in debug mode, we can make some better error messaging when the Origin header checking fails. In common scenarios, we can notice that they are likely missing headers from proxies. In any case, we can remove the verbose messaging around CSRF Tokens, which are not the way they have failed and are unhelpful to solving the error they are viewing.

Checklist

  • This PR targets the main branch.
  • The commit message is written in past tense, mentions the ticket number, and ends with a period.
  • I have checked the "Has patch" ticket flag in the Trac system.
  • I have added or updated relevant tests.
  • I have added or updated relevant docs, including release notes if applicable.

@ryanhiebert ryanhiebert force-pushed the proxies branch 2 times, most recently from 0df060c to 95759af Compare March 25, 2024 02:59
@ryanhiebert ryanhiebert force-pushed the proxies branch 3 times, most recently from d857f02 to d7f6022 Compare March 30, 2024 01:51
Copy link
Contributor

@sarahboyce sarahboyce left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you Ryan ⭐ I have initial comments

Copy link
Member

@adamchainz adamchainz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your work here @ryanhiebert ! I have some comments with small improvements.

@adamchainz
Copy link
Member

adamchainz commented May 20, 2024

Lint error:

Error: ./django/views/csrf.py:26:5: F401 'django.middleware.csrf.REASON_BAD_ORIGIN' imported but unused

Set up pre-commit for yourself: https://docs.djangoproject.com/en/dev/internals/contributing/writing-code/coding-style/#pre-commit-checks

@ryanhiebert ryanhiebert force-pushed the proxies branch 3 times, most recently from c6805e2 to 6e3a65e Compare May 20, 2024 15:03
@ryanhiebert ryanhiebert force-pushed the proxies branch 3 times, most recently from 755cbb3 to dc5ce91 Compare May 22, 2024 13:27
Comment on lines +48 to +51
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<p>The <code>Origin</code> header does not match
the expected server origin,
but common proxy headers are present in the request
and may include parts of the <code>Origin</code> header.</p>
<p>The <code>Origin</code> header does not match the expected server origin,
but common proxy headers are present in the request and may include parts of
the <code>Origin</code> header.</p>

This file is roughly wrapped at 80 characters so let's apply similar wrapping here

Comment on lines +58 to +66
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe?

Suggested change
<p>If you’re sure that you are only running behind a secure proxy
that always set these headers to avoid spoofing as described in
<a href="https://docs.djangoproject.com/en/{{ docs_version }}/ref/settings/#secure-proxy-ssl-header">this warning in the docs</a>,
you may wish to add one or more of the following
settings to permit Django to trust these headers.</p>
<p><pre>
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
USE_X_FORWARDED_HOST = True
</pre></p>
<p>If you are running behind a secure proxy that sets these headers, you may
want to add one or more of the following settings to permit Django to trust
these headers.</p>
<p><pre>
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
USE_X_FORWARDED_HOST = True
</pre>
Modifying these setting can compromise your site’s security. Ensure you fully
understand your setup before changing it. See <a href="https://docs.djangoproject.com/en/{{ docs_version }}/ref/settings/#secure-proxy-ssl-header"><code>SECURE_PROXY_SSL_HEADER</code></a>
for more details.</p>

image

Comment on lines +68 to +70
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If the expected server origin looks correct,
you may wish to add the origin to the <code>CSRF_TRUSTED_ORIGINS</code>
setting.
If the expected server origin looks correct, you may wish to add the origin
to the <code>CSRF_TRUSTED_ORIGINS</code> setting.

(wrapping nit)

Comment on lines +64 to +73
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"bad_origin": reason.startswith("Origin checking failed"),
"forwarded_may_fix": (
request.headers.get("X-Forwarded-Proto", "") == "https"
and not request.is_secure()
or request.headers.get("Origin", "").endswith(
f'://{request.headers.get("X-Forwarded-Host", "")}'
)
),
"x_forwarded_proto": request.headers.get("X-Forwarded-Proto"),
"x_forwarded_host": request.headers.get("X-Forwarded-Host"),
"bad_origin": True,
"forwarded_may_fix": (
request.headers.get("X-Forwarded-Proto", "") == "https"
or request.headers.get("Origin", "").endswith(
f'://{request.headers.get("X-Forwarded-Host", "")}'
)
),
"x_forwarded_proto": None,
"x_forwarded_host": None,

Thank you for the updates @ryanhiebert
There are a couple of things I think we should still add tests/assert for. If I make the above changes, nothing fails. These changes are:

  • bad_origin always True
  • and not request.is_secure() is removed from "forwarded_may_fix"
  • can we also assert the values of x_forwarded_proto and x_forwarded_host rendering in the template?

Comment on lines +193 to +235
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* The error messaging is improved when ``Origin`` checking fails,
including better hints when likely proxy headers are detected.
* The ``'403_csrf.html'`` template now has improved messaging when ``Origin``
checking fails, including better hints when likely proxy headers are detected.

Docs are wrapped at 80 characters and we will now need to rebase and move this to the 5.2 release notes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants