contrast-agent 6.12.0 → 6.14.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: 6772cdef949fd96dd24342c5f4a9a7b813a4d77873a9aa117c1a6750088a647f
4
- data.tar.gz: 8008b5a90911e19594a32a5dba27079d0f7f5e857e34b1cedb974a4e8422fb2d
3
+ metadata.gz: 577b0810f45b302615af1f151ebb6b772d76c0bccd460057022f5fbadf065d73
4
+ data.tar.gz: f3e882dd5e3d7e63e4cf09f37733acd02ad3b70b2d195b8a9377175cfe1b4330
5
5
  SHA512:
6
- metadata.gz: e70042ce2030918ecbafedfc2b254fd15ff9bc8316fecbd2901e0d8a6581e46505b039d5c21a932b595423565a36b16872362897bc344dc77d61ef8ac41ec8e8
7
- data.tar.gz: 3d8cf2341b2258470ec334be4b81efccbea5a27c26c49b5ca0106e3b44e29f6c878aee0c28dcb7b0c0a84887fb1f298978f0419522503ee8293e0053f9a63bc9
6
+ metadata.gz: 168ea3d43d19acbe29a80b9b244a91c29b0f7c091137b7a0575edd39f763ec013e1402bc1337c167e8147738428813b7d1010e92a8e102aa3b72570685d73605
7
+ data.tar.gz: ddbf43ffe314bfd53c19687dc7bfc549a1b5374a43ede461a73487519ef263672f6dc7fe449140159c5e26587a55052b132242c20b1673d2dbed3d882340f157
@@ -7,9 +7,13 @@ module Contrast
7
7
  module Policy
8
8
  module TriggerValidation
9
9
  # Validator used to assert a REDOS finding is actually vulnerable
10
- # before serializing that finding as a DTM to report to the TeamServer.
10
+ # before serializing that finding as a Event to report to the TeamServer.
11
11
  module REDOSValidator
12
12
  RULE_NAME = 'redos'
13
+ # If Regexp is set to Float::Infinite this is the maximum number it will receive
14
+ POSITIVE_INFINITY = 18_446_744_073.709553
15
+ # We are checking and for negative infinity (-1.0/0.0 )
16
+ NEGATIVE_INFINITY = -POSITIVE_INFINITY
13
17
 
14
18
  class << self
15
19
  def valid? _patcher, object, _ret, args
@@ -49,8 +53,42 @@ module Contrast
49
53
 
50
54
  # Use #match? because it doesn't fill out global variables
51
55
  # in the way match or =~ do.
56
+ #
57
+ # Since ruby 3.2.0 the Regexp now have a timeout option. we need to check and see if the timeout
58
+ # is set. If so we can assume that the regexp is safe.
59
+ # puts "SAFE #{regexp_timeout_safe?(regexp)}"
60
+ return false if regexp_timeout_safe?(regexp)
61
+
62
+ # report only if pattern is bad:
52
63
  VULNERABLE_PATTERN.match?(regexp.source)
53
64
  end
65
+
66
+ # Check and see if a regexp is with safely set Timeout or not.
67
+ #
68
+ # @param regexp [Regexp]
69
+ # @return [Boolean]
70
+ def regexp_timeout_safe? regexp
71
+ return false if RUBY_VERSION < '3.2.0'
72
+ # Global
73
+ return false if Regexp.timeout.nil? || regexp_infinite?(Regexp)
74
+
75
+ # Local
76
+ return false if regexp.cs__is_a?(Regexp) && !(regexp.timeout.nil? || regexp_infinite?(regexp))
77
+
78
+ true
79
+ end
80
+
81
+ private
82
+
83
+ # Check and see if the set timeout is set to infinity:
84
+ #
85
+ # @param regexp[Regexp] Instance or class
86
+ # @return[Boolean]
87
+ def regexp_infinite? regexp
88
+ return false unless regexp.timeout == POSITIVE_INFINITY || regexp.timeout == NEGATIVE_INFINITY
89
+
90
+ true
91
+ end
54
92
  end
55
93
  end
56
94
  end
@@ -3,6 +3,6 @@
3
3
 
4
4
  module Contrast
5
5
  module Agent
