A request to create an MR is considered a "unauthenticated" request
Summary
When a rate limit for unauthenticated requests is set and this limit is reached, requests to create MRs will be blocked
For some reason, the headers
of the request to create the MR did not carry the CSRF token, which caused the request to be identified as an unauthenticated request.
Our users were confused by this. Because a normal user or even an administrator was logged in, the request he made should be considered as an authenticated request instead of unauthenticated one. At the same time, there is no precise definition of unauthenticated request in the document.
Steps to reproduce
-
Log in as administrator and checked
Enable unauthenticated web request rate limit
-
Access gitlab in another browser without logging in, and deliberately reach the frequency limit in step 1
-
Return to administrator and create MR in any project
-
Creating actions will be blocked
Example Project
This problem occurs in self-managed, so there is no demo project on gitlab.com.
What is the current bug behavior?
When a rate limit for unauthenticated requests is set and this limit is reached, requests to create MRs will be blocked
What is the expected correct behavior?
Creating MRs is not blocked.
Relevant logs and/or screenshots
See Steps to reproduce part.
Output of checks
This problem occurs in at least 15-11
and latest versions including 16.10
which is not yet released.
Possible fixes
Considering that some requests put the csrf token into the body instead of headers, we can take them out for judgment
/lib/gitlab/request_forgery_protection.rb#L34
git diff
diff --git a/lib/gitlab/request_forgery_protection.rb b/lib/gitlab/request_forgery_protection.rb
index 3a389d3363f8..3832265a15c0 100644
--- a/lib/gitlab/request_forgery_protection.rb
+++ b/lib/gitlab/request_forgery_protection.rb
@@ -33,6 +33,10 @@ def self.call(env)
def self.verified?(env)
minimal_env = env.slice('REQUEST_METHOD', 'rack.session', 'HTTP_X_CSRF_TOKEN')
.merge('rack.input' => '')
+
+ authenticity_token = Rack::Request.new(env).params['authenticity_token']
+ minimal_env['HTTP_X_CSRF_TOKEN'] ||= authenticity_token
+
call(minimal_env)
true