package-audit 0.6.2 → 0.7.1

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: cca016948e4ab3d4643c8e7c7b6bca064873a0b390709d6318d899ee03464c36
4
- data.tar.gz: '037543298033670ef8cd62ceb31a021389e55b0baf634117777018933d89b6b3'
3
+ metadata.gz: a14d75d3c6f64af8c327c492e0d0c1bcf98fc3119964e63d944fc33fc6ce6b8e
4
+ data.tar.gz: 01f5eaac43d53a65ac42a46a736793b8dbe56f4ad3531a8e649d9516b85a5027
5
5
  SHA512:
6
- metadata.gz: 494ad5afd212b57e596fd599b8b57f86453c3cb5f988d4ae88a572c685a83f8ba4c39c750353e962453d98ba3336d30ecf1da729ffad4c26cfce418c049e56eb
7
- data.tar.gz: 6088d06e5a5ccbf73d9ecd3e3fbcd130030dbc47ca861a910f56ba21850ae467eda5f7a4b0064200d18bb1d7fe461f7db561f64f471b0c747a25d6bc18ec9115
6
+ metadata.gz: 9f2599769354017f84a5eb4f5da8cb6b67b69be12ed6f67126ed0701b1746461960c24ecd1ba7d2cf81d5719ca18234f1f9bdcb645a5bb9d8916faaca040ee96
7
+ data.tar.gz: 9eeeb933dd6e5535c0fdcdfca6fea339ca34fc1a611460b68ea0274da083ec08be63424eb82c7229ed939cf05fe49621bbf9f4d04af9abffc6001f7a43e507cb
@@ -12,6 +12,8 @@ module Package
12
12
  end
13
13
 
14
14
  def format # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
15
+ return @curr if @target.nil? # No latest version available
16
+
15
17
  version_parts = @curr.split('.').map(&:to_i)
16
18
  latest_version_parts = @target.split('.').map(&:to_i)
17
19
  curr_tokens = @curr.split('.')
@@ -14,6 +14,8 @@ module Package
14
14
  end
15
15
 
16
16
  def format
17
+ return 'unknown' if @date.nil? # Handle private packages
18
+
17
19
  seconds_since_date = (Time.now - Time.parse(@date)).to_i
18
20
 
19
21
  if seconds_since_date >= Const::Time::SECONDS_ELAPSED_TO_BE_OUTDATED
@@ -55,15 +55,16 @@ module Package
55
55
  private
56
56
 
57
57
  def fetch_from_package_json
58
- package_json = JSON.parse(File.read("#{@dir}/#{Const::File::PACKAGE_JSON}"), symbolize_names: true)
59
- default_deps = package_json[:dependencies] || {}
60
- dev_deps = package_json[:devDependencies] || {}
58
+ package_json = JSON.parse(File.read("#{@dir}/#{Const::File::PACKAGE_JSON}"))
59
+ default_deps = package_json['dependencies'] || {}
60
+ dev_deps = package_json['devDependencies'] || {}
61
+ resolutions = package_json['resolutions'] || {}
61
62
 
62
63
  # Filter out local dependencies before processing
63
64
  default_deps = filter_local_dependencies(default_deps)
64
65
  dev_deps = filter_local_dependencies(dev_deps)
65
66
 
66
- [default_deps, dev_deps]
67
+ [default_deps, dev_deps, resolutions]
67
68
  end
68
69
 
69
70
  def filter_local_dependencies(dependencies)
@@ -79,9 +80,10 @@ module Package
79
80
  end
80
81
 
81
82
  def fetch_from_lock_file
82
- default_deps, dev_deps = fetch_from_package_json
83
+ default_deps, dev_deps, resolutions = fetch_from_package_json
83
84
  if File.exist?("#{@dir}/#{Const::File::YARN_LOCK}")
84
- YarnLockParser.new("#{@dir}/#{Const::File::YARN_LOCK}").fetch(default_deps || {}, dev_deps || {})
85
+ YarnLockParser.new("#{@dir}/#{Const::File::YARN_LOCK}").fetch(default_deps || {}, dev_deps || {},
86
+ resolutions || {})
85
87
  else
86
88
  []
87
89
  end
@@ -1,5 +1,6 @@
1
1
  require 'json'
2
2
  require 'net/http'
