tcell_agent 2.5.1 → 2.5.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 521fa2c98be5ea73aa4a9f4a8c00b9c1e51e2dd801de3c886324e28c95205142
4
- data.tar.gz: a257258e3e3a4f71ee52d2242a3e37ec56c103da6aaae7ed471b87ef3b5ae054
3
+ metadata.gz: 729643a91b2542ef11a78966c493fadd8a15f6dd7ddc99a5764e9f993904c78e
4
+ data.tar.gz: 47cb2b434ec142362510f0494c441caa73c34dde4f56afdee470685f92825ac6
5
5
  SHA512:
6
- metadata.gz: '0349621e1d4393d435561bb72dcb8928746caffb6f57828f4ea429d93546ef550be81ce7d15fad344775b9c4af18b17cff6339c800c51bcc573c025bcb2e4f49'
7
- data.tar.gz: 4c7b9c61a59d6b7023fd2e54b8262a8ea1efed04600a36ccd5d92be85eb2240a1832178197dfa40ccef35ecddc886ee34d25ec674ba926c909461c7164b5b11d
6
+ metadata.gz: a72a5cbe005619fe1932b39798d4d2b63937e2b2a71a2ff80d15186f157c8a11978b61f84bbae6bf9778aa028aba3766addc4c0571a0ec0216d53b29a96adc9e
7
+ data.tar.gz: 0f40534a487aa4b1f5576795ea2904449b5dc531cdbd56720f8f62a8c0866b32b7d12d0e04e9c9fa40cab4860eceafe02e7047149ec39bdab8c5465831edc77a
@@ -33,14 +33,13 @@ module TCellAgent
33
33
  response
34
34
  end
35
35
 
36
- def self.get_handler_and_context(request, response_headers)
36
+ def self.get_handler_and_context(request)
37
37
  dlp_handler = nil
38
38
  tcell_context = nil
39
39
 
40
40
  TCellAgent::Instrumentation.safe_block('DLP Handler get handler and context') do
41
41
  if TCellAgent.configuration.should_instrument? &&
42
- TCellAgent.configuration.should_intercept_requests? &&
43
- TCellAgent::Utils::Rails.processable_response?(response_headers)
42
+ TCellAgent.configuration.should_intercept_requests?
44
43
 
45
44
  # do all this work so that dlp doesn't run at all unless it's on and there
46
45
  # are rules to run
@@ -5,6 +5,21 @@ module TCellAgent
5
5
  module Rails
6
6
  module JSAgent
7
7
  HEAD_SEARCH_REGEX = Regexp.new('(<head>|<head( |\n).*?>)', Regexp::IGNORECASE)
8
+ def self.insert_js_agent?(response_headers)
9
+ content_disposition = response_headers['Content-Disposition']
10
+ is_attachment = content_disposition && content_disposition =~ /^attachment/i
11
+
12
+ content_type = response_headers['Content-Type']
13
+ applicable_content_type = content_type &&
14
+ content_type.start_with?('text/html')
15
+
16
+ content_encoding = response_headers['Content-Encoding']
17
+ compressed_content_encoding = content_encoding &&
18
+ (content_encoding =~ /(br|gzip)/i)
19
+
20
+ !is_attachment && applicable_content_type && !compressed_content_encoding
21
+ end
22
+
8
23
  def self.insert_now(js_agent_handler, script_insert, rack_body, content_length)
9
24
  TCellAgent::Instrumentation.safe_block('Handling JSAgent Insert Now') do
10
25
  if js_agent_handler
@@ -43,7 +58,7 @@ module TCellAgent
43
58
  script_insert = nil
44
59
 
45
60
  TCellAgent::Instrumentation.safe_block('JSAgent get handler and script insert') do
46
- return [nil, nil] unless (response_headers['Content-Type'] || '').start_with?('text/html')
61
+ return [nil, nil] unless insert_js_agent?(response_headers)
47
62
 
48
63
  js_agent_policy = TCellAgent.policy(TCellAgent::PolicyTypes::JSAGENTINJECTION)