6
- VERSION = '6.12.0'
6
+ VERSION = '6.14.0'
7
7
  end
8
8
  end
@@ -0,0 +1,140 @@
1
+ # Copyright (c) 2023 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
+ # frozen_string_literal: true
3
+
4
+ require 'yaml'
5
+ require 'contrast/configuration'
6
+ require 'contrast/agent/reporting/reporter'
7
+ require 'base64'
8
+
9
+ module Contrast
10
+ module Config
11
+ # Helper module with methods to validate the existing yaml file.
12
+ module Validate
13
+ # rubocop:disable Rails/Output
14
+ SKIP_LOG = %w[service_key api_key].cs__freeze
15
+ REQUIRED = %i[url api_key service_key user_name].cs__freeze
16
+ PASS = " \u{2705} "
17
+ FAIL = " \u{274C} "
18
+ REQUIRED_HEADERS = %i[server_type server_name server_path app_language app_name].cs__freeze
19
+
20
+ def validate_file
21
+ puts("\u{1F9EA} Validating Agent Configuration...\n")
22
+ Contrast::Config.validate_config
23
+ puts('done...')
24
+ puts("Validating Contrast Reporter Headers...\n")
25
+ reporter = Contrast::Config.validate_headers
26
+ puts('done...')
27
+ puts("Testing Reporter Client Connection...\n")
28
+ Contrast::Config.test_connection(reporter) if reporter
29
+ puts('Validation complete')
30
+ end
31
+
32
+ def validate_config
33
+ config = Contrast::Configuration.new
34
+ abort("Unable to Build Config #{ FAIL }") unless config
35
+ missing = []
36
+
37
+ api_hash = config.api.to_contrast_hash
38
+
39
+ api_hash.each_key do |key|
40
+ value = mask_keys(api_hash, key)
41
+ if value.is_a?(Contrast::Config::ApiProxyConfiguration)
42
+ Contrast::Config.validate_proxy(value)
43
+ elsif value.is_a?(Contrast::Config::CertificationConfiguration)
44
+ Contrast::Config.validate_cert(value)
45
+ next
46
+ elsif value.is_a?(Contrast::Config::RequestAuditConfiguration)
47
+ Contrast::Config.validate_audit(value)
48
+ next
49
+ elsif value.nil? && REQUIRED.include?(key.to_sym)
50
+ missing << key
51
+ end
52
+ end
53
+ return if missing.empty?
54
+
55
+ abort("Validation failed: Missing required API configuration values: #{ missing.join(', ') } #{ FAIL }")
56
+ end
57
+
58
+ def validate_proxy config
59
+ puts(" Proxy Enabled: #{ config.enable }")
60
+ return unless config.enable
61
+
62
+ mark = config.url.nil? ? FAIL : PASS
63
+ puts(" Proxy URL: #{ config.url } #{ mark }")
64
+ abort('Proxy Enabled but no Proxy URL given') unless config.url
65
+ end
66
+
67
+ def validate_cert config
68
+ puts(" Certification Enabled: #{ config.enable }")
69
+ return unless config.enable
70
+
71
+ mark = config.ca_file.nil? ? FAIL : PASS
72
+ puts(" CA File: #{ config.ca_file } #{ mark }")
73
+ abort('CA file path not provided') unless config.ca_file
74
+ mark = config.cert_file.nil? ? FAIL : PASS
75
+ puts(" Cert File: #{ config.cert_file } #{ mark }")
76
+ abort('Cert file path not provided') unless config.cert_file
77
+ mark = config.key_file.nil? ? FAIL : PASS
78
+ puts(" Key File: #{ config.key_file } #{ mark }")
79
+ abort('Key file path not provided') unless config.key_file
80
+ end
81
+
82
+ def validate_audit config
83
+ puts(" Request Audit Enabled: #{ config.enable }")
84
+ return unless config.enable
85
+
86
+ config.cs__class::CONFIG_VALUES.each do |value_name|
87
+ puts(" #{ value_name }::#{ config.send(value_name.to_sym) }")
88
+ end
89
+ end
90
+
91
+ def init_reporter
92
+ Contrast::Agent::Reporter.new
93
+ end
94
+
95
+ def validate_headers
96
+ missing = []
97
+ reporter = init_reporter
98
+ reporter_headers = reporter.client.headers.to_contrast_hash
99
+ REQUIRED_HEADERS.each do |key|
100
+ value = decode_header(reporter_headers, key)
101
+ missing << key if value.nil?
102
+ end
103
+ unless missing.empty?
104
+ abort("Validation failed: Missing required header values: #{ missing.join(', ') } #{ FAIL }")
105
+ end
106
+ reporter
107
+ end
108
+
109
+ def test_connection reporter
110
+ puts(" Connection failed #{ FAIL }") unless reporter
111
+ connection = reporter.connection
112
+ abort("Failed to Initialize Connection please check error logs for details #{ FAIL } ") unless connection
113
+ abort('Failed to Start Client please check error logs for details') unless reporter.client.startup!(connection)
114
+ last_response = reporter.client.response_handler.last_response_code
115
+ if last_response.include?('40')
116
+ puts(" Last response code: #{ last_response } #{ FAIL }")
117
+ abort("Failed to Initialize Connection please check error logs for details #{ FAIL } ")
118
+ elsif connection
119
+ puts(" Last response code: #{ last_response } #{ PASS }")
120
+ puts(" Connection successful #{ PASS }") if connection
121
+ end
122
+ end
123
+
124
+ def mask_keys hash, key
125
+ value = hash[key]
126
+ redacted_value = Contrast::Configuration::REDACTED if SKIP_LOG.include?(key.to_s)
127
+ puts(" #{ key }::#{ redacted_value || value }") unless value.is_a?(Contrast::Config::BaseConfiguration)
128
+ value
129
+ end
130
+
131
+ def decode_header hash, key
132
+ value = hash[key]
133
+ decoded_header = Base64.strict_decode64(value)
134
+ puts(" #{ key }::#{ key == :app_language ? value : decoded_header }")
135
+ value
136
+ end
137
+ # rubocop:enable Rails/Output
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,129 @@
1
+ # Copyright (c) 2023 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
+ # frozen_string_literal: true
3
+
4
+ require 'fileutils'
5
+ require 'yaml'
6
+
7
+ module Contrast
8
+ module Config
9
+ # Helper module with methods to find active configuration file used by the agent or create it.\
10
+ # This file is used before the agent start so methods added here must not be dependent on Agent
11
+ # instrumentation.
12
+ module YamlFile
13
+ CONFIG_FILE_NAME = 'contrast_security'
14
+ EXT = { yml: 'yml', yaml: 'yaml' }.freeze # rubocop:disable Security/Object/Freeze
15
+
16
+ POSSIBLE_TARGET_PATHS = %w[
17
+ ./
18
+ ./config/
19
+ /etc/contrast/ruby/
20
+ /etc/contrast/
21
+ /etc/
22
+ ].freeze # rubocop:disable Security/Object/Freeze
23
+
24
+ HEADER = "# +-------------------------------------------------------------------------+\n" \
25
+ "# This Contrast Security configuration is Auto-generated by rake task.\n" \
26
+ "# To List all available rake task use 'rake -T'. \n" \
27
+ "#\n" \
28
+ "# Please enter valid api information, for the Ruby Agent to be able to\n" \
29
+ "# connect to Contrast UI. You can validate your config file by running: \n" \
30
+ "# 'bundle exec rake contrast:config:validate' \n" \
31
+ "#\n" \
32
+ "# To find your organization keys please follow this documentation:\n" \
33
+ "# https://docs.contrastsecurity.com/en/find-the-agent-keys.html\n" \
34
+ "# +-------------------------------------------------------------------------+\n"
35
+
36
+ FOOTER = "\n# For more information visit the full Ruby agent configuration guide:\n" \
37
+ '# https://docs.contrastsecurity.com/en/ruby-configuration.html'
38
+
39
+ COMMENT = "#agent:\n" \
40
+ "# logger:\n" \
41
+ "# level: WARN\n" \
42
+ "# path: contrast_agent.log\n" \
43
+ "#server:\n" \
44
+ "# name: Server name\n" \
45
+ "#application:\n" \
46
+ "# name: Application name\n" \
47
+ "# code: Application name\n" \
48
+ "# group: Application group\n" \
49
+ "# session_metadata: Application metadata used for creation of Session ID\n" \
50
+ "# version: Application version\n"
51
+
52
+ DEFAULT_CONFIG = {
53
+ 'api' => {
54
+ 'url' => 'https://app.contrastsecurity.com',
55
+ 'api_key' => 'contrast_user',
56
+ 'service_key' => 'demo',
57
+ 'user_name' => 'demo'
58
+ }
59
+ }.freeze # rubocop:disable Security/Object/Freeze
60
+
61
+ class << self
62
+ # Checks all accessible by the agent path for active configuration created.
63
+ #
64
+ # @return [Boolean]
65
+ def created?
66
+ return true if File.exist?(Contrast::Config::YamlFile.target_path)
67
+ return true unless find!.empty?
68
+
69
+ false
70
+ end
71
+
72
+ # Finds active configuration used.
73
+ #
74
+ # @return [String] path of the config file.
75
+ def find!
76
+ found = ''
77
+ paths = POSSIBLE_TARGET_PATHS.dup
78
+ paths << ENV['CONTRAST_CONFIG_PATH'] if ENV['CONTRAST_CONFIG_PATH']
79
+ paths.each do |path|
80
+ EXT.each_value do |extension|
81
+ effective_config = "#{ path }#{ file_name }.#{ extension }"
82
+ found = effective_config if File.exist?(effective_config)
83
+ end
84
+ end
85
+ found
86
+ end
87
+
88
+ # Create new config file to the default destination.
89
+ #
90
+ def create
91
+ # rubocop:disable Rails/Output
92
+ puts("\u{1F48E} Generating: Contrast Configuration file.")
93
+ if Contrast::Config::YamlFile.created?
94
+ puts("\u{2705} Configuration file already exists: #{ Contrast::Config::YamlFile.find! }")
95
+ else
96
+ File.open(Contrast::Config::YamlFile.target_path, 'w') do |file|
97
+ file.write(HEADER)
98
+ file.write(YAML.dump(DEFAULT_CONFIG).gsub('---', ' '))
99
+ file.write(COMMENT)
100
+ file.write(FOOTER)
101
+ file.close
102
+ end
103
+
104
+ puts("\u{2728} Created! path #{ Contrast::Config::YamlFile.target_path }\n")
105
+ puts("\nOpen the file and enter your Contrast Security api keys or set them via environment variables.\n")
106
+ puts('Visit our documentation for more details: ' \
107
+ 'https://docs.contrastsecurity.com/en/ruby-configuration.html')
108
+ end
109
+ rescue StandardError => e
110
+ puts("\u{2757} WARNING configuration could not be created due to error: '#{ e }'. " \
111
+ "Try created in manually by running 'bundle exec rake contrast:config:create'.")
112
+ # rubocop:enable Rails/Output
113
+ end
114
+
115
+ def target_path
116
+ File.join(execution_directory, "#{ file_name }.#{ EXT[:yml] }")
117
+ end
118
+
119
+ def execution_directory
120
+ Dir.pwd
121
+ end
122
+
123
+ def file_name
124
+ ENV['CONTRAST_YAML_FILE_TEST_CREATE_CONFIG_FILE_NAME_VALUE'] || CONFIG_FILE_NAME
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
@@ -1,47 +1,22 @@
1
1
  # Copyright (c) 2023 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'yaml'
