Skip to content

Only allow modifying patches through POST requests - #127

Merged
JelteF merged 4 commits into
mainfrom
post-for-modifications
Oct 25, 2026
Merged

JelteF merged 4 commits into
mainfrom
post-for-modifications

Conversation

@JelteF

@JelteF JelteF commented Oct 25, 2026

Copy link
Copy Markdown
Collaborator

Changing the status of a patch, closing or moving it, becoming reviewer or committer, and (un)subscribing were all done through plain links, i.e. GET requests. Crawlers follow all of those links on every patch page, and since they're not logged in each of them resulted in a redirect to the login page, generating a lot of useless load. It also meant that anyone could trick a logged in user into modifying a patch by getting them to click a link, since GET requests aren't protected against CSRF.

These buttons are now forms that POST, with a CSRF token. A GET request to one of these URLs now redirects to the patch page without doing anything, also when not logged in, so crawlers that still have the old URLs don't end up at the login page. The staff-only importUser AJAX call, which creates a user, now also uses POST.

Fixes #116

FennemAI and others added 4 commits October 25, 2026 18:21
Changing the status of a patch, closing or moving it, becoming reviewer
or committer, and (un)subscribing were all done through plain links,
i.e. GET requests. Crawlers follow all of those links on every patch
page, and since they're not logged in each of them resulted in a
redirect to the login page, generating a lot of useless load. It also
meant that anyone could trick a logged in user into modifying a patch
by getting them to click a link, since GET requests aren't protected
against CSRF.

These buttons are now forms that POST, with a CSRF token. A GET request
to one of these URLs now redirects to the patch page without doing
anything, also when not logged in, so crawlers that still have the old
URLs don't end up at the login page. The staff-only `importUser` AJAX
call, which creates a user, now also uses POST.

Fixes #116
The previous commit added a custom `patch_modification` decorator that
redirected GET requests to the patch page, instead of using Django's
`require_POST`. The only reason for that was a logged out user clicking
one of the new POST buttons: `login_required` would then send them to
the login page with the action URL as `next`, and after logging in the
browser would do a GET to that URL.

Instead, logged out users now don't get these POST buttons at all. The
patch command bar shows a "Log in to edit" button (next to the Review
button) and the reviewers row shows "Log in to become reviewer", both
of which log in and return to the patch page. That allows using the
standard `require_POST`, which returns a 405 for GET requests before
the login check, so crawlers with the old URLs still don't end up at
the login page.

This also restores the Review button that opens the review popup, which
was accidentally replaced by the old Comment/Review dropdown when
merging main.
Now that these views use Django's `require_POST` and `login_required`
directly, this test was mostly testing Django's own behaviour. POST
requests to the patch modification views are already exercised by
`test_remove_reviewer.py`.
@JelteF
JelteF marked this pull request as ready for review October 25, 2026 21:12
@JelteF
JelteF merged commit 33f7288 into main Oct 25, 2026
2 checks passed
@JelteF
JelteF deleted the post-for-modifications branch October 25, 2026 21:12
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.

Make all modifications be POST rather than GET

2 participants