49
64
  script_insert = js_agent_policy.get_js_agent_script_tag(
@@ -1,7 +1,6 @@
1
1
  require 'tcell_agent/instrumentation'
2
2
  require 'tcell_agent/rails/responses'
3
3
  require 'tcell_agent/rails/js_agent_insert'
4
- require 'tcell_agent/rails/dlp_handler'
5
4
  require 'tcell_agent/rails/tcell_body_proxy'
6
5
 
7
6
  module TCellAgent
@@ -22,7 +21,7 @@ module TCellAgent
22
21
  TCellAgent::Instrumentation.safe_block('Handling Request') do
23
22
  tcell_response = response
24
23
  unless request.env[TCellAgent::Instrumentation::TCELL_ID].patches_blocking_triggered
25
- tcell_response = _handle_appsensor_js_agent_and_dlp(request, tcell_response)
24
+ tcell_response = _handle_appsensor_js_agent(request, tcell_response)
26
25
  end
27
26
  tcell_response = _handle_redirect(request, tcell_response)
28
27
  tcell_response = _set_headers(request, tcell_response)
@@ -77,14 +76,12 @@ module TCellAgent
77
76
  response
78
77
  end
79
78
 
80
- def _handle_appsensor_js_agent_and_dlp(request, response)
79
+ def _handle_appsensor_js_agent(request, response)
81
80
  TCellAgent::Instrumentation.safe_block('Handling AppSensor, JS Agent, and DLP') do
82
81
  status_code, response_headers, response_body = response
83
82
 
84
83
  js_agent_handler, script_insert =
85
84
  TCellAgent::Instrumentation::Rails::JSAgent.get_handler_and_script_insert(request, response_headers)
86
- dlp_handler, tcell_context =
87
- TCellAgent::Instrumentation::Rails::DLPHandler.get_handler_and_context(request, response_headers)
88
85
 
89
86
  content_length = 0
90
87
  defer_appfw_due_to_streaming = false
@@ -97,29 +94,21 @@ module TCellAgent
97
94
 
98
95
  # when content length is present it can be inferred that the
99
96
  # response is not a streaming response, so js agent insertion
100
- # and dlp reports and redactions can be done up front
97
+ # can be done up front
101
98
  response_body, content_length =
102
99
  TCellAgent::Instrumentation::Rails::JSAgent.insert_now(js_agent_handler,
103
100
  script_insert,
104
101
  response_body,
105
102
  content_length)
106
103
 
107
- response_body, content_length =
108
- TCellAgent::Instrumentation::Rails::DLPHandler.report_and_redact_now(dlp_handler,
109
- tcell_context,
110
- response_body,
111
- content_length)
112
-
113
104
  response_headers['Content-Length'] = content_length.to_s
114
105
 
115
106
  elsif response_body.is_a?(Rack::BodyProxy)
116
107
  response_body = TCellAgent::Instrumentation::Rails::TCellBodyProxy.new(
117
108
  response_body,
118
- TCellAgent::Utils::Rails.processable_response?(response_headers),
119
109
  js_agent_handler,
120
110
  script_insert,
121
- dlp_handler,
122
- tcell_context
111
+ response_headers
123
112
  )
124
113
  defer_appfw_due_to_streaming = true
125
114
  end
@@ -7,18 +7,6 @@ module TCellAgent
7
7
  STATUSES_MISSING_CONTENT_LENGTH.include?(status_code.to_i) ||
8
8
  (headers['Content-Length'] && headers['Content-Length'].to_i.zero?)
9
9
  end
10
-
11
- def self.processable_response?(response_headers)
12
- content_disposition = response_headers['Content-Disposition']
13
- is_attachment = content_disposition && content_disposition =~ /^attachment/i
14
-
15
- content_type = response_headers['Content-Type']
16
- applicable_content_type = content_type &&
17
- (content_type =~ %r{application/json}i ||
18
- content_type =~ %r{application/xml}i ||
19
- content_type =~ /^text/i)
20
- !is_attachment && applicable_content_type
21
- end
22
10
  end
23
11
  end
24
12
  end
@@ -4,27 +4,17 @@ module TCellAgent
4
4
  module Instrumentation
5
5
  module Rails
6
6
  class TCellBodyProxy
7
- attr_accessor :meta_data
8
-
9
- # for specs
10
- attr_accessor :content_length
7
+ attr_accessor :content_length, :meta_data
11
8
 
12
9
  def initialize(body,
13
- process_js_and_dlp,
14
10
  js_agent_insertion_proc,
15
11
  script_insert,
16
- dlp_cleaner_proc,
17
- tcell_context)
12
+ response_headers)
18
13
  @content_length = 0
19
14
  @body = body
20
-
21
- @process_js_and_dlp = process_js_and_dlp
22
-
23
15
  @js_agent_insertion_proc = js_agent_insertion_proc
24
16
  @script_insert = script_insert
25
-
26
- @dlp_cleaner_proc = dlp_cleaner_proc
27
- @tcell_context = tcell_context
17
+ @response_headers = response_headers
28
18
  end
29
19
 