5
- require 'contrast/configuration'
6
- require 'contrast/agent/reporting/reporter'
4
+ require 'contrast/config/yaml_file'
5
+ require 'contrast/config/validate'
7
6
 
8
7
  module Contrast
9
8
  # A Rake task to generate a contrast_security.yaml file with some basic settings
10
9
  module Config
11
10
  extend Rake::DSL
12
- DEFAULT_CONFIG = {
13
- 'api' => {
14
- 'url' => 'Enter your Contrast URL ex: https://app.contrastsecurity.com/Contrast',
15
- 'api_key' => 'Enter your Contrast api key',
16
- 'service_key' => 'Enter your Contrast service key',
17
- 'user_name' => 'Enter your Contrast user name'
18
- },
19
- 'agent' => {
20
- 'logger' => {
21
- 'level' => 'ERROR',
22
- 'path' => 'contrast_agent.log'
23
- }
24
- }
25
- }.cs__freeze
26
-
27
- SKIP_LOG = %w[service_key api_key].cs__freeze
28
- REQUIRED = %i[url api_key service_key user_name].cs__freeze
11
+ # The file create methods are required in the gemspec. Some of the Agent functions are not
12
+ # available there. To be safe the validate mechanics are extracted in different module.
13
+ extend Contrast::Config::Validate
29
14
 
