appium_lib_core 12.1.0 → 12.2.0

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: cb6226306206eafec9dbd6f2c2f1ac09c86fee48ee841be8616df8acf6ce56a5
4
- data.tar.gz: ab63b82ecafb824a8b0edfdcbcba8d9ec0e1530e8a42f86c4c95aa95246a6871
3
+ metadata.gz: b8b24034cf3c55ee8315eea3f56344e02705caed8f7cfd0d2a859ff3e8195a79
4
+ data.tar.gz: a3c665e85f24c552cd8b80a52934d81fad4764794cea23d2af38632641d1a890
5
5
  SHA512:
6
- metadata.gz: 2573d787ffb963708aae21889b3f3ab6f68b7747b623a7ba906fff4065f7514557608dfaa6b9b05b8ceddaf4a6f0ae96edb20a436af01e3148c5c13ed64bf598
7
- data.tar.gz: 21c2e01a1bdfb8bfd81ad309eb8e6fbdfa6d5abba485c77b52c257652be9c8b58a4f62a110a78128f2f26438e0d018cebfe6f1cffd8f60e1aa91293c2d14e269
6
+ metadata.gz: a06868c2fe0fd5c243aa18338029510dedf336f8911073289324334b4b3cfdbc6f2b247ce4ca42da2ec0f301223dfbdf2f89bfed5bbbcc452bc4bd7ae82e14ea
7
+ data.tar.gz: 472c0d31754e6e48a673bc0d363fd54ccf4d6f5be1f9b1880a0ef60cdf1d4f6a91214ee66cc59bff20a1020433ef7c4b4cd8b9ae38d084c1225193feed79b877
data/CHANGELOG.md CHANGED
@@ -2,6 +2,9 @@
2
2
  All notable changes to this project will be documented in this file.
3
3
  Read `release_notes.md` for commit level details.
4
4
 
5
+ ## [12.2.0] - 2026-06-25
6
+ - Add validation for direct connect URL when `direct_connect` capability is `true`.
7
+
5
8
  ## [12.1.0] - 2026-03-21
6
9
  - Replace internal `add_command` method with Selnium Bridge's `add_command` to simplify the codebase.
7
10
 
data/Gemfile CHANGED
@@ -8,7 +8,7 @@ gem 'minitest', '~> 5.0'
8
8
  gem 'minitest-reporters', '~> 1.1'
9
9
  gem 'parallel_tests'
10
10
  gem 'rake', '~> 13.0'
11
- gem 'rubocop', '1.85.1'
11
+ gem 'rubocop', '1.86.1'
12
12
  gem 'simplecov'
13
13
  gem 'steep', '~> 1.10.0'
14
14
  gem 'webmock', '~> 3.26.0'
@@ -13,6 +13,9 @@
13
13
  # limitations under the License.
14
14
 
15
15
  require 'uri'
16
+ require 'socket'
17
+ require 'ipaddr'
18
+ require 'timeout'
16
19
 
17
20
  module Appium
18
21
  # The struct for 'location'
@@ -99,6 +102,59 @@ module Appium
99
102
  @port = capabilities[W3C_KEYS[:port]] || capabilities[KEYS[:port]]
100
103
  @path = capabilities[W3C_KEYS[:path]] || capabilities[KEYS[:path]]
101
104
  end
