`include` directive in .gitlab-ci.yml allows SSRF requests, may have other problems
Summary
In EE, users can include a line like the following in their .gitlab-ci.yml files:
include: http:/.....
The implementing code is https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/lib/gitlab/ci/external/file/remote.rb
This uses Gitlab::HTTP to perform the request, but explicitly passes allow_local_requests: true to the call.
In turn, this means that arbitrary GET requests can be performed against internal resources.
Data exfiltration potential is limited to resources that respond with a YAML file following certain constraints. This feels like a low-severity SSRF, but probably worth fixing anyway.
Initially I was interested in whether file:///... URLs would be accepted, but it seems they are not. HTTParty only permits HTTP, HTTPS and generic URL schemes.
We might want to perform a thorough audit of both the remote and local functionality of this directive to ensure that:
- "generic" URIs don't introduce any risks
- "local" resources (which I think means local to the git checkout) aren't vulnerable to path traversal, other horrors
Steps to reproduce
- Run gitlab with SSRF protection enabled
- Run HTTP server on localhost:8080 or so
- Upload a
.gitlab-ci.ymlfile containinginclude: http://localhost:8080or so
What is the current bug behavior?
HTTP request against internal IP is performed
What is the expected correct behavior?
Request should not be performed
Possible fixes
Just remove allow_local_requests: true. I don't think this will break most HTTP requests referring to, e.g. GitLab.com when the pipeline is being run on GitLab.com - the hostname will resolve to the external load balancer, which won't be a private IP, so all should be well.
If we make this change, self-hosted instances that run GitLab internally on a private IP will need to ensure that that IP isn't forbidden. This will be true of other integrations, though, so I think that's OK.
/cc @jritchey @ayufan @dblessing @DylanGriffith