30
20
  def close
@@ -58,35 +48,34 @@ module TCellAgent
58
48
  end
59
49
 
60
50
  def process_body(body)
51
+ new_body = body
61
52
  TCellAgent::Instrumentation.safe_block('Processing tcell body proxy body') do
62
53
  chunked_response_match = nil
63
- if body.class.name == 'String' && body =~ /^([[:xdigit:]]+)(;.+)?\r\n/
54
+
55
+ if @response_headers['Transfer-Encoding'] == 'chunked' &&
56
+ body.class.name == 'String' &&
57
+ body =~ /^([[:xdigit:]]+)(;.+)?\r\n/
64
58
  chunked_response_match = Regexp.last_match(1)
65
59
  @content_length += chunked_response_match.to_i(16)
66
60
  end
67
61
 
68
- new_body = body
69
62
  if body.class.name == 'ActionView::OutputBuffer' ||
70
63
  (body.class.name == 'String' && !chunked_response_match)
71
- if @process_js_and_dlp
72
- if @js_agent_insertion_proc
73
- new_body = @js_agent_insertion_proc.call(@script_insert, body)
74
- if new_body != body
75
- # js agent was successfully inserted so no need to keep
76
- # calling this proc
77
- @js_agent_insertion_proc = nil
78
- end
79
- end
80
- if @dlp_cleaner_proc
81
- @dlp_cleaner_proc.call(@tcell_context, new_body)
64
+ if @js_agent_insertion_proc
65
+ new_body = @js_agent_insertion_proc.call(@script_insert, body)
66
+
67
+ if new_body != body
68
+ # js agent was successfully inserted so no need to keep
69
+ # calling this proc
70
+ @js_agent_insertion_proc = nil
82
71
  end
83
72
  end
84
73
 
85
74
  @content_length += new_body.bytesize
86
75
  end
87
-
88
- new_body
89
76
  end
77
+
78
+ new_body
90
79
  end
91
80
  end
92
81
  end
Binary file
@@ -1,5 +1,5 @@
1
1
  # See the file "LICENSE" for the full license governing this code.
2
2
 
3
3
  module TCellAgent
4
- VERSION = '2.5.1'.freeze
4
+ VERSION = '2.5.2'.freeze
5
5
  end
@@ -22,8 +22,7 @@ module TCellAgent
22
22
  it 'appfirewall injections should be checked' do
23
23
  tcell_body_proxy = TCellBodyProxy.new(
24
24
  Rack::BodyProxy.new(['body']) {},
25
- true,
26
- nil, nil, nil, nil
25
+ nil, nil, {}
27
26
  )
28
27
  tcell_body_proxy.meta_data = @meta_data
29
28
 
@@ -48,8 +47,7 @@ module TCellAgent
48
47
  it 'should check for appfirewall injections' do
49
48
  tcell_body_proxy = TCellBodyProxy.new(
50
49
  Rack::BodyProxy.new(['body']) {},
51
- true,
52
- nil, nil, nil, nil
50
+ nil, nil, {}
53
51
  )
54
52
  tcell_body_proxy.meta_data = @meta_data
55
53
 
@@ -78,8 +76,7 @@ module TCellAgent
78
76
  it 'should return an enumerator' do
79
77
  tcell_body_proxy = TCellBodyProxy.new(
80
78
  Rack::BodyProxy.new(['body']) {},
81
- true,
82
- nil, nil, nil, nil
79
+ nil, nil, {}
83
80
  )
84
81
  expect(tcell_body_proxy.each.class.name).to eq('Enumerator')
85
82
  end
@@ -89,15 +86,16 @@ module TCellAgent
89
86
  context 'with a chunked response' do
90
87
  it 'should only calculate content length' do
91
88
  tcell_body_proxy = TCellBodyProxy.new(
92
- Rack::BodyProxy.new(["2d\r\nsome content\r\n"]) {},
93
- false,
94
- nil, nil, nil, nil
89
+ Rack::BodyProxy.new(["2d\r\nsome content\r\n", "0\r\n"]) {},
90
+ nil, nil, { 'Transfer-Encoding' => 'chunked' }
95
91
  )
96
92
 
97
93
  expect(TCellAgent::Instrumentation).to receive(:safe_block).with(
98
94
  'Processing tcell body proxy body'
99
95
  ).and_call_original
100
-
96
+ expect(TCellAgent::Instrumentation).to receive(:safe_block).with(
97
+ 'Processing tcell body proxy body'
98
+ ).and_call_original
101
99
  tcell_body_proxy.each { |b| }