105
+
106
+ def valid?
107
+ return false unless [@protocol, @host, @port, @path].none?(&:nil?)
108
+
109
+ addresses = resolve_addresses(@host)
110
+ return false if addresses.empty?
111
+
112
+ addresses.find { |ip| disallowed? ip }.nil?
113
+ end
114
+
115
+ private
116
+
117
+ # Do not allow loopback, link-local, unspecified and multicast addresses for
118
+ # direct connect since they are not accessible from outside of the server.
119
+ DNS_RESOLVE_TIMEOUT_SECONDS = 30
120
+ LOOPBACK_RANGES = [IPAddr.new('127.0.0.0/8'), IPAddr.new('::1/128')].freeze
121
+ LINK_LOCAL_RANGES = [IPAddr.new('169.254.0.0/16'), IPAddr.new('fe80::/10')].freeze
122
+ UNSPECIFIED_RANGES = [IPAddr.new('0.0.0.0/32'), IPAddr.new('::/128')].freeze
123
+ MULTICAST_RANGES = [IPAddr.new('224.0.0.0/4'), IPAddr.new('ff00::/8')].freeze
124
+ DISALLOWED_RANGES = [
125
+ *LOOPBACK_RANGES,
126
+ *LINK_LOCAL_RANGES,
127
+ *UNSPECIFIED_RANGES,
128
+ *MULTICAST_RANGES
129
+ ].freeze
130
+
131
+ def resolve_addresses(host)
132
+ normalized_host = host.to_s.delete_prefix('[').delete_suffix(']')
133
+ # If the host is already an IP literal, skip DNS resolution to avoid blocking calls
134
+ return [normalized_host] if ip_literal?(normalized_host)
135
+
136
+ Timeout.timeout(DNS_RESOLVE_TIMEOUT_SECONDS) do
137
+ Socket.getaddrinfo(normalized_host, nil).map { |entry| entry[3] }.uniq
138
+ end
139
+ rescue Timeout::Error
140
+ ::Appium::Logger.warn("DNS resolution for '#{host}' timed out after #{DNS_RESOLVE_TIMEOUT_SECONDS}s")
141
+ []
142
+ rescue SocketError => e
143
+ ::Appium::Logger.warn("Failed to resolve host '#{host}' for direct connect: #{e.message}")
144
+ []
145
+ end
146
+
147
+ def ip_literal?(host)
148
+ IPAddr.new(host)
149
+ true
150
+ rescue IPAddr::InvalidAddressError
151
+ false
152
+ end
153
+
154
+ def disallowed?(ip)
155
+ address = IPAddr.new ip
156
+ DISALLOWED_RANGES.any? { |range| range.include? address }
157
+ end
102
158
  end
103
159
 
104
160
  class Driver
@@ -164,8 +220,7 @@ module Appium
164
220
  # @return [Appium::Core::Base::Driver]
165
221
  attr_reader :driver
166
222
 
167
- # <b>[Experimental feature]</b><br>
168
- # Enable an experimental feature updating Http client endpoint following below keys by Appium/Selenium server.<br>
223
+ # Enable updating Http client endpoint following below keys by Appium/Selenium server.<br>
169
224
  # This works with {Appium::Core::Base::Http::Default}.
170
225
  #
171
226
  # If your Selenium/Appium server decorates the new session capabilities response with the following keys:<br>
@@ -177,6 +232,12 @@ module Appium
177
232
  # ignore them if this parameter is <code>false</code>. Defaults to true.
178
233
  # These keys can have <code>appium:</code> prefix.
179
234
  #
235
+ # Note that the server should provide the keys with valid values. The host value must not be
236
+ # - loopback (for example `127.0.0.1`, `::1`)
237
+ # - link-local (for example `169.254.x.x`, `fe80::/10`)
238
+ # - unspecified/wildcard (`0.0.0.0`, `::`)
239
+ # - multicast (`224.0.0.0/4`, `ff00::/8`)
240
+ #
180
241
  # @return [Bool]
181
242
  attr_reader :direct_connect
182
243
 
@@ -419,7 +480,14 @@ module Appium
419
480
 
420
481
  if @direct_connect
421
482
  d_c = DirectConnections.new(@driver.capabilities)
422
- @driver.update_sending_request_to(protocol: d_c.protocol, host: d_c.host, port: d_c.port, path: d_c.path)
483
+ if d_c.valid?
484
+ @driver.update_sending_request_to(protocol: d_c.protocol, host: d_c.host, port: d_c.port, path: d_c.path)
485
+ else
486
+ ::Appium::Logger.warn(
487
+ "Direct connect is enabled but the server did not provide valid direct connect information (#{d_c.protocol}, #{d_c.host}, #{d_c.port}, #{d_c.path}). " \
488
+ "Continue with the original URL (#{@custom_url})"
489
+ )
490
+ end
423
491
  end
424
492
  rescue Errno::ECONNREFUSED => e
425
493
  raise "ERROR: Unable to connect to Appium. Is the server running on #{@custom_url}? Error: #{e}"
@@ -14,7 +14,7 @@
14
14
 
15
15
  module Appium
16
16
  module Core
17
- VERSION = '12.1.0' unless defined? ::Appium::Core::VERSION
18
- DATE = '2026-03-21' unless defined? ::Appium::Core::DATE
17
+ VERSION = '12.2.0' unless defined? ::Appium::Core::VERSION
18
+ DATE = '2026-04-19' unless defined? ::Appium::Core::DATE
19
19
  end
20
20
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appium_lib_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 12.1.0
4
+ version: 12.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kazuaki MATSUO
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-03-22 00:00:00.000000000 Z
11
+ date: 2026-04-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: selenium-webdriver