Skip to content

Commit 18ea109

Browse files
committed
Decode user and password from env configured proxy
If someone sets an env variable defining a http_proxy, containing a username / password with percent-encoded characters, then the resulting base64 encoded auth header will be wrong. For example, suppose a username is `Y\X` and the password is `R%S] ?X`. Properly URL encoded the proxy url would be: http://Y%5CX:R%25S%5D%20%3FX@proxy.example:8000 The resulting proxy auth header should be: `WVxYOlIlU10gP1g=`, but the getters defined by ruby StdLib `URI` return a username `Y%5CX` and password `R%25S%5D%20%3FX`, resulting in `WSU1Q1g6UiUyNVMlNUQlMjAlM0ZY`. As a result the proxy will deny the request. Please note that this is my first contribution to the ruby ecosystem, to standard lib especially and I am not a ruby developer. Sorry for that and a happy and healthy 2021! References: - https://gitlab.com/gitlab-org/gitlab/-/issues/289836 - https://bugs.ruby-lang.org/projects/ruby-master/repository/trunk/revisions/58461 - https://bugs.ruby-lang.org/issues/17542
1 parent d9ba437 commit 18ea109

File tree

3 files changed

+26
-3
lines changed

3 files changed

+26
-3
lines changed

Gemfile.lock

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
PATH
22
remote: .
33
specs:
4-
net-http (0.1.0)
4+
net-http (0.1.1)
5+
net-protocol
6+
uri
57

68
GEM
79
remote: https://rubygems.org/
810
specs:
11+
net-protocol (0.1.0)
912
power_assert (1.1.5)
1013
rake (13.0.1)
1114
test-unit (3.3.5)
1215
power_assert
16+
uri (0.10.1)
1317

1418
PLATFORMS
1519
ruby

lib/net/http.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,7 +1180,8 @@ def proxy_port
11801180
# The username of the proxy server, if one is configured.
11811181
def proxy_user
11821182
if ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE && @proxy_from_env
1183-
proxy_uri&.user
1183+
user = proxy_uri&.user
1184+
CGI.unescape(user) unless user.nil?
11841185
else
11851186
@proxy_user
11861187
end
@@ -1189,7 +1190,8 @@ def proxy_user
11891190
# The password of the proxy server, if one is configured.
11901191
def proxy_pass
11911192
if ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE && @proxy_from_env
1192-
proxy_uri&.password
1193+
pass = proxy_uri&.password
1194+
CGI.unescape(pass) unless pass.nil?
11931195
else
11941196
@proxy_pass
11951197
end

test/net/http/test_http.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,23 @@ def test_proxy_eh_ENV_with_user
188188
end
189189
end
190190

191+
def test_proxy_eh_ENV_with_urlencoded_user
192+
TestNetHTTPUtils.clean_http_proxy_env do
193+
ENV['http_proxy'] = 'http://Y%5CX:R%25S%5D%20%3FX@proxy.example:8000'
194+
195+
http = Net::HTTP.new 'hostname.example'
196+
197+
assert_equal true, http.proxy?
198+
if Net::HTTP::ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE
199+
assert_equal "Y\\X", http.proxy_user
200+
assert_equal "R%S] ?X", http.proxy_pass
201+
else
202+
assert_nil http.proxy_user
203+
assert_nil http.proxy_pass
204+
end
205+
end
206+
end
207+
191208
def test_proxy_eh_ENV_none_set
192209
TestNetHTTPUtils.clean_http_proxy_env do
193210
assert_equal false, Net::HTTP.new('hostname.example').proxy?

0 commit comments

Comments
 (0)