3
+ require 'openssl'
3
4
  require 'socket'
4
5
 
5
6
  module Package
@@ -7,42 +8,27 @@ module Package
7
8
  module Npm
8
9
  class NpmMetaData
9
10
  REGISTRY_URL = 'https://registry.npmjs.org'
11
+ BATCH_SIZE = 10 # Process 10 packages at a time
12
+ MAX_RETRIES = 3 # Maximum number of retries per request
13
+ INITIAL_RETRY_DELAY = 1 # Initial retry delay in seconds
14
+ TIMEOUT = 10 # Timeout in seconds
10
15
 
11
16
  def initialize(packages)
12
17
  @packages = packages
13
18
  end
14
19
 
15
- def fetch # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
16
- threads = @packages.map do |package|
17
- Thread.new do
18
- response = Net::HTTP.get_response(URI.parse("#{REGISTRY_URL}/#{package.name}"))
19
- raise "Unable to fetch meta data for #{package.name} from #{REGISTRY_URL} (#{response.class})" unless
20
- response.is_a?(Net::HTTPSuccess)
21
-
22
- json_package = JSON.parse(response.body, symbolize_names: true)
23
- update_meta_data(package, json_package)
24
- rescue Net::TimeoutError, Net::OpenTimeout, Net::ReadTimeout => e
25
- warn "Warning: Network timeout while fetching metadata for #{package.name}: #{e.message}"
26
- Thread.current[:exception] = e
27
- rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH => e
28
- warn "Warning: Network error while fetching metadata for #{package.name}: #{e.message}"
29
- Thread.current[:exception] = e
30
- rescue StandardError => e
31
- Thread.current[:exception] = e
32
- end
33
- end
34
-
20
+ def fetch # rubocop:disable Metrics/MethodLength
35
21
  network_errors = []
36
- threads.each do |thread|
37
- thread.join
38
- next unless thread[:exception]
39
-
40
- case thread[:exception]
41
- when Net::TimeoutError, Net::OpenTimeout, Net::ReadTimeout, SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH # rubocop:disable Layout/LineLength
42
- network_errors << thread[:exception]
43
- else
44
- raise thread[:exception]
22
+
23
+ @packages.each_slice(BATCH_SIZE) do |batch|
24
+ threads = batch.map do |package|
25
+ Thread.new do
26
+ fetch_package_metadata(package, network_errors)
27
+ end
45
28
  end
29
+
30
+ threads.each(&:join)
31
+ sleep(0.1) # Small delay between batches to avoid overwhelming the server
46
32
  end
47
33
 
48
34
  unless network_errors.empty?
@@ -55,10 +41,88 @@ module Package
55
41
 
56
42
  private
57
43
 
44
+ def fetch_package_metadata(package, network_errors, retry_count = 0)
45
+ response = make_request_with_retry(package.name, retry_count)
46
+ return if response.nil?
47
+
48
+ json_package = JSON.parse(response.body, symbolize_names: true)
49
+ update_meta_data(package, json_package)
50
+ rescue StandardError => e
51
+ handle_error(package, e, network_errors)
52
+ end
53
+
54
+ def make_request_with_retry(package_name, retry_count) # rubocop:disable Metrics/MethodLength
55
+ response = make_request(package_name)
56
+ return nil if response.is_a?(Net::HTTPNotFound) # Skip 404s - likely private packages
57
+
58
+ raise "Unable to fetch meta data for #{package_name} from #{REGISTRY_URL} (#{response.class})" unless
59
+ response.is_a?(Net::HTTPSuccess)
60
+
61
+ response
62
+ rescue Net::OpenTimeout, Net::ReadTimeout, SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH => e
63
+ return nil if retry_count >= MAX_RETRIES
64
+
65
+ retry_after_delay(retry_count)
66
+ retry_count += 1
67
+ retry
68
+ rescue OpenSSL::SSL::SSLError => e
69
+ warn "Warning: SSL verification failed for #{package_name}: #{e.message}"
70
+ nil
71
+ end
72
+
73
+ def handle_error(package, error, network_errors)
74
+ # Don't warn about 404s for private packages
75
+ return if error.is_a?(RuntimeError) && error.message.include?('(Net::HTTPNotFound)')
76
+
77
+ warn "Warning: Error while fetching metadata for #{package.name}: #{error.message}"
78
+ network_errors << error
79
+ end
80
+
81
+ def make_request(package_name)
82
+ uri = URI(REGISTRY_URL)
83
+ http = Net::HTTP.new(uri.host, uri.port)
84
+ http.use_ssl = true
85
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
86
+ http.cert_store = OpenSSL::X509::Store.new
87
+ http.cert_store.set_default_paths
88
+ http.read_timeout = TIMEOUT
89
+ http.open_timeout = TIMEOUT
90
+
91
+ path = "/#{package_name}"
92
+ http.get(path)
93
+ end
94
+
95
+ def retry_after_delay(retry_count)
96
+ delay = INITIAL_RETRY_DELAY * (2**retry_count) # Exponential backoff
97
+ sleep(delay)
98
+ end
99
+
58
100
  def update_meta_data(package, json_data)
