tcell_agent 2.5.1 → 2.5.2

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: 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