30
15
  namespace :contrast do
31
16
  namespace :config do
32
17
  desc 'Create a contrast_security.yaml in the applications root directory'
33
18
  task :create do
34
- execution_directory = Dir.pwd
35
- target_path = File.join(execution_directory, 'contrast_security.yaml')
36
- if File.exist?(target_path)
37
- puts 'WARNING: contrast_security.yaml already exists'
38
- else
39
- File.write(target_path, YAML.dump(DEFAULT_CONFIG))
40
-
41
- puts "Created contrast_security.yaml at #{ target_path }"
42
- puts 'Open the file and enter your Contrast Security api keys or set them via environment variables'
43
- puts 'Visit our documentation site for more details: https://docs.contrastsecurity.com/installation-rubyconfig.html'
44
- end
19
+ Contrast::Config::YamlFile.create
45
20
  end
46
21
  end
47
22
  end
@@ -50,94 +25,8 @@ module Contrast
50
25
  namespace :config do
51
26
  desc 'Validate the provided Contrast configuration and confirm connectivity'
52
27
  task validate: :environment do
53
- puts 'Validating Agent Configuration...'
54
- Contrast::Config.validate_config
55
- puts '...done!'
56
- puts 'Validating Contrast Reporter Headers...'
57
- reporter = Contrast::Config.validate_headers
58
- puts '...done!'
59
- puts 'Testing Reporter Client Connection...'
60
- Contrast::Config.test_connection(reporter) if reporter
61
- puts '...done!'
62
- end
63
- end
64
-
65
- def self.validate_config
66
- config = Contrast::Configuration.new
67
- abort('Unable to Build Config') unless config
68
- missing = []
69
-
70
- api_hash = config.api.to_contrast_hash
71
-
72
- api_hash.each_key do |key|
73
- value = mask_keys(api_hash, key)
74
- if value.is_a?(Contrast::Config::ApiProxyConfiguration)
75
- Contrast::Config.validate_proxy(value)
76
- elsif value.is_a?(Contrast::Config::CertificationConfiguration)
77
- Contrast::Config.validate_cert(value)
78
- next
79
- elsif value.is_a?(Contrast::Config::RequestAuditConfiguration)
80
- Contrast::Config.validate_audit(value)
81
- next
82
- elsif value.nil? && REQUIRED.includes?(key.to_sym)
83
- missing << key
84
- end
85
- end
86
- abort("Missing required API configuration values: #{ missing.join(', ') }") unless missing.empty?
87
- end
88
-
89
- def self.validate_proxy config
90
- puts("Proxy Enabled: #{ config.enable }")
91
- return unless config.enable
92
-
93
- puts("Proxy URL: #{ config.url }")
94
- abort('Proxy Enabled but no Proxy URL given') unless config.url
95
- end
96
-
97
- def self.validate_cert config
98
- puts("Certification Enabled: #{ config.enable }")
99
- return unless config.enable
100
-
101
- puts("CA File: #{ config.ca_file }")
102
- abort('CA file path not provided') unless config.ca_file
103
- puts("Cert File: #{ config.cert_file }")
104
- abort('Cert file path not provided') unless config.cert_file
105
- puts("Key File: #{ config.key_file }")
106
- abort('Key file path not provided') unless config.key_file
107
- end
108
-
109
- def self.validate_audit config
110
- puts("Request Audit Enabled: #{ config.enable }")
111
- return unless config.enable
112
-
113
- config.each do |k, v|
114
- puts("#{ k }::#{ v }")
115
- end
116
- end
117
-
118
- def self.validate_headers
119
- missing = []
120
- reporter = Contrast::Agent::Reporter.new
121
- reporter_headers = reporter.client.headers.to_contrast_hash
122
- reporter_headers.each_key do |key|
123
- value = mask_keys(reporter_headers, key)
124
- missing << key if value.nil?
28
+ validate_file
125
29
  end