59
- latest_version = json_data[:'dist-tags'][:latest]
60
- version_date = json_data[:time][package.version.to_sym]
61
- latest_version_date = json_data[:time][latest_version.to_sym]
101
+ # No early return - let's try to get metadata even if version is unknown
102
+
103
+ latest_version = find_latest_version(json_data)
104
+ return unless latest_version
105
+
106
+ dates = find_version_dates(json_data, package.version, latest_version)
107
+ return unless dates
108
+
109
+ update_package_metadata(package, latest_version, dates)
110
+ end
111
+
112
+ def find_latest_version(json_data)
113
+ json_data[:'dist-tags']&.[](:latest)
114
+ end
115
+
116
+ def find_version_dates(json_data, version, latest_version)
117
+ version_date = json_data[:time]&.[](version.to_sym)
118
+ latest_version_date = json_data[:time]&.[](latest_version.to_sym)
119
+ return unless version_date || latest_version_date # Return if both dates are missing
120
+
121
+ [version_date || latest_version_date, latest_version_date || version_date]
122
+ end
123
+
124
+ def update_package_metadata(package, latest_version, dates)
125
+ version_date, latest_version_date = dates
62
126
  package.update version_date: Time.parse(version_date).strftime('%Y-%m-%d'),
63
127
  latest_version: latest_version,
64
128
  latest_version_date: Time.parse(latest_version_date).strftime('%Y-%m-%d')
@@ -32,17 +32,32 @@ module Package
32
32
 
33
33
  private
34
34
 
35
- def update_meta_data(json) # rubocop:disable Metrics/AbcSize
36
- parent_name = json[:data][:resolution][:path].split('>').first
35
+ def update_meta_data(json)
36
+ resolution_path = json.dig(:data, :resolution, :path)
37
+ return unless resolution_path # Skip if no resolution path (private package)
38
+
39
+ parent_name = resolution_path.split('>').first
37
40
  advisory = json[:data][:advisory]
38
- name = advisory[:module_name]
39
- version = advisory[:findings][0][:version]
41
+ package_info = extract_package_info(advisory)
42
+ update_vulnerability_info(package_info, parent_name, advisory[:severity])
43
+ end
44
+
45
+ def extract_package_info(advisory)
46
+ {
47
+ name: advisory[:module_name],
48
+ version: advisory[:findings][0][:version]
49
+ }
50
+ end
51
+
52
+ def update_vulnerability_info(package_info, parent_name, severity)
53
+ name = package_info[:name]
54
+ version = package_info[:version]
40
55
  full_name = "#{name}@#{version}"
41
- vulnerability = advisory[:severity] || Enum::VulnerabilityType::UNKNOWN
56
+ vulnerability = severity || Enum::VulnerabilityType::UNKNOWN
42
57
 
43
- @vuln_hash[full_name] = Package.new(name, version, 'node') unless @vuln_hash.key? full_name
58
+ @vuln_hash[full_name] ||= Package.new(name, version, 'node')
44
59
  @vuln_hash[full_name].update vulnerabilities: @vuln_hash[full_name].vulnerabilities + [vulnerability]
45
- @vuln_hash[full_name].update groups: @pkg_hash[parent_name].groups.map(&:to_s)
60
+ @vuln_hash[full_name].update groups: @pkg_hash[parent_name]&.groups&.map(&:to_s) || []
46
61
  end
47
62
  end
48
63
  end
