contrast-agent 6.15.2 → 7.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/cs__assess_fiber_track/cs__assess_fiber_track.c +1 -1
- data/ext/cs__assess_fiber_track/cs__assess_fiber_track.h +1 -1
- data/ext/cs__assess_module/cs__assess_module.c +0 -19
- data/ext/cs__assess_test/cs__assess_tests.c +1 -1
- data/ext/cs__common/cs__common.c +17 -18
- data/ext/cs__common/cs__common.h +7 -11
- data/ext/cs__contrast_patch/cs__contrast_patch.c +16 -24
- data/ext/extconf_common.rb +79 -0
- data/lib/contrast/agent/assess/policy/source_method.rb +1 -0
- data/lib/contrast/agent/reporting/reporting_events/route_coverage.rb +2 -2
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +2 -1
- data/lib/contrast/agent/request/request_context.rb +2 -0
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/components/api.rb +1 -1
- data/lib/contrast/components/assess_rules.rb +1 -1
- data/lib/contrast/components/sampling.rb +1 -1
- data/lib/contrast/framework/sinatra/support.rb +22 -38
- data/lib/contrast/utils/hash_digest.rb +7 -6
- data/lib/contrast/utils/middleware_utils.rb +4 -4
- data/lib/contrast/utils/object_share.rb +3 -3
- data/lib/contrast.rb +0 -16
- data/ruby-agent.gemspec +4 -8
- metadata +26 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc98145df7f08bc47cbff0f0416a7b43852b8075c6806bd38fbbe0aa27d94adb
|
4
|
+
data.tar.gz: 60885ba415f59b893a5da6101ddc3b9d6deeac5a9d41bb2eb7c459291873b08f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a6449786512d444818087fed5d880c061b1108b8e9fbe64e4fd0f3657bac3b53ffb60806a7767a50a9c7a910b5e62e223d6af84be51d8ca9b6e4e5b5ae67d07
|
7
|
+
data.tar.gz: 4f2cb9c1435fbe5fdfbccbc3cc69ba3823de97f617bcff63493087a70a0551852dbe09f7699089cd22dfc509e57c39525420290813cd12ac92ee91164e2910bc
|
@@ -62,7 +62,7 @@ VALUE rb_fiber_yield_hook(int argc, const VALUE *argv) {
|
|
62
62
|
return rb_fiber_yield_original(argc, argv);
|
63
63
|
}
|
64
64
|
|
65
|
-
int install_fiber_hooks() {
|
65
|
+
int install_fiber_hooks(void) {
|
66
66
|
rb_fiber_new_original = rb_fiber_new;
|
67
67
|
patch_via_funchook(&rb_fiber_new_original, &rb_fiber_new_hook);
|
68
68
|
|
@@ -115,23 +115,4 @@ void Init_cs__assess_module(void) {
|
|
115
115
|
|
116
116
|
contrast_register_patch("Module", "module_eval",
|
117
117
|
contrast_assess_module_module_eval);
|
118
|
-
/*
|
119
|
-
* We patch these for better ancestors handling, and only for older ruby
|
120
|
-
* versions.
|
121
|
-
*/
|
122
|
-
// if (rb_ver_below_three()) {
|
123
|
-
/*
|
124
|
-
* `included` is a private method. We should make it public, patch it,
|
125
|
-
* and make our new method public
|
126
|
-
*/
|
127
|
-
// contrast_register_patch("Module", "included",
|
128
|
-
// contrast_assess_module_included);
|
129
|
-
/*
|
130
|
-
* The `prepend` patch may actually be the issue, if we're not properly
|
131
|
-
* passing along the call/context. It could be that my attempt to fix
|
132
|
-
* `included` left this section unreachable.
|
133
|
-
*/
|
134
|
-
// contrast_register_patch("Module", "prepend",
|
135
|
-
// contrast_assess_module_prepend);
|
136
|
-
// }
|
137
118
|
}
|
data/ext/cs__common/cs__common.c
CHANGED
@@ -28,8 +28,12 @@ void patch_via_funchook(void *original_function, void *hook_function) {
|
|
28
28
|
|
29
29
|
void *funchook_lib_handle;
|
30
30
|
void *funchook_reference, *(*funchook_create)(void);
|
31
|
+
/* This variables are used to load the funchook dylib */
|
32
|
+
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
33
|
+
#pragma GCC diagnostic push
|
31
34
|
int prepareResult, (*funchook_prepare)(void *, void **, void *);
|
32
35
|
int installResult, (*funchook_install)(void *, int);
|
36
|
+
#pragma GCC diagnostic pop
|
33
37
|
|
34
38
|
funchook_lib_handle =
|
35
39
|
dlopen(StringValueCStr(funchook_path), RTLD_NOW | RTLD_GLOBAL);
|
@@ -55,7 +59,7 @@ void contrast_alias_method(const VALUE target, const char *to,
|
|
55
59
|
ID2SYM(rb_intern(to)), ID2SYM(rb_intern(from)));
|
56
60
|
}
|
57
61
|
|
58
|
-
VALUE contrast_patcher() {
|
62
|
+
VALUE contrast_patcher(void) {
|
59
63
|
return patcher;
|
60
64
|
}
|
61
65
|
|
@@ -102,7 +106,7 @@ VALUE contrast_check_and_register_instance_patch(const char *module_name,
|
|
102
106
|
VALUE(c_fn)(const int, VALUE *,
|
103
107
|
const VALUE)) {
|
104
108
|
|
105
|
-
VALUE object, method, is_prepended
|
109
|
+
VALUE object, method, is_prepended;
|
106
110
|
/* check if method is prepended */
|
107
111
|
object = rb_const_get(rb_cObject, rb_intern(module_name));
|
108
112
|
method = ID2SYM(rb_intern(method_name));
|
@@ -119,7 +123,7 @@ VALUE contrast_check_and_register_instance_patch(const char *module_name,
|
|
119
123
|
}
|
120
124
|
}
|
121
125
|
|
122
|
-
|
126
|
+
VALUE
|
123
127
|
_contrast_register_patch(const char *module_name, const char *method_name,
|
124
128
|
VALUE(c_fn)(const int, VALUE *, const VALUE),
|
125
129
|
patch_impl patch) {
|
@@ -175,13 +179,6 @@ _contrast_register_patch(const char *module_name, const char *method_name,
|
|
175
179
|
return SYM2ID(underlying_method_name);
|
176
180
|
}
|
177
181
|
|
178
|
-
int rb_ver_below_three() {
|
179
|
-
int ruby_version =
|
180
|
-
FIX2INT(rb_funcall(rb_const_get(rb_cObject, rb_intern("RUBY_VERSION")),
|
181
|
-
rb_intern("to_i"), 0));
|
182
|
-
return ruby_version < 3;
|
183
|
-
}
|
184
|
-
|
185
182
|
/* used for direct check on object: String.cs__prepended? *args */
|
186
183
|
extern VALUE contrast_check_prepended(VALUE self, VALUE method_name,
|
187
184
|
VALUE is_instance) {
|
@@ -200,17 +197,18 @@ extern VALUE contrast_lookout_prepended(VALUE self, VALUE object_name,
|
|
200
197
|
return result;
|
201
198
|
}
|
202
199
|
|
203
|
-
|
200
|
+
VALUE _contrast_check_prepended(VALUE object, VALUE method_name,
|
204
201
|
VALUE is_instance) {
|
205
|
-
VALUE entry, ancestors,
|
202
|
+
VALUE entry, ancestors, entry_methods;
|
206
203
|
VALUE result = Qfalse;
|
207
|
-
|
208
|
-
|
204
|
+
VALUE object_idx = Qnil;
|
205
|
+
long y;
|
206
|
+
unsigned long i;
|
209
207
|
|
210
208
|
/* get self ancestors */
|
211
209
|
ancestors = rb_mod_ancestors(object);
|
212
210
|
/* get the size of the array */
|
213
|
-
|
211
|
+
unsigned long length = RARRAY_LEN(ancestors);
|
214
212
|
/* Locate self in ancestors: */
|
215
213
|
for (i = 0; i < length; ++i) {
|
216
214
|
entry = rb_ary_entry(ancestors, i);
|
@@ -226,14 +224,14 @@ static VALUE _contrast_check_prepended(VALUE object, VALUE method_name,
|
|
226
224
|
for (i = 0; i < object_idx; ++i) {
|
227
225
|
entry = rb_ary_entry(ancestors, i);
|
228
226
|
if (is_instance == Qtrue) {
|
229
|
-
entry_methods = rb_class_instance_methods(
|
227
|
+
entry_methods = rb_class_instance_methods(1UL, &entry, entry);
|
230
228
|
} else {
|
231
|
-
entry_methods = rb_obj_singleton_methods(
|
229
|
+
entry_methods = rb_obj_singleton_methods(1UL, &entry, entry);
|
232
230
|
}
|
233
231
|
|
234
232
|
/* Loop through the instance/singleton methods of the prepended modules
|
235
233
|
*/
|
236
|
-
|
234
|
+
long entry_methods_length = RARRAY_LEN(entry_methods);
|
237
235
|
for (y = 0; y <= entry_methods_length; ++y) {
|
238
236
|
if (rb_ary_entry(entry_methods, y) == method_name) {
|
239
237
|
result = Qtrue;
|
@@ -244,6 +242,7 @@ static VALUE _contrast_check_prepended(VALUE object, VALUE method_name,
|
|
244
242
|
break;
|
245
243
|
}
|
246
244
|
}
|
245
|
+
|
247
246
|
return result;
|
248
247
|
}
|
249
248
|
|
data/ext/cs__common/cs__common.h
CHANGED
@@ -10,6 +10,9 @@ typedef enum {
|
|
10
10
|
IMPL_PREPEND_SINGLETON,
|
11
11
|
} patch_impl;
|
12
12
|
|
13
|
+
/* the unused variable warning is triggered for gcc only */
|
14
|
+
#pragma GCC diagnostic ignored "-Wunused-variable"
|
15
|
+
#pragma GCC diagnostic push
|
13
16
|
static VALUE cs__send_method;
|
14
17
|
static VALUE cs__alias_method_sym;
|
15
18
|
|
@@ -34,14 +37,7 @@ static VALUE rb_sym_alias_instance;
|
|
34
37
|
static VALUE rb_sym_alias_singleton;
|
35
38
|
static VALUE rb_sym_prepend_instance;
|
36
39
|
static VALUE rb_sym_prepend_singleton;
|
37
|
-
|
38
|
-
/*
|
39
|
-
* Check if ruby version is < 3.0.0.
|
40
|
-
* We are using this for handling ancestors of included modules.
|
41
|
-
* Since this is fixed after Ruby 3.0.0 we should remove this after
|
42
|
-
* dropping support for older versions, as no longer needed.
|
43
|
-
*/
|
44
|
-
int rb_ver_below_three();
|
40
|
+
#pragma GCC diagnostic pop
|
45
41
|
|
46
42
|
void patch_via_funchook(void *original_function, void *hook_function);
|
47
43
|
|
@@ -73,11 +69,11 @@ VALUE contrast_register_prepend_patch(const char *module_name,
|
|
73
69
|
VALUE(c_fn)(const int, VALUE *,
|
74
70
|
const VALUE));
|
75
71
|
|
76
|
-
|
72
|
+
VALUE _contrast_register_patch(const char *module_name, const char *method_name,
|
77
73
|
VALUE(c_fn)(const int, VALUE *, const VALUE),
|
78
74
|
patch_impl patch_impl);
|
79
75
|
|
80
|
-
|
76
|
+
VALUE _contrast_check_prepended(VALUE self, VALUE method_name, VALUE is_instance);
|
81
77
|
|
82
78
|
extern VALUE contrast_check_prepended(VALUE self, VALUE method_name, VALUE is_instance);
|
83
79
|
|
@@ -90,7 +86,7 @@ VALUE contrast_check_and_register_instance_patch(const char *module_name,
|
|
90
86
|
VALUE(c_fn)(const int, VALUE *,
|
91
87
|
const VALUE));
|
92
88
|
|
93
|
-
VALUE contrast_patcher();
|
89
|
+
VALUE contrast_patcher(void);
|
94
90
|
|
95
91
|
void Init_cs__common(void);
|
96
92
|
|
@@ -97,8 +97,6 @@ VALUE rescue_func(VALUE arg1) {
|
|
97
97
|
*/
|
98
98
|
exception = rb_errinfo();
|
99
99
|
rb_exc_raise(exception);
|
100
|
-
|
101
|
-
return Qnil;
|
102
100
|
}
|
103
101
|
|
104
102
|
/**
|
@@ -109,17 +107,18 @@ VALUE rescue_func(VALUE arg1) {
|
|
109
107
|
*
|
110
108
|
**/
|
111
109
|
VALUE contrast_patch_call_ensure(const VALUE *args) {
|
112
|
-
|
110
|
+
/* we do not need to ensure that post patch is called if no error was thrown */
|
113
111
|
if (!RTEST(rb_errinfo())) {
|
114
112
|
return Qnil;
|
115
113
|
}
|
116
114
|
|
117
115
|
int argc;
|
118
|
-
VALUE object, preshift, method_policy
|
116
|
+
VALUE object, preshift, method_policy;
|
119
117
|
VALUE *argv;
|
118
|
+
/* VALUE method; */
|
120
119
|
|
121
120
|
object = args[0];
|
122
|
-
method = args[1];
|
121
|
+
/* method = args[1]; */
|
123
122
|
argc = NUM2INT(args[2]);
|
124
123
|
argv = (VALUE *)args[3];
|
125
124
|
method_policy = args[4];
|
@@ -137,8 +136,8 @@ VALUE ensure_wrapper(const VALUE *args) {
|
|
137
136
|
original_args = (VALUE)args[1];
|
138
137
|
ensure_args = (VALUE)args[2];
|
139
138
|
|
140
|
-
|
141
|
-
|
139
|
+
/* this ensure if being treated as a rescue due to issues surrounding
|
140
|
+
Kernel#throw */
|
142
141
|
return rb_ensure(original_method, original_args, contrast_patch_call_ensure,
|
143
142
|
(VALUE)ensure_args);
|
144
143
|
}
|
@@ -154,7 +153,7 @@ VALUE contrast_call_super(const VALUE *args) {
|
|
154
153
|
|
155
154
|
VALUE contrast_run_patches(const VALUE *wrapped_args) {
|
156
155
|
VALUE impl, method, method_policy, object, original_args, original_ret,
|
157
|
-
preshift
|
156
|
+
preshift;
|
158
157
|
int argc;
|
159
158
|
VALUE *argv;
|
160
159
|
VALUE ensure_args[6];
|
@@ -257,9 +256,15 @@ VALUE contrast_ensure_function(const VALUE method_policy) {
|
|
257
256
|
|
258
257
|
VALUE contrast_patch_dispatch(const int argc, const VALUE *argv,
|
259
258
|
const patch_impl impl, const VALUE object) {
|
259
|
+
/*
|
260
|
+
* Silence the known variable unused warning detected by compiler.
|
261
|
+
* Since this Variable is set by cases and we check if it is set or not.
|
262
|
+
* To disalbe this remove the -Wno-maybe-uninitialized flag.
|
263
|
+
*/
|
264
|
+
|
260
265
|
VALUE cs__method, known, method, method_policy;
|
261
266
|
VALUE original_args[4];
|
262
|
-
|
267
|
+
long do_contrast, nested_scope;
|
263
268
|
|
264
269
|
/* Do Contrast analysis, unless our subsequent checks tell us no. */
|
265
270
|
do_contrast = 1;
|
@@ -369,6 +374,8 @@ call_original:
|
|
369
374
|
case IMPL_PREPEND_SINGLETON:
|
370
375
|
return contrast_call_super(original_args);
|
371
376
|
};
|
377
|
+
|
378
|
+
return Qfalse;
|
372
379
|
}
|
373
380
|
|
374
381
|
VALUE contrast_alias_instance_patch(const int argc, const VALUE *argv,
|
@@ -490,21 +497,6 @@ VALUE contrast_patch_prepend(const VALUE self, const VALUE originalModule,
|
|
490
497
|
}
|
491
498
|
rb_prepend_module(originalModule, module);
|
492
499
|
|
493
|
-
if (rb_ver_below_three()) {
|
494
|
-
VALUE module_at;
|
495
|
-
VALUE rb_incl_in_mod_ary =
|
496
|
-
rb_funcall(originalModule, rb_intern("included_in"), 0);
|
497
|
-
if (RB_TYPE_P(rb_incl_in_mod_ary, T_ARRAY)) {
|
498
|
-
int i = 0;
|
499
|
-
int size = RARRAY_LEN(rb_incl_in_mod_ary);
|
500
|
-
for (i = 0; i < size; ++i) {
|
501
|
-
module_at = rb_ary_entry(rb_incl_in_mod_ary, i);
|
502
|
-
if (RB_TYPE_P(module_at, T_MODULE)) {
|
503
|
-
rb_include_module(module_at, module);
|
504
|
-
}
|
505
|
-
}
|
506
|
-
}
|
507
|
-
}
|
508
500
|
return Qtrue;
|
509
501
|
}
|
510
502
|
|
data/ext/extconf_common.rb
CHANGED
@@ -2,18 +2,97 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require 'mkmf'
|
5
|
+
require 'rbconfig'
|
5
6
|
require_relative '../lib/contrast/agent/version'
|
6
7
|
|
8
|
+
# The mkmf.rb file uses all passed flags from Ruby configuration (RbConfig::CONFIG) on
|
9
|
+
# Ruby build time. Problem with Clang and GCC is that it do not keep up with c89 and finds
|
10
|
+
# error on including <ryby.h> as not allowing inline variables.
|
11
|
+
#
|
12
|
+
# Ruby inlining is a C99 feature that is allowed to be used, because the Ruby configure script
|
13
|
+
# can work around the absence of the inline feature with a simple #define:
|
14
|
+
#
|
15
|
+
# ifndef __cplusplus
|
16
|
+
# define inline
|
17
|
+
# endif
|
18
|
+
#
|
19
|
+
# There is difference between using c89 and gnu89, as the latter is extended version of the
|
20
|
+
# 1989 standard allowing features like // comments for example. This makes the use of the
|
21
|
+
# gnu not favorable since it will skip some checks and would make wholes in the c89 standard
|
22
|
+
# support.
|
23
|
+
#
|
24
|
+
# We can directly append the CFLAGS we need with ENV variable used to create the makefile.
|
25
|
+
# MAKEFILE_CONFIG is extension of the RbConfig::CONFIG used to build the Ruby itself.
|
26
|
+
# So if we try to run c89 on clang it will brake because of detecting errors from external
|
27
|
+
# library used - Ruby itself build with different standard as it seems. This means the
|
28
|
+
# Ruby must be compiled beforehand with the compiler forced to C89.
|
29
|
+
#
|
30
|
+
# This makes the C dialect of choice to be gnu89 with strict pedantic warnings reported as errors,
|
31
|
+
# and making the compiler configurable by flags:
|
32
|
+
STANDARD_FLAGS = '-std=gnu89'
|
33
|
+
CLANG = 'clang'
|
34
|
+
|
35
|
+
# TODO: RUBY-999999 Add -pedantic flag, remove all warning flags and see to it that as many as possible become obsolete.
|
36
|
+
# Note: Adding -pedantic could raise <ruby.h> warnings, and we are not in control of that code.
|
37
|
+
# e.g. error: '_Bool' is a C99 extension [-Werror,-Wc99-extensions] ; empty macros and etc.
|
38
|
+
#
|
39
|
+
# -Wno-int-conversion => Passing VALUEs as function args but required as unsigned long parameters.
|
40
|
+
# -Werror => report all warnings as errors
|
41
|
+
# -Wshorten-64-to-32 => is recognized by clang but not in gcc.
|
42
|
+
# Use alternative if viable. [Wno-narrowing]
|
43
|
+
# -Wno-maybe-uninitialized is used by clang but not gcc
|
44
|
+
#
|
45
|
+
# Note: Clang supports old style function definition e.g. void func () {}
|
46
|
+
# but the gcc is not.
|
47
|
+
# make sure to add parameters type => void func (void) {}.
|
48
|
+
# All Changes must be tested against both clang and gcc.
|
49
|
+
WARNING_FLAGS = %w[
|
50
|
+
-Wno-language-extension-token -Wno-incompatible-function-pointer-types
|
51
|
+
-Wno-declaration-after-statement -Wno-variadic-macros -Wno-int-conversion
|
52
|
+
-Wno-incompatible-pointer-types -Wno-narrowing
|
53
|
+
].freeze # rubocop:disable Security/Object/Freeze
|
54
|
+
|
55
|
+
# Flags that are only recognized by gcc:
|
56
|
+
GCC_FLAGS = %w[-Wno-maybe-uninitialized].freeze # rubocop:disable Security/Object/Freeze
|
57
|
+
|
58
|
+
# Extend $CFLAGS passed directly to compiler in ruby mkmf
|
59
|
+
def extend_cflags
|
60
|
+
$CFLAGS += " #{ [STANDARD_FLAGS, WARNING_FLAGS].flatten.join(' ') }"
|
61
|
+
# Extend with GCC specific flags:
|
62
|
+
unless RbConfig::MAKEFILE_CONFIG['CC'].downcase.include?(CLANG) ||
|
63
|
+
RbConfig::MAKEFILE_CONFIG['CPP'].downcase.include?(CLANG) ||
|
64
|
+
RbConfig::CONFIG['CC'].downcase.include?(CLANG)
|
65
|
+
|
66
|
+
$CFLAGS += " #{ GCC_FLAGS.flatten.join(' ') }"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
7
70
|
def make!
|
8
71
|
create_makefile("#{ $TO_MAKE }/#{ $TO_MAKE }")
|
9
72
|
end
|
10
73
|
|
74
|
+
# -----------------------------------------------------------------------
|
75
|
+
# | MOVING CODE BELLOW THIS SECTION MAY BRAKE MAKEFILE. ORDER MATTERS! |
|
76
|
+
# ----------------------------------------------------------------------
|
77
|
+
|
11
78
|
def ext_path
|
12
79
|
# __dir__ is relative to the file you're reading.
|
13
80
|
# this file you're reading is presently within $APP_ROOT/ext/.
|
14
81
|
__dir__
|
15
82
|
end
|
16
83
|
|
84
|
+
# We need to first build funchook which relies on ext_path method. This enables the require of
|
85
|
+
# funchook.h file. Then we can pass CFLAGS and extend makefile flags and invoke make!
|
17
86
|
require_relative './build_funchook'
|
18
87
|
|
88
|
+
# Extended flags are mainly tested with clang and gcc. Experience with other compilers may vary.
|
89
|
+
# To that end if something brakes on client side we must have a mechanism to go back to previous
|
90
|
+
# non strict gnu89 standard and be able to maintain the build.
|
91
|
+
# We can disable newly added changes with this setting CONTRAST_USE_C89=false.
|
92
|
+
extend_cflags unless ENV['CONTRAST__USE_GNU89'] == 'false'
|
93
|
+
|
94
|
+
# use same C compiler if set.
|
95
|
+
RbConfig::CONFIG['CC'] = RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
|
96
|
+
|
97
|
+
# Generate Makefile.
|
19
98
|
make!
|
@@ -33,8 +33,8 @@ module Contrast
|
|
33
33
|
# Parse the given controller and route from a Rack based application framework in order to create an instance
|
34
34
|
# of this class
|
35
35
|
#
|
36
|
-
# @param final_controller [Grape::API
|
37
|
-
# entrypoint of the route actively being executed
|
36
|
+
# @param final_controller [Class<Grape::API>, Class<Sinatra::Base>] the controller responsible for the
|
37
|
+
# definition of the entrypoint of the route actively being executed
|
38
38
|
# @param method [String] the HTTP request method of the route actively being executed
|
39
39
|
# @param route_pattern [Grape::Router::Route, Mustermann::Sinatra] the pattern to which the url maps
|
40
40
|
# @param url [String] the literal url of the route actively being executed
|
@@ -32,7 +32,8 @@ module Contrast
|
|
32
32
|
FORBIDDEN_NO_ACTION_MSG = 'Report access was forbidden because the supplied credentials failed ' \
|
33
33
|
'to authenticate the Agent'
|
34
34
|
UNPROCESSABLE_ENTITY_MSG = 'Reporter received Unprocessable Entity response. Disabling permanently.'
|
35
|
-
RETRY_AFTER_MSG =
|
35
|
+
RETRY_AFTER_MSG = 'There are too many requests of this type being sent by this Agent. ' \
|
36
|
+
"#{ SUSPEND_MSG }".cs__freeze
|
36
37
|
|
37
38
|
def last_response_code
|
38
39
|
@_last_response_code ||= ''
|
@@ -135,6 +135,8 @@ module Contrast
|
|
135
135
|
@observed_route = Contrast::Agent::Reporting::ObservedRoute.new
|
136
136
|
reporting_route = Contrast::Agent.framework_manager.get_route_information(@request)
|
137
137
|
append_to_observed_route(reporting_route)
|
138
|
+
rescue StandardError => e
|
139
|
+
logger.error('Unable to determine current route', e)
|
138
140
|
end
|
139
141
|
end
|
140
142
|
end
|
@@ -18,7 +18,7 @@ module Contrast
|
|
18
18
|
include Contrast::Config::BaseConfiguration
|
19
19
|
|
20
20
|
CANON_NAME = 'api'
|
21
|
-
PROXY_NAME = "#{ CANON_NAME }.proxy"
|
21
|
+
PROXY_NAME = "#{ CANON_NAME }.proxy".cs__freeze
|
22
22
|
CONFIG_VALUES = %w[api_key user_name service_key url].cs__freeze
|
23
23
|
|
24
24
|
# @return [String]
|
@@ -16,7 +16,7 @@ module Contrast
|
|
16
16
|
|
17
17
|
SPEC_KEY = :disabled_rules.cs__freeze
|
18
18
|
CANON_NAME = 'assess.rules'
|
19
|
-
NAME_PREFIX = "#{ CONTRAST }.#{ CANON_NAME }"
|
19
|
+
NAME_PREFIX = "#{ CONTRAST }.#{ CANON_NAME }".cs__freeze
|
20
20
|
|
21
21
|
# @return [Array, nil] list of disabled assess rules
|
22
22
|
attr_accessor :disabled_rules
|
@@ -103,7 +103,7 @@ module Contrast
|
|
103
103
|
include Contrast::Config::BaseConfiguration
|
104
104
|
|
105
105
|
CANON_NAME = 'assess.sampling'
|
106
|
-
NAME_PREFIX = "#{ CONTRAST }.#{ CANON_NAME }"
|
106
|
+
NAME_PREFIX = "#{ CONTRAST }.#{ CANON_NAME }".cs__freeze
|
107
107
|
CONFIG_VALUES = %w[enable baseline request_frequency response_frequency window_ms].cs__freeze
|
108
108
|
|
109
109
|
# @return [Integer, nil]
|
@@ -67,30 +67,39 @@ module Contrast
|
|
67
67
|
# Given the current request - return a RouteCoverage object
|
68
68
|
|
69
69
|
# @param request [Contrast::Agent::Request] a contrast tracked request.
|
70
|
-
# @param
|
70
|
+
# @param _controller [::Sinatra::Base] optionally use this controller instead of global ::Sinatra::Base.
|
71
71
|
# @return [Contrast::Agent::Reporting::RouteCoverage, nil] a Dtm describing the route
|
72
72
|
# matched to the request if a match was found.
|
73
|
-
def current_route_coverage request,
|
74
|
-
return unless sinatra_controller?(controller)
|
75
|
-
|
73
|
+
def current_route_coverage request, _controller = ::Sinatra::Base, full_route = nil
|
76
74
|
method = request.env[::Rack::REQUEST_METHOD] # GET, PUT, POST, etc...
|
77
|
-
|
75
|
+
route = _cleaned_route(request)
|
78
76
|
# Find route match--checking superclasses if necessary.
|
79
|
-
|
80
|
-
|
77
|
+
sinatra_controllers.each do |potential_controller|
|
78
|
+
next unless sinatra_controller?(potential_controller)
|
79
|
+
|
80
|
+
next if potential_controller.nil? || potential_controller.cs__class == NilClass
|
81
81
|
|
82
|
-
|
82
|
+
route_patterns = potential_controller.routes.fetch(method) { [] }.
|
83
|
+
map(&:first)
|
84
|
+
route_pattern = route_patterns.find do |matcher|
|
85
|
+
matcher.params(route) # ::Mustermann::Sinatra match.
|
86
|
+
end
|
87
|
+
next unless route_pattern
|
83
88
|
|
84
|
-
|
85
|
-
|
86
|
-
|
89
|
+
full_route ||= request.env[::Rack::PATH_INFO]
|
90
|
+
new_route_coverage = Contrast::Agent::Reporting::RouteCoverage.new
|
91
|
+
new_route_coverage.attach_rack_based_data(potential_controller, method, route_pattern, full_route)
|
92
|
+
return new_route_coverage
|
93
|
+
end
|
94
|
+
nil
|
87
95
|
end
|
88
96
|
|
89
97
|
# Search object space for sinatra controllers--any class that subclasses ::Sinatra::Base.
|
90
98
|
#
|
91
|
-
# @return [Array<::Sinatra::Base
|
99
|
+
# @return [Array<Class<::Sinatra::Base>>] sinatra controlelrs
|
92
100
|
def sinatra_controllers
|
93
|
-
|
101
|
+
@_sinatra_controllers ||=
|
102
|
+
[::Sinatra::Base] + ObjectSpace.each_object(Class).select { |clazz| sinatra_controller?(clazz) }
|
94
103
|
end
|
95
104
|
|
96
105
|
def retrieve_request env
|
@@ -112,31 +121,6 @@ module Contrast
|
|
112
121
|
|
113
122
|
private
|
114
123
|
|
115
|
-
# Given a controller and a route to match against, find the route_pattern and class that will serve the
|
116
|
-
# route. This is recursive as Sinatra's routing is recursive from subclass to super.
|
117
|
-
#
|
118
|
-
# @param controller [Sinatra::Base, #routes] a Sinatra application.
|
119
|
-
# @param method [::Rack::REQUEST_METHOD] GET, POST, PUT, etc...
|
120
|
-
# @param route [String] the relative route passed from Rack.
|
121
|
-
# @return [Array[Sinatra::Base, Mustermann::Sinatra], nil] Either the controller that
|
122
|
-
# will handle the route along with the route pattern or nil if no match.
|
123
|
-
def _route_recurse controller, method, route
|
124
|
-
return if controller.nil? || controller.cs__class == NilClass
|
125
|
-
|
126
|
-
route_patterns = controller.routes.fetch(method) { [] }.
|
127
|
-
map(&:first)
|
128
|
-
route_pattern = route_patterns&.find do |matcher|
|
129
|
-
matcher.params(route) # ::Mustermann::Sinatra match.
|
130
|
-
end
|
131
|
-
|
132
|
-
return controller, route_pattern if route_pattern
|
133
|
-
|
134
|
-
# Check routes defined in superclass if present.
|
135
|
-
return unless controller.superclass&.instance_variable_get(:@routes)
|
136
|
-
|
137
|
-
_route_recurse(controller.superclass, method, route)
|
138
|
-
end
|
139
|
-
|
140
124
|
# Get route and do some cleanup matching that of Sinatra::Base#process_route.
|
141
125
|
#
|
142
126
|
# @param request [Contrast::Agent::Request] a contrast tracked request.
|
@@ -44,14 +44,15 @@ module Contrast
|
|
44
44
|
update(route.signature)
|
45
45
|
if (observation = route.observations[0])
|
46
46
|
update(observation.verb)
|
47
|
+
else
|
48
|
+
update(request.request_method)
|
47
49
|
end
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
return unless request ||= context&.request
|
50
|
+
else
|
51
|
+
return unless request ||= context&.request
|
52
52
|
|
53
|
-
|
54
|
-
|
53
|
+
update(request.normalized_uri) # the normalized URL used to access the method in the route.
|
54
|
+
update(request.request_method)
|
55
|
+
end
|
55
56
|
end
|
56
57
|
|
57
58
|
# Update to CRC checksum the event source name and source type.
|
@@ -11,12 +11,12 @@ module Contrast
|
|
11
11
|
module MiddlewareUtils
|
12
12
|
private
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
LANGUAGE_DEPRECATION_YEAR = '2023'
|
14
|
+
LANGUAGE_DEPRECATION_VERSION = '3.0'
|
15
|
+
LANGUAGE_DEPRECATION_YEAR = '2024'
|
17
16
|
LANGUAGE_DEPRECATION_WARNING =
|
18
17
|
"[Contrast Security] [DEPRECATION] Support for Ruby #{ LANGUAGE_DEPRECATION_VERSION } will be removed in " \
|
19
|
-
"April #{ LANGUAGE_DEPRECATION_YEAR }. Please contact Customer Support prior if you require continued
|
18
|
+
"April #{ LANGUAGE_DEPRECATION_YEAR }. Please contact Customer Support prior if you require continued" \
|
19
|
+
'support.'.cs__freeze
|
20
20
|
|
21
21
|
def setup_agent
|
22
22
|
# Generate new config file if one is not already created:
|
@@ -55,9 +55,9 @@ module Contrast
|
|
55
55
|
EMPTY_HASH = {}.freeze
|
56
56
|
|
57
57
|
# RegExps
|
58
|
-
DIGIT_REGEXP = /[[:digit:]]
|
59
|
-
WHITE_SPACE_REGEXP = /\s
|
60
|
-
NOT_WHITE_SPACE_REGEXP = /[^\s]
|
58
|
+
DIGIT_REGEXP = /[[:digit:]]/
|
59
|
+
WHITE_SPACE_REGEXP = /\s/
|
60
|
+
NOT_WHITE_SPACE_REGEXP = /[^\s]/
|
61
61
|
|
62
62
|
# Messages
|
63
63
|
OVERRIDE_MESSAGE = 'A security filter prevented original response from being returned.'
|
data/lib/contrast.rb
CHANGED
@@ -102,19 +102,3 @@ if RUBY_VERSION >= '3.0.0' && RUBY_VERSION < '3.1.0'
|
|
102
102
|
Class.alias_method(:prepend, :cs__orig_prepend)
|
103
103
|
Class.remove_method(:cs__orig_prepend)
|
104
104
|
end
|
105
|
-
|
106
|
-
if RUBY_VERSION < '3.0.0'
|
107
|
-
# Better handles ancestors for older ruby versions.
|
108
|
-
# This is called from C, tread lightly.
|
109
|
-
class Module
|
110
|
-
@_included_in = []
|
111
|
-
# Returns array with modules including this instance
|
112
|
-
def included_in
|
113
|
-
@_included_in ||= [] unless cs__frozen?
|
114
|
-
end
|
115
|
-
|
116
|
-
def self.included_in
|
117
|
-
@_included_in ||= [] unless cs__frozen?
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
data/ruby-agent.gemspec
CHANGED
@@ -51,7 +51,7 @@ end
|
|
51
51
|
def self.add_frameworks spec
|
52
52
|
spec.add_development_dependency 'grape', '~> 1.5', '>= 1.5.2'
|
53
53
|
spec.add_development_dependency 'rack-protection', '>= 2'
|
54
|
-
spec.add_development_dependency 'rails', '~> 7'
|
54
|
+
spec.add_development_dependency 'rails', '>= 6', '~> 7'
|
55
55
|
spec.add_development_dependency 'sinatra', '>= 2'
|
56
56
|
end
|
57
57
|
|
@@ -80,7 +80,7 @@ def self.add_specs spec
|
|
80
80
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
81
81
|
spec.add_development_dependency 'rspec-benchmark'
|
82
82
|
spec.add_development_dependency 'rspec_junit_formatter', '0.3.0'
|
83
|
-
spec.add_development_dependency 'rspec-rails', '
|
83
|
+
spec.add_development_dependency 'rspec-rails', '6.0'
|
84
84
|
spec.add_development_dependency 'tzinfo-data' # Alpine rspec-rails requirement.
|
85
85
|
spec.add_development_dependency 'warning'
|
86
86
|
spec.add_development_dependency 'typhoeus', '~> 1.4'
|
@@ -102,11 +102,7 @@ end
|
|
102
102
|
|
103
103
|
# Dependencies not mocked out during RSpec that we test real code of, beyond just frameworks.
|
104
104
|
def self.add_tested_gems spec
|
105
|
-
|
106
|
-
spec.add_development_dependency 'async', '~> 1.30.3'
|
107
|
-
else
|
108
|
-
spec.add_development_dependency 'async'
|
109
|
-
end
|
105
|
+
spec.add_development_dependency 'async'
|
110
106
|
spec.add_development_dependency 'execjs'
|
111
107
|
spec.add_development_dependency 'rhino'
|
112
108
|
spec.add_development_dependency 'sqlite3'
|
@@ -181,7 +177,7 @@ Gem::Specification.new do |spec|
|
|
181
177
|
'Testing and Protection.'
|
182
178
|
spec.homepage = 'https://www.contrastsecurity.com'
|
183
179
|
spec.license = 'CONTRAST SECURITY (see license file)'
|
184
|
-
spec.required_ruby_version = ['>=
|
180
|
+
spec.required_ruby_version = ['>= 3.0.0', '< 3.3.0']
|
185
181
|
|
186
182
|
spec.bindir = 'exe'
|
187
183
|
# Keep cs__common first, it handles funchook.h right now.
|
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:
|
4
|
+
version: 7.0.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-
|
16
|
+
date: 2023-04-03 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: bundler
|
@@ -277,6 +277,9 @@ dependencies:
|
|
277
277
|
name: rails
|
278
278
|
requirement: !ruby/object:Gem::Requirement
|
279
279
|
requirements:
|
280
|
+
- - ">="
|
281
|
+
- !ruby/object:Gem::Version
|
282
|
+
version: '6'
|
280
283
|
- - "~>"
|
281
284
|
- !ruby/object:Gem::Version
|
282
285
|
version: '7'
|
@@ -284,6 +287,9 @@ dependencies:
|
|
284
287
|
prerelease: false
|
285
288
|
version_requirements: !ruby/object:Gem::Requirement
|
286
289
|
requirements:
|
290
|
+
- - ">="
|
291
|
+
- !ruby/object:Gem::Version
|
292
|
+
version: '6'
|
287
293
|
- - "~>"
|
288
294
|
- !ruby/object:Gem::Version
|
289
295
|
version: '7'
|
@@ -305,16 +311,16 @@ dependencies:
|
|
305
311
|
name: async
|
306
312
|
requirement: !ruby/object:Gem::Requirement
|
307
313
|
requirements:
|
308
|
-
- - "
|
314
|
+
- - ">="
|
309
315
|
- !ruby/object:Gem::Version
|
310
|
-
version:
|
316
|
+
version: '0'
|
311
317
|
type: :development
|
312
318
|
prerelease: false
|
313
319
|
version_requirements: !ruby/object:Gem::Requirement
|
314
320
|
requirements:
|
315
|
-
- - "
|
321
|
+
- - ">="
|
316
322
|
- !ruby/object:Gem::Version
|
317
|
-
version:
|
323
|
+
version: '0'
|
318
324
|
- !ruby/object:Gem::Dependency
|
319
325
|
name: execjs
|
320
326
|
requirement: !ruby/object:Gem::Requirement
|
@@ -531,14 +537,14 @@ dependencies:
|
|
531
537
|
requirements:
|
532
538
|
- - '='
|
533
539
|
- !ruby/object:Gem::Version
|
534
|
-
version: '
|
540
|
+
version: '6.0'
|
535
541
|
type: :development
|
536
542
|
prerelease: false
|
537
543
|
version_requirements: !ruby/object:Gem::Requirement
|
538
544
|
requirements:
|
539
545
|
- - '='
|
540
546
|
- !ruby/object:Gem::Version
|
541
|
-
version: '
|
547
|
+
version: '6.0'
|
542
548
|
- !ruby/object:Gem::Dependency
|
543
549
|
name: tzinfo-data
|
544
550
|
requirement: !ruby/object:Gem::Requirement
|
@@ -678,22 +684,22 @@ email:
|
|
678
684
|
executables: []
|
679
685
|
extensions:
|
680
686
|
- ext/cs__common/extconf.rb
|
681
|
-
- ext/cs__assess_marshal_module/extconf.rb
|
682
|
-
- ext/cs__assess_yield_track/extconf.rb
|
683
|
-
- ext/cs__scope/extconf.rb
|
684
|
-
- ext/cs__assess_kernel/extconf.rb
|
685
687
|
- ext/cs__assess_array/extconf.rb
|
686
|
-
- ext/
|
687
|
-
- ext/
|
688
|
+
- ext/cs__assess_basic_object/extconf.rb
|
689
|
+
- ext/cs__assess_fiber_track/extconf.rb
|
688
690
|
- ext/cs__assess_hash/extconf.rb
|
689
|
-
- ext/
|
691
|
+
- ext/cs__assess_kernel/extconf.rb
|
692
|
+
- ext/cs__assess_marshal_module/extconf.rb
|
690
693
|
- ext/cs__assess_module/extconf.rb
|
694
|
+
- ext/cs__assess_regexp/extconf.rb
|
695
|
+
- ext/cs__assess_string/extconf.rb
|
691
696
|
- ext/cs__assess_string_interpolation/extconf.rb
|
692
|
-
- ext/cs__tests/extconf.rb
|
693
697
|
- ext/cs__assess_test/extconf.rb
|
694
|
-
- ext/
|
695
|
-
- ext/cs__assess_basic_object/extconf.rb
|
698
|
+
- ext/cs__assess_yield_track/extconf.rb
|
696
699
|
- ext/cs__contrast_patch/extconf.rb
|
700
|
+
- ext/cs__os_information/extconf.rb
|
701
|
+
- ext/cs__scope/extconf.rb
|
702
|
+
- ext/cs__tests/extconf.rb
|
697
703
|
extra_rdoc_files: []
|
698
704
|
files:
|
699
705
|
- ".clang-format"
|
@@ -1342,7 +1348,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
1342
1348
|
requirements:
|
1343
1349
|
- - ">="
|
1344
1350
|
- !ruby/object:Gem::Version
|
1345
|
-
version:
|
1351
|
+
version: 3.0.0
|
1346
1352
|
- - "<"
|
1347
1353
|
- !ruby/object:Gem::Version
|
1348
1354
|
version: 3.3.0
|
@@ -1352,7 +1358,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
1352
1358
|
- !ruby/object:Gem::Version
|
1353
1359
|
version: '0'
|
1354
1360
|
requirements: []
|
1355
|
-
rubygems_version: 3.
|
1361
|
+
rubygems_version: 3.2.33
|
1356
1362
|
signing_key:
|
1357
1363
|
specification_version: 4
|
1358
1364
|
summary: Contrast Security's agent for rack-based applications.
|