102
100
 
103
101
  expect(tcell_body_proxy.content_length).to eq(45)
@@ -109,8 +107,7 @@ module TCellAgent
109
107
  it 'should only calculate content length' do
110
108
  tcell_body_proxy = TCellBodyProxy.new(
111
109
  Rack::BodyProxy.new(['some content']) {},
112
- false,
113
- nil, nil, nil, nil
110
+ nil, nil, {}
114
111
  )
115
112
 
116
113
  expect(TCellAgent::Instrumentation).to receive(:safe_block).with(
@@ -126,11 +123,9 @@ module TCellAgent
126
123
  context 'that should be processed' do
127
124
  it 'should call js and dlp procs as well as calculate content length' do
128
125
  js_agent_insertion_proc = double('js_agent_insertion_proc')
129
- dlp_cleaner_proc = double('dlp_cleaner_proc')
130
126
  tcell_body_proxy = TCellBodyProxy.new(
131
127
  Rack::BodyProxy.new(['some content']) {},
132
- true,
133
- js_agent_insertion_proc, 'script_insert', dlp_cleaner_proc, nil
128
+ js_agent_insertion_proc, 'script_insert', {}
134
129
  )
135
130
 
136
131
  expect(TCellAgent::Instrumentation).to receive(:safe_block).with(
@@ -139,7 +134,6 @@ module TCellAgent
139
134
  expect(js_agent_insertion_proc).to receive(:call).with(
140
135
  'script_insert', 'some content'
141
136
  ).and_return('some content')
142
- expect(dlp_cleaner_proc).to receive(:call).with(nil, 'some content')
143
137
 
144
138
  tcell_body_proxy.each { |b| }
145
139
 
@@ -154,11 +148,9 @@ module TCellAgent
154
148
  it 'should only calculate content length' do
155
149
  body_chunk = 'some content'
156
150
  js_agent_insertion_proc = double('js_agent_insertion_proc')
157
- dlp_cleaner_proc = double('dlp_cleaner_proc')
158
151
  tcell_body_proxy = TCellBodyProxy.new(
159
152
  Rack::BodyProxy.new([body_chunk]) {},
160
- false,
161
- nil, nil, nil, nil
153
+ nil, nil, {}
162
154
  )
163
155
 
164
156
  expect(TCellAgent::Instrumentation).to receive(:safe_block).with(
@@ -167,11 +159,7 @@ module TCellAgent
167
159
  expect(body_chunk).to receive(:class).and_return(
168
160
  double('body_class', :name => 'ActionView::OutputBuffer')
169
161
  )
170
- expect(body_chunk).to receive(:class).and_return(
171
- double('body_class', :name => 'ActionView::OutputBuffer')
172
- )
173
162
  expect(js_agent_insertion_proc).to_not receive(:call)
174
- expect(dlp_cleaner_proc).to_not receive(:call)
175
163
 
176
164
  tcell_body_proxy.each { |b| }
177
165
 
@@ -183,11 +171,9 @@ module TCellAgent
183
171
  it 'should call js and dlp procs as well as calculate content length' do
184
172
  body_chunk = 'some content'
185
173
  js_agent_insertion_proc = double('js_agent_insertion_proc')
186
- dlp_cleaner_proc = double('dlp_cleaner_proc')
187
174
  tcell_body_proxy = TCellBodyProxy.new(
188
175
  Rack::BodyProxy.new([body_chunk]) {},
189
- true,
190
- js_agent_insertion_proc, 'script_insert', dlp_cleaner_proc, nil
176
+ js_agent_insertion_proc, 'script_insert', {}
191
177
  )
192
178
 
193
179
  expect(TCellAgent::Instrumentation).to receive(:safe_block).with(
@@ -196,7 +182,6 @@ module TCellAgent
196
182
  expect(js_agent_insertion_proc).to receive(:call).with(
197
183
  'script_insert', body_chunk
198
184
  ).and_return(body_chunk)
199
- expect(dlp_cleaner_proc).to receive(:call).with(nil, body_chunk)
200
185
 
201
186
  tcell_body_proxy.each { |b| }
202
187
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tcell_agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.1
4
+ version: 2.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rapid7, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-17 00:00:00.000000000 Z
11
+ date: 2022-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -272,7 +272,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
272
272
  - !ruby/object:Gem::Version
273
273
  version: '0'
274
274
  requirements: []
275
- rubygems_version: 3.2.22
275
+ rubygems_version: 3.2.32
276
276
  signing_key:
277
277
  specification_version: 4
278
278
  summary: tCell Agent for Rails