@@ -9,45 +9,127 @@ module Package
9
9
  @yarn_lock_path = yarn_lock_path
10
10
  end
11
11
 
12
- def fetch(default_deps, dev_deps) # rubocop:disable Metrics/MethodLength
13
- pkgs = []
14
- default_deps.merge(dev_deps).each do |dep_name, expected_version|
15
- pkg_block = fetch_package_block(dep_name, expected_version)
16
- version = fetch_package_version(dep_name, pkg_block)
17
- pks = Package.new(dep_name.to_s, version, 'node')
18
- pks.update groups: if dev_deps.key?(dep_name)
19
- [Enum::Group::DEV]
20
- else
21
- [Enum::Group::DEFAULT, Enum::Group::DEV]
22
- end
23
- pkgs << pks
12
+ def fetch(default_deps, dev_deps, resolutions = {})
13
+ default_deps.merge(dev_deps).map do |dep_name, expected_version|
14
+ process_package(dep_name, expected_version, dev_deps, resolutions)
24
15
  end
25
- pkgs
26
16
  end
27
17
 
28
18
  private
29
19
 
30
- def fetch_package_block(dep_name, expected_version)
31
- regex = regex_pattern_for_package(dep_name, expected_version)
32
- blocks = @yarn_lock_file.match(regex)
33
- if blocks.nil? || blocks[0].nil?
34
- raise NoMatchingPatternError, "Unable to find \"#{dep_name}\" in #{@yarn_lock_path}"
20
+ def process_package(dep_name, expected_version, dev_deps, resolutions)
21
+ version_to_check = get_version_to_check(dep_name, expected_version, resolutions)
22
+ pkg_block = fetch_package_block(dep_name, version_to_check)
23
+ version = fetch_package_version(dep_name, pkg_block)
24
+ create_package(dep_name, version, dev_deps)
25
+ end
26
+
27
+ def get_version_to_check(dep_name, expected_version, resolutions)
28
+ version_to_check = resolutions[dep_name] || expected_version
29
+ return version_to_check unless version_to_check.start_with?('patch:')
30
+
31
+ patch_version = version_to_check.match(/patch:.*?@npm%3A([\d.-]+)#/)&.captures&.[](0)
32
+ patch_version || version_to_check
33
+ end
34
+
35
+ def create_package(dep_name, version, dev_deps)
36
+ pks = Package.new(dep_name.to_s, version, 'node')
37
+ pks.update groups: package_groups(dep_name, dev_deps)
38
+ pks
39
+ end
40
+
41
+ def package_groups(dep_name, dev_deps)
42
+ if dev_deps.key?(dep_name)
43
+ [Enum::Group::DEV]
44
+ else
45
+ [Enum::Group::DEFAULT, Enum::Group::DEV]
35
46
  end
47
+ end
48
+
49
+ def fetch_package_block(dep_name, expected_version)
50
+ blocks = find_package_blocks(dep_name)
51
+ raise NoMatchingPatternError, "Unable to find \"#{dep_name}\" in #{@yarn_lock_path}" if blocks.empty?
52
+
53
+ find_matching_block(blocks, dep_name, expected_version)
54
+ end
55
+
56
+ def find_package_blocks(dep_name)
57
+ block_pattern = build_block_pattern(dep_name)
58
+ @yarn_lock_file.scan(block_pattern)
59
+ end
60
+
61
+ def build_block_pattern(dep_name)
62
+ /
63
+ ^["']? # Start of line with optional quote
64
+ (?:[^"\n]+,\s*)* # Any previous entries in a comma-separated list
65
+ (?:patch:)? # Optional patch prefix
66
+ #{Regexp.escape(dep_name)}@[^:\n]+ # Our package name and version
67
+ (?:[^"\n]*,\s*[^"\n]+)* # Any following entries
68
+ ["']?:.*? # End quote and colon, followed by the rest
69
+ (?:resolution:.*?)? # Optional resolution field
70
+ (?=\n["']|\n\s*\n|\z) # Until next entry or end of file
71
+ /mx
72
+ end
36
73
 
37
- blocks[0] || ''
74
+ def find_matching_block(blocks, dep_name, expected_version)
75
+ version_pattern = build_version_pattern(dep_name, expected_version)
76
+ blocks.find { |block| block.match?(version_pattern) } || blocks.first
77
+ end
78
+
79
+ def build_version_pattern(dep_name, expected_version)
80
+ /
81
+ (?:patch:)?#{Regexp.escape(dep_name)}@
82
+ (?:npm:)?#{Regexp.escape(expected_version)}["']?(?:,|:)
83
+ /x
38
84
  end
39
85
 
40
86
  def fetch_package_version(dep_name, pkg_block)
41
- version = pkg_block.match(/version"?\s*"(.*?)"/)&.captures&.[](0)
87
+ # Try different version formats:
88
+ # 1. version: "1.2.3" - quoted version
89
+ # 2. version: 1.2.3 - unquoted version
90
+ # 3. "pkg@1.2.3": - version in package spec
91
+ # 4. "pkg@npm:1.2.3": - version with npm prefix
92
+ # Try to find version in this order:
93
+ # 1. resolution field (for overrides)
94
+ # 2. version field (both quoted and unquoted)
95
+ # 3. package spec
96
+ version = extract_version_from_block(dep_name, pkg_block)
97
+
42
98
  if version.nil?
43
99
  raise NoMatchingPatternError,
44
100
  "Unable to find the version of \"#{dep_name}\" in #{@yarn_lock_path}"
45
101
  end
46
102
 
47
- version || '0.0.0.0'
103
+ version || 'unknown'
104
+ end
105
+
106
+ def extract_version_from_block(dep_name, pkg_block)
107
+ find_resolution_version(dep_name, pkg_block) ||
108
+ find_version_field(pkg_block) ||
109
+ find_spec_version(dep_name, pkg_block)
110
+ end
111
+
112
+ def find_resolution_version(dep_name, pkg_block)
113
+ pattern = /
114
+ resolution:.*?["']#{Regexp.escape(dep_name)}@
115
+ (?:npm:)?(?:patch:#{Regexp.escape(dep_name)}@npm%3A)?
116
+ ([\d.-]+(?:-(?:beta|rc|dev)\.\d+(?:\.\d+)?)?)
117
+ (?:&hash=[a-f0-9]+)?["']
118
+ /x
119
+ pkg_block.match(pattern)&.captures&.[](0)
120
+ end
121
+
122
+ def find_version_field(pkg_block)
123
+ pattern = /version["']?\s*["']?([\d.-]+(?:-(?:beta|rc|dev)\.\d+(?:\.\d+)?)?)(?:&hash=[a-f0-9]+)?["']?(?:\s|$)/
124
+ pkg_block.match(pattern)&.captures&.[](0)
125
+ end
126
+
127
+ def find_spec_version(dep_name, pkg_block)
128
+ pattern = %r{^.*?#{Regexp.escape(dep_name)}@(?:npm:|https://[^#]+#)?(?:patch:#{Regexp.escape(dep_name)}@npm%3A)?(?:v)?([\d.-]+(?:-(?:beta|rc|dev)\.\d+(?:\.\d+)?)?)(?:&hash=[a-f0-9]+)?["']?(?:,|\s*:)}m
129
+ pkg_block.match(pattern)&.captures&.[](0)
48
130
  end
49
131
 
50
- def regex_pattern_for_package(dep_name, version)
132
+ def regex_pattern_for_package(dep_name, _version)
51
133
  # assume the package name is prefixed by a space, a quote or be the first thing on the line
52
134
  # there can be multiple comma-separated versions on the same line with or without quotes
53
135
  # Here are some examples of strings that would be matched:
@@ -55,7 +137,45 @@ module Package
55
137
  # - lodash@^4.17.15, lodash@^4.17.20:
56
138
  # - "@adobe/css-tools@^4.0.1":
57
139
  # - "@babel/runtime@^7.23.1", "@babel/runtime@^7.9.2":
58
- /(?:^|[ "])#{Regexp.escape(dep_name)}@#{Regexp.escape(version)}.*?:.*?(\n\n|\z)/m
140
+ # For resolutions (exact versions):
141
+ # - "@apollo/client@3.12.5":
142
+ # For both regular dependencies and resolutions
143
+ # The package might appear in different formats:
144
+ # 1. As a dependency spec: "@apollo/client@^3.14.0"
145
+ # 2. As a resolved version: "@apollo/client@3.12.5"
146
+ # 3. As part of a multi-version spec: "@apollo/client@^3.14.0, @apollo/client@^3.12.5"
147
+ # 4. With npm prefix: "@apollo/client@npm:3.12.5"
148
+ # 5. In resolution field: "resolution: \"@apollo/client@npm:3.12.5\""
149
+ escaped_name = Regexp.escape(dep_name)
150
+ # Look for any entry that starts with our package name and includes the version
151
+ # We match the entire block and let fetch_package_version handle version extraction
152
+ # The pattern matches:
153
+ # 1. Package name at start of line or after quote
154
+ # 2. Everything up to the next double newline or end of file
155
+ # 3. Handles both compact and expanded formats with dependencies
156
+ # Match both old and new yarn.lock formats:
157
+ # Old: pkg@^1.0.0:
158
+ # New: "pkg@^1.0.0":
159
+ # The pattern matches the entire block including any indented lines
160
+ # We look for:
161
+ # 1. Start of line
162
+ # 2. Optional quote
163
+ # 3. Package name
164
+ # 4. @ symbol
165
+ # 5. Version spec (anything up to : or ")
166
+ # 6. Optional quote and colon
167
+ # 7. Rest of the block until next entry or end of file
168
+ # The pattern needs to match:
169
+ # 1. Basic format: pkg@^1.0.0:
170
+ # 2. Quoted format: "pkg@^1.0.0":
171
+ # 3. Multiple specs: "pkg@1.0.0", "pkg@npm:1.0.0":
172
+ # 4. Scoped packages: "@scope/pkg@1.0.0":
173
+ # Match any of:
174
+ # 1. Basic: pkg@^1.0.0:
175
+ # 2. Quoted: "pkg@^1.0.0":
176
+ # 3. Multiple: "pkg@1.0.0", "pkg@npm:1.0.0":
177
+ # 4. Scoped: "@scope/pkg@1.0.0":
178
+ /^(?:["']?#{escaped_name}@[^,\n:"]+(?:,\s*["']#{escaped_name}@[^,\n:"]+)*["']?:.*?)(?=\n["']|\n\s*\n|\z)/m
59
179
  end
60
180
  end
61
181
  end
@@ -1,4 +1,5 @@
1
1
  require_relative '../models/package'
2
+ require 'openssl'
2
3
 
3
4
  module Package
4
5
  module Audit
@@ -170,15 +171,24 @@ module Package
170
171
  }
171
172
  end
172
173
 
173
- def fetch_gem_version_dates(gem_name)
174
+ def fetch_gem_version_dates(gem_name) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
174
175
  uri = build_api_uri(gem_name)
175
176
  response = make_http_request(uri)
176
177
 
177
178
  return nil unless success_response?(response)
178
179
 
179
180
  parse_version_dates(response.body)
181
+ rescue Net::OpenTimeout, Net::ReadTimeout => e
182
+ log_api_error(gem_name, "Network timeout: #{e.message}") if debug_mode?
183
+ nil
184
+ rescue OpenSSL::SSL::SSLError => e
185
+ log_api_error(gem_name, "SSL verification failed: #{e.message}") if debug_mode?
186
+ nil
187
+ rescue SocketError, Errno::ECONNREFUSED => e
188
+ log_api_error(gem_name, "Network error: #{e.message}") if debug_mode?
189
+ nil
180
190
  rescue StandardError => e
181
- log_api_error(gem_name, e) if debug_mode?
191
+ log_api_error(gem_name, e.message) if debug_mode?
182
192
  nil
183
193
  end
184
194
 
@@ -206,6 +216,9 @@ module Package
206
216
  def create_http_client(uri)
207
217
  Net::HTTP.new(uri.host, uri.port).tap do |http|
208
218
  http.use_ssl = true
219
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
220
+ http.cert_store = OpenSSL::X509::Store.new
221
+ http.cert_store.set_default_paths
209
222
  http.read_timeout = HTTP_READ_TIMEOUT
210
223
  http.open_timeout = HTTP_OPEN_TIMEOUT
211
224
  end
@@ -1,5 +1,5 @@
1
1
  module Package
2
2
  module Audit
3
- VERSION = '0.6.2'
3
+ VERSION = '0.7.1'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: package-audit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vadim Kononov