ruby-proxy-headers 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b268cd14cb2ce0cd1b3c0a59ddf0c9020f65af6cd414b23202996d3868f837e
4
- data.tar.gz: 16a7d3756a1bc7b0b90e85ce5b8dca41959f79a178238a051a256ca49b0e55fa
3
+ metadata.gz: 30f82103fa860333b7df81d1b90271b048a8dd4e334bcb74caf5c762c2c7d695
4
+ data.tar.gz: 296932a159549772f64c66a305a794800f54a70f08b08f2e6e31cf5270d84c63
5
5
  SHA512:
6
- metadata.gz: 450bd0c6e87d23873d11f0970989743c8171772d38ba8db7c3094d8badfc7eb354ad690c4b8b19a0c881255e7613e07054ca113a7f64b0a3956a2d80aacc1cb7
7
- data.tar.gz: 762c4662050a554d9b8e280766322ee5e4aee6611d9ed6fbd5414b79b3703bd5328398cb290e2ad4edb8c3a7cb46e95f3997b6f734c6d9eb5f12eb67e9f33c48
6
+ metadata.gz: 92f5f07379e76973c41159aadf9ff343dad72fd7df8ab14a6c090805b7af2c2f52af6ac048916de4a2f65f8e70efc4f11831d721ed16987b9859a14affc069bf
7
+ data.tar.gz: 87c47f3acd8ed3d0741b3075999f632e6998f59cdfb86606de02227fdf3fc9a72c78355964e048c29e8dae02d340d19f18b3b77ea3a131b92ad123e345a41329
data/README.md CHANGED
@@ -1,3 +1,4 @@
1
+ [![Gem Version](https://badge.fury.io/rb/ruby-proxy-headers.svg)](https://badge.fury.io/rb/ruby-proxy-headers)
1
2
  # Ruby Proxy Headers
2
3
 
3
4
  Send and receive custom proxy headers during HTTPS `CONNECT` tunneling in modern Ruby HTTP workflows (for example [ProxyMesh](https://proxymesh.com) `X-ProxyMesh-IP` / `X-ProxyMesh-Country`).
@@ -31,6 +31,8 @@ module RubyProxyHeaders
31
31
  # @param target_port [Integer] Target port (default: 443)
32
32
  # @return [OpenSSL::SSL::SSLSocket] TLS-wrapped socket to target
33
33
  def connect(target_host, target_port = 443)
34
+ validate_connect_target!(target_host, target_port)
35
+
34
36
  # Connect to proxy
35
37
  @socket = TCPSocket.new(@proxy[:host], @proxy[:port])
36
38
  @socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
@@ -74,6 +76,7 @@ module RubyProxyHeaders
74
76
 
75
77
  # Add custom proxy headers
76
78
  @proxy_headers.each do |name, value|
79
+ RubyProxyHeaders.validate_header!(name, value)
77
80
  request_lines << "#{name}: #{value}"
78
81
  end
79
82
 
@@ -131,6 +134,17 @@ module RubyProxyHeaders
131
134
  @socket = ssl_socket
132
135
  end
133
136
 
137
+ def validate_connect_target!(host, port)
138
+ if RubyProxyHeaders::INVALID_HEADER_VALUE_RE.match?(host.to_s)
139
+ raise ArgumentError,
140
+ "CONNECT target host contains invalid characters (CR, LF, or NUL): #{host.inspect}"
141
+ end
142
+ if RubyProxyHeaders::INVALID_HEADER_VALUE_RE.match?(port.to_s)
143
+ raise ArgumentError,
144
+ "CONNECT target port contains invalid characters (CR, LF, or NUL): #{port.inspect}"
145
+ end
146
+ end
147
+
134
148
  def raise_connect_error
135
149
  case @proxy_response_status
136
150
  when 407
@@ -82,6 +82,7 @@ module RubyProxyHeaders
82
82
  end
83
83
  if proxy_connect_request_headers&.any?
84
84
  proxy_connect_request_headers.each do |k, v|
85
+ RubyProxyHeaders.validate_header!(k, v)
85
86
  buf << "#{k}: #{v}\r\n"
86
87
  end
87
88
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyProxyHeaders
4
- VERSION = '0.2.1'
4
+ VERSION = '0.2.2'
5
5
  end
@@ -4,8 +4,22 @@ require_relative 'ruby_proxy_headers/version'
4
4
  require_relative 'ruby_proxy_headers/net_http'
5
5
 
6
6
  module RubyProxyHeaders
7
+ INVALID_HEADER_NAME_RE = /[\r\n\0]/
8
+ INVALID_HEADER_VALUE_RE = /[\r\n\0]/
9
+
7
10
  # CONNECT response headers from the last Net::HTTP-based proxied HTTPS request on this thread.
8
11
  def self.proxy_connect_response_headers
9
12
  Thread.current[:ruby_proxy_headers_connect_headers]
10
13
  end
14
+
15
+ # Raises ArgumentError if +name+ or +value+ contain CR, LF, or NUL bytes
16
+ # that would allow HTTP header injection in a raw CONNECT request.
17
+ def self.validate_header!(name, value)
18
+ if INVALID_HEADER_NAME_RE.match?(name.to_s)
19
+ raise ArgumentError, "proxy CONNECT header name contains invalid characters (CR, LF, or NUL): #{name.inspect}"
20
+ end
21
+ if INVALID_HEADER_VALUE_RE.match?(value.to_s)
22
+ raise ArgumentError, "proxy CONNECT header value contains invalid characters (CR, LF, or NUL): #{value.inspect}"
23
+ end
24
+ end
11
25
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-proxy-headers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - ProxyMesh
@@ -163,6 +163,20 @@ dependencies:
163
163
  - - "~>"
164
164
  - !ruby/object:Gem::Version
165
165
  version: '1.6'
166
+ - !ruby/object:Gem::Dependency
167
+ name: webmock
168
+ requirement: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - "~>"
171
+ - !ruby/object:Gem::Version
172
+ version: '3.18'
173
+ type: :development
174
+ prerelease: false
175
+ version_requirements: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - "~>"
178
+ - !ruby/object:Gem::Version
179
+ version: '3.18'
166
180
  description: |
167
181
  Extensions for Ruby HTTP stacks to send custom headers on HTTPS CONNECT to a proxy
168
182
  and read headers from the proxy CONNECT response (e.g. X-ProxyMesh-IP).
@@ -207,7 +221,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
207
221
  - !ruby/object:Gem::Version
208
222
  version: '0'
209
223
  requirements: []
210
- rubygems_version: 3.6.7
224
+ rubygems_version: 4.0.16
211
225
  specification_version: 4
212
226
  summary: Custom proxy CONNECT headers for Ruby HTTP clients (ProxyMesh, etc.)
213
227
  test_files: []