126
- abort("Missing required header values: #{ missing.join(', ') }") unless missing.empty?
127
- reporter
128
- end
129
-
130
- def self.test_connection reporter
131
- connection = reporter.connection
132
- abort('Failed to Initialize Connection please check error logs for details') unless connection
133
- abort('Failed to Start Client please check error logs for details') unless reporter.client.startup!(connection)
134
- end
135
-
136
- def self.mask_keys hash, key
137
- value = hash[key]
138
- redacted_value = Contrast::Configuration::REDACTED if SKIP_LOG.include?(key.to_s)
139
- puts("#{ key }::#{ redacted_value || value }") unless value.is_a?(Contrast::Config::BaseConfiguration)
140
- value
141
30
  end
142
31
  end
143
32
  end
@@ -1,6 +1,8 @@
1
1
  # Copyright (c) 2023 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
+ require 'contrast/config/yaml_file'
5
+
4
6
  module Contrast
5
7
  module Utils
6
8
  # helper methods for Contrast::Agent::Middleware
@@ -16,6 +18,8 @@ module Contrast
16
18
  "April #{ LANGUAGE_DEPRECATION_YEAR }. Please contact Customer Support prior if you require continued support."
17
19
 
18
20
  def setup_agent
21
+ # Generate new config file if one is not already created:
22
+ Contrast::Config::YamlFile.create unless Contrast::Config::YamlFile.created?
19
23
  ::Contrast::SETTINGS.reset_state
