-
Notifications
You must be signed in to change notification settings - Fork 101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: Prevent race condition on unique-submission forms #1841
Conversation
a44fcdd
to
81e7ba9
Compare
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## main #1841 +/- ##
============================================
- Coverage 44.62% 44.61% -0.01%
- Complexity 658 662 +4
============================================
Files 58 58
Lines 2593 2600 +7
============================================
+ Hits 1157 1160 +3
- Misses 1436 1440 +4 |
@susnux Looks good :) Just a little question: You check all submissions against the new submission for uniqueness. If we have a form with lots of submissions, isn't this very resource consuming? |
@Chartman123 I pushed a performance fix, what do you think? |
724e1b6
to
7b7b92b
Compare
Yes, something like this was on my mind 👍🏻 |
// Insert new submission | ||
$this->submissionMapper->insert($submission); | ||
$submissionId = $submission->getId(); | ||
|
||
// Ensure the form is unique if needed. | ||
// If we can not submit anymore then the submission must be unique | ||
if (!$this->formsService->canSubmit($form) && !$this->submissionService->isUniqueSubmission($submission)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (!$this->formsService->canSubmit($form) && !$this->submissionService->isUniqueSubmission($submission)) { | |
if (!$this->formsService->canSubmit($form) && !$this->submissionService->isUniqueSubmission($submission)) { |
Since the first part of this condition already exists up exactly and throws an exception, if this exception exists this part of the code would never be reached?
Or does canSubmit
result change after the first insertion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a calculated form prop https://github.com/nextcloud/forms/blob/main/lib%2FService%2FFormsService.php#L271
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea is here if the user still can submit after insert then multiple submissions are allowed. If not submissions have to be unique and we need to verify the answer is the only one.
While writing this: Is this not a (unrelated to this PR) bug? If unique submissions are enabled why should the owner be allowed to submit multiple?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why should the owner be allowed to submit multiple?
Good question, the only reason I could think of: The owner fills the form for someone else who can't access the online form for some reason but needs to?
This part of the code was added by @jotoeri 2 years ago. So let's ask him what was his intention :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, i'm not 100% sure, but i think we shortly discussed that somewhere that once. Otherwise that change wouldn't have gone through just like that.^^
Anyways: I would interpret the Owner as some kind of an administrator for the form, being allowed to do everything with it. The owner could also just remove the submitOnce, submit and then re-set it, which is just annoying handling. So why should we block the owner of doing whatever he/she wants to do with the form?
In fact it's mostly a UX-Question wrt. the owner, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fenn-cs do the comments help you to finish your review?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left and inline remark/question to help me review.
@susnux One thing that just came to my mind: by moving the check right before the insert, we would check for valid submission data even if a user were no longer allowed to submit. This creates some unnecessary checks in that case. |
Well this only happens when using API and not our frontend as the frontend already checks that. Meaning only API usage from external application will cause this. If we keep the order of the checks the time frame for the attack is a bit wider but as we sanitize afterwards it would be reverted anyways. |
For me it's ok to keep it the way you implemented it currently 👍🏻 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just squash the fixup commit, then we can merge it from my point of view :)
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
7b7b92b
to
655762a
Compare
Done |
/backport to stable3 |
Currently a series of requests can be crafted so that multiple submissions of the same user are inserted.
As the unique property of a submission is only checked once so that if multiple requests arrive at the server right in the same time they will all be inserted.
To prevent this the time window is minimized by placing the check right before the insert and check afterwards if the submission really is unique.