20
24
 
21
25
  inform_deprecations
@@ -932,6 +932,22 @@
932
932
  "source":"O",
933
933
  "target":"R",
934
934
  "action":"SPLAT"
935
+ }, {
936
+ "class_name":"IO",
937
+ "method_name":"to_path",
938
+ "instance_method": true,
939
+ "method_visibility": "public",
940
+ "source":"O",
941
+ "target":"R",
942
+ "action":"SPLAT"
943
+ }, {
944
+ "class_name":"IO",
945
+ "method_name":"path",
946
+ "instance_method": true,
947
+ "method_visibility": "public",
948
+ "source":"O",
949
+ "target":"R",
950
+ "action":"SPLAT"
935
951
  }, {
936
952
  "class_name": "ActiveModel::AttributeAssignment",
937
953
  "method_name": "assign_attributes",
@@ -1177,6 +1193,16 @@
1177
1193
  "action": "BUFFER",
1178
1194
  "patch_method": "buffer_keep_splat"
1179
1195
  },
1196
+ {
1197
+ "class_name": "IO::Buffer",
1198
+ "instance_method": true,
1199
+ "method_visibility": "public",
1200
+ "method_name": "read",
1201
+ "source":"P0,O",
1202
+ "target":"O",
1203
+ "action": "BUFFER",
1204
+ "patch_method": "buffer_keep_splat"
1205
+ },
1180
1206
  {
1181
1207
  "class_name": "ERB",
1182
1208
  "method_name": "result",
data/ruby-agent.gemspec CHANGED
@@ -2,6 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require_relative './lib/contrast/agent/version'
5
+ require_relative './lib/contrast/config/yaml_file'
5
6
 
6
7
  lib = File.expand_path('lib', __dir__)
7
8
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
@@ -178,14 +179,14 @@ Gem::Specification.new do |spec|
178
179
  'Testing and Protection.'
179
180
  spec.homepage = 'https://www.contrastsecurity.com'
180
181
  spec.license = 'CONTRAST SECURITY (see license file)'
181
- spec.required_ruby_version = ['>= 2.7.0', '< 3.2.0']
182
+ spec.required_ruby_version = ['>= 2.7.0', '< 3.3.0']
182
183
 
183
184
  spec.bindir = 'exe'
184
185
  # Keep cs__common first, it handles funchook.h right now.
185
186
  spec.extensions = Dir['ext/cs__common/extconf.rb', 'ext/**/extconf.rb']
186
187
  spec.require_paths = ['lib']
187
188
 
188
- unless File.exist?(File.join(Dir.pwd, 'contrast_security.yaml'))
189
+ unless Contrast::Config::YamlFile.created?
189
190
  spec.post_install_message = 'To generate the required contrast_security.yaml file you can run: '\
190
191
  'bundle exec rake contrast:config:create'
191
192
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: contrast-agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.12.0
4
+ version: 6.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - galen.palmer@contrastsecurity.com
@@ -13,7 +13,7 @@ authors:
13
13
  autorequire:
14
14
  bindir: exe
15
15
  cert_chain: []
16
- date: 2023-01-10 00:00:00.000000000 Z
16
+ date: 2023-01-26 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: bundler
@@ -684,22 +684,22 @@ email:
684
684
  executables: []
685
685
  extensions:
686
686
  - ext/cs__common/extconf.rb
687
- - ext/cs__assess_module/extconf.rb
688
- - ext/cs__scope/extconf.rb
689
- - ext/cs__assess_string_interpolation/extconf.rb
690
- - ext/cs__assess_kernel/extconf.rb
691
687
  - ext/cs__assess_basic_object/extconf.rb
692
- - ext/cs__assess_test/extconf.rb
693
- - ext/cs__assess_yield_track/extconf.rb
694
688
  - ext/cs__assess_hash/extconf.rb
689
+ - ext/cs__assess_kernel/extconf.rb
690
+ - ext/cs__assess_string_interpolation/extconf.rb
691
+ - ext/cs__contrast_patch/extconf.rb
695
692
  - ext/cs__assess_string/extconf.rb
693
+ - ext/cs__assess_regexp/extconf.rb
696
694
  - ext/cs__tests/extconf.rb
695
+ - ext/cs__assess_module/extconf.rb
696
+ - ext/cs__assess_yield_track/extconf.rb
697
697
  - ext/cs__assess_fiber_track/extconf.rb
698
- - ext/cs__contrast_patch/extconf.rb
699
- - ext/cs__assess_array/extconf.rb
698
+ - ext/cs__scope/extconf.rb
699
+ - ext/cs__assess_test/extconf.rb
700
700
  - ext/cs__os_information/extconf.rb
701
701
  - ext/cs__assess_marshal_module/extconf.rb
702
- - ext/cs__assess_regexp/extconf.rb
702
+ - ext/cs__assess_array/extconf.rb
703
703
  extra_rdoc_files: []
704
704
  files:
705
705
  - ".clang-format"
@@ -1234,6 +1234,8 @@ files:
1234
1234
  - lib/contrast/config/protect_rules_configuration.rb
1235
1235
  - lib/contrast/config/request_audit_configuration.rb
1236
1236
  - lib/contrast/config/server_configuration.rb
1237
+ - lib/contrast/config/validate.rb
1238
+ - lib/contrast/config/yaml_file.rb
1237
1239
  - lib/contrast/configuration.rb
1238
1240
  - lib/contrast/extension/assess.rb
1239
1241
  - lib/contrast/extension/assess/array.rb
@@ -1337,8 +1339,7 @@ metadata:
1337
1339
  support_uri: https://support.contrastsecurity.com
1338
1340
  trouble_shooting_uri: https://support.contrastsecurity.com/hc/en-us/search?utf8=%E2%9C%93&query=Ruby
1339
1341
  wiki_uri: https://docs.contrastsecurity.com/
1340
- post_install_message: 'To generate the required contrast_security.yaml file you can
1341
- run: bundle exec rake contrast:config:create'
1342
+ post_install_message:
1342
1343
  rdoc_options: []
1343
1344
  require_paths:
1344
1345
  - lib
@@ -1349,7 +1350,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
1349
1350
  version: 2.7.0
1350
1351
  - - "<"
1351
1352
  - !ruby/object:Gem::Version
1352
- version: 3.2.0
1353
+ version: 3.3.0
1353
1354
  required_rubygems_version: !ruby/object:Gem::Requirement
1354
1355
  requirements:
1355
1356
  - - ">="