tcell_agent 1.1.12 → 2.2.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.
Files changed (169) hide show
  1. checksums.yaml +5 -5
  2. data/bin/tcell_agent +45 -137
  3. data/lib/tcell_agent.rb +12 -14
  4. data/lib/tcell_agent/agent.rb +108 -97
  5. data/lib/tcell_agent/agent/route_manager.rb +0 -16
  6. data/lib/tcell_agent/agent/static_agent.rb +9 -30
  7. data/lib/tcell_agent/config_initializer.rb +66 -0
  8. data/lib/tcell_agent/configuration.rb +69 -345
  9. data/lib/tcell_agent/hooks/login_fraud.rb +30 -33
  10. data/lib/tcell_agent/instrument_servers.rb +23 -0
  11. data/lib/tcell_agent/instrumentation.rb +12 -10
  12. data/lib/tcell_agent/instrumentation/cmdi.rb +29 -25
  13. data/lib/tcell_agent/instrumentation/lfi.rb +84 -0
  14. data/lib/tcell_agent/instrumentation/monkey_patches/file.rb +25 -0
  15. data/lib/tcell_agent/instrumentation/monkey_patches/io.rb +131 -0
  16. data/lib/tcell_agent/instrumentation/monkey_patches/kernel.rb +102 -0
  17. data/lib/tcell_agent/logger.rb +49 -114
  18. data/lib/tcell_agent/patches.rb +6 -7
  19. data/lib/tcell_agent/policies/appfirewall_policy.rb +26 -0
  20. data/lib/tcell_agent/policies/command_injection_policy.rb +28 -0
  21. data/lib/tcell_agent/policies/dataloss_policy.rb +44 -44
  22. data/lib/tcell_agent/policies/headers_policy.rb +25 -0
  23. data/lib/tcell_agent/policies/http_redirect_policy.rb +13 -79
  24. data/lib/tcell_agent/policies/js_agent_policy.rb +27 -0
  25. data/lib/tcell_agent/policies/local_file_access.rb +28 -0
  26. data/lib/tcell_agent/policies/login_policy.rb +43 -0
  27. data/lib/tcell_agent/policies/patches_policy.rb +27 -0
  28. data/lib/tcell_agent/policies/policies_manager.rb +68 -0
  29. data/lib/tcell_agent/policies/policy_polling.rb +58 -0
  30. data/lib/tcell_agent/policies/policy_types.rb +14 -0
  31. data/lib/tcell_agent/policies/system_enablements.rb +27 -0
  32. data/lib/tcell_agent/rails/auth/authlogic.rb +46 -75
  33. data/lib/tcell_agent/rails/auth/authlogic_helper.rb +20 -0
  34. data/lib/tcell_agent/rails/auth/devise.rb +100 -105
  35. data/lib/tcell_agent/rails/auth/devise_helper.rb +29 -0
  36. data/lib/tcell_agent/rails/auth/doorkeeper.rb +62 -76
  37. data/lib/tcell_agent/{userinfo.rb → rails/auth/userinfo.rb} +0 -0
  38. data/lib/tcell_agent/rails/csrf_exception.rb +2 -10
  39. data/lib/tcell_agent/rails/dlp.rb +35 -23
  40. data/lib/tcell_agent/rails/dlp_handler.rb +1 -2
  41. data/lib/tcell_agent/rails/js_agent_insert.rb +12 -13
  42. data/lib/tcell_agent/rails/middleware/body_filter_middleware.rb +4 -25
  43. data/lib/tcell_agent/rails/middleware/context_middleware.rb +2 -12
  44. data/lib/tcell_agent/rails/middleware/global_middleware.rb +1 -2
  45. data/lib/tcell_agent/rails/middleware/headers_middleware.rb +14 -34
  46. data/lib/tcell_agent/{rails.rb → rails/railties/tcell_agent_railties.rb} +11 -16
  47. data/lib/tcell_agent/rails/railties/tcell_agent_unicorn_railties.rb +8 -0
  48. data/lib/tcell_agent/rails/routes.rb +10 -12
  49. data/lib/tcell_agent/rails/routes/grape.rb +4 -14
  50. data/lib/tcell_agent/rails/routes/route_id.rb +3 -1
  51. data/lib/tcell_agent/rails/settings_reporter.rb +23 -36
  52. data/lib/tcell_agent/rails/tcell_body_proxy.rb +5 -4
  53. data/lib/tcell_agent/rust/agent_config.rb +60 -0
  54. data/lib/tcell_agent/rust/{libtcellagent-alpine-1.3.2.so → libtcellagent-5.0.2.dylib} +0 -0
  55. data/lib/tcell_agent/rust/{libtcellagent-1.3.2.so → libtcellagent-5.0.2.so} +0 -0
  56. data/lib/tcell_agent/rust/libtcellagent-alpine-5.0.2.so +0 -0
  57. data/lib/tcell_agent/rust/models.rb +6 -52
  58. data/lib/tcell_agent/rust/native_agent.rb +549 -0
  59. data/lib/tcell_agent/rust/native_agent_response.rb +42 -0
  60. data/lib/tcell_agent/rust/native_library.rb +69 -0
  61. data/lib/tcell_agent/rust/tcellagent-5.0.2.dll +0 -0
  62. data/lib/tcell_agent/sensor_events/agent_setting_event.rb +12 -0
  63. data/lib/tcell_agent/sensor_events/{app_config.rb → app_config_setting_event.rb} +0 -6
  64. data/lib/tcell_agent/sensor_events/dlp.rb +2 -6
  65. data/lib/tcell_agent/sensor_events/sensor.rb +0 -62
  66. data/lib/tcell_agent/sensor_events/server_agent.rb +13 -18
  67. data/lib/tcell_agent/sensor_events/util/sanitizer_utilities.rb +0 -108
  68. data/lib/tcell_agent/sensor_events/util/utils.rb +0 -2
  69. data/lib/tcell_agent/servers/passenger.rb +1 -28
  70. data/lib/tcell_agent/servers/puma.rb +3 -21
  71. data/lib/tcell_agent/servers/rails_server.rb +1 -2
  72. data/lib/tcell_agent/servers/thin.rb +2 -2
  73. data/lib/tcell_agent/servers/unicorn.rb +19 -80
  74. data/lib/tcell_agent/servers/webrick.rb +1 -2
  75. data/lib/tcell_agent/settings_reporter.rb +11 -90
  76. data/lib/tcell_agent/sinatra.rb +14 -16
  77. data/lib/tcell_agent/tcell_context.rb +40 -14
  78. data/lib/tcell_agent/utils/headers.rb +14 -0
  79. data/lib/tcell_agent/version.rb +1 -1
  80. data/spec/lib/tcell_agent/configuration_spec.rb +55 -346
  81. data/spec/lib/tcell_agent/hooks/login_fraud_spec.rb +46 -173
  82. data/spec/lib/tcell_agent/instrumentation/cmdi/io_cmdi_spec.rb +504 -0
  83. data/spec/lib/tcell_agent/instrumentation/cmdi/kernel_cmdi_spec.rb +435 -0
  84. data/spec/lib/tcell_agent/instrumentation/cmdi_spec.rb +201 -0
  85. data/spec/lib/tcell_agent/instrumentation/lfi/file_lfi_spec.rb +326 -0
  86. data/spec/lib/tcell_agent/instrumentation/lfi/io_lfi_spec.rb +562 -0
  87. data/spec/lib/tcell_agent/instrumentation/lfi/kernel_lfi_spec.rb +264 -0
  88. data/spec/lib/tcell_agent/instrumentation/lfi_spec.rb +150 -0
  89. data/spec/lib/tcell_agent/patches_spec.rb +25 -43
  90. data/spec/lib/tcell_agent/policies/appfirewall_policy_spec.rb +183 -0
  91. data/spec/lib/tcell_agent/policies/clickjacking_policy_spec.rb +57 -0
  92. data/spec/lib/tcell_agent/policies/command_injection_policy_spec.rb +84 -773
  93. data/spec/lib/tcell_agent/policies/content_security_policy_spec.rb +161 -0
  94. data/spec/lib/tcell_agent/policies/dataloss_policy_spec.rb +9 -9
  95. data/spec/lib/tcell_agent/policies/http_redirect_policy_spec.rb +243 -198
  96. data/spec/lib/tcell_agent/policies/js_agent_policy_spec.rb +75 -0
  97. data/spec/lib/tcell_agent/policies/login_policy_spec.rb +165 -33
  98. data/spec/lib/tcell_agent/policies/patches_policy_spec.rb +84 -277
  99. data/spec/lib/tcell_agent/policies/policies_manager_spec.rb +104 -0
  100. data/spec/lib/tcell_agent/policies/policy_polling_spec.rb +6 -0
  101. data/spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb +56 -0
  102. data/spec/lib/tcell_agent/rails/csrf_exception_spec.rb +9 -18
  103. data/spec/lib/tcell_agent/rails/js_agent_insert_spec.rb +13 -30
  104. data/spec/lib/tcell_agent/rails/logger_spec.rb +27 -7
  105. data/spec/lib/tcell_agent/rails/middleware/tcell_body_proxy_spec.rb +17 -12
  106. data/spec/lib/tcell_agent/rails/routes/routes_spec.rb +14 -14
  107. data/spec/lib/tcell_agent/rust/agent_config_spec.rb +27 -0
  108. data/spec/lib/tcell_agent/sensor_events/util/sanitizer_utilities_spec.rb +0 -35
  109. data/spec/lib/tcell_agent/settings_reporter_spec.rb +56 -155
  110. data/spec/spec_helper.rb +1 -1
  111. data/spec/support/builders.rb +103 -0
  112. data/spec/support/force_logger_mocking.rb +38 -0
  113. data/spec/support/resources/lfi_sample_file.txt +2 -0
  114. data/spec/support/static_agent_overrides.rb +0 -15
  115. metadata +72 -83
  116. data/lib/tcell_agent/agent/event_processor.rb +0 -326
  117. data/lib/tcell_agent/agent/fork_pipe_manager.rb +0 -113
  118. data/lib/tcell_agent/agent/policy_manager.rb +0 -219
  119. data/lib/tcell_agent/agent/policy_types.rb +0 -30
  120. data/lib/tcell_agent/api.rb +0 -91
  121. data/lib/tcell_agent/appsensor/injections_reporter.rb +0 -24
  122. data/lib/tcell_agent/authlogic.rb +0 -26
  123. data/lib/tcell_agent/config/child_process_events.rb +0 -8
  124. data/lib/tcell_agent/config/unknown_options.rb +0 -123
  125. data/lib/tcell_agent/devise.rb +0 -35
  126. data/lib/tcell_agent/instrumentation/cmdi/backtick.rb +0 -10
  127. data/lib/tcell_agent/instrumentation/cmdi/exec.rb +0 -14
  128. data/lib/tcell_agent/instrumentation/cmdi/popen.rb +0 -28
  129. data/lib/tcell_agent/instrumentation/cmdi/spawn.rb +0 -11
  130. data/lib/tcell_agent/instrumentation/cmdi/system.rb +0 -11
  131. data/lib/tcell_agent/policies/http_tx_policy.rb +0 -60
  132. data/lib/tcell_agent/policies/login_fraud_policy.rb +0 -45
  133. data/lib/tcell_agent/policies/rust_policies.rb +0 -110
  134. data/lib/tcell_agent/rails/on_start.rb +0 -41
  135. data/lib/tcell_agent/rust/libtcellagent-1.3.2.dylib +0 -0
  136. data/lib/tcell_agent/rust/tcellagent-1.3.2.dll +0 -0
  137. data/lib/tcell_agent/rust/whisperer.rb +0 -308
  138. data/lib/tcell_agent/sensor_events/appsensor_event.rb +0 -52
  139. data/lib/tcell_agent/sensor_events/appsensor_meta_event.rb +0 -45
  140. data/lib/tcell_agent/sensor_events/command_injection.rb +0 -75
  141. data/lib/tcell_agent/sensor_events/honeytokens.rb +0 -16
  142. data/lib/tcell_agent/sensor_events/login_fraud.rb +0 -60
  143. data/lib/tcell_agent/sensor_events/metrics.rb +0 -123
  144. data/lib/tcell_agent/sensor_events/patches.rb +0 -21
  145. data/lib/tcell_agent/start_background_thread.rb +0 -55
  146. data/lib/tcell_agent/system_info.rb +0 -11
  147. data/lib/tcell_agent/utils/io.rb +0 -38
  148. data/lib/tcell_agent/utils/passwords.rb +0 -28
  149. data/lib/tcell_agent/utils/queue_with_timeout.rb +0 -142
  150. data/spec/lib/tcell_agent/agent/fork_pipe_manager_spec.rb +0 -100
  151. data/spec/lib/tcell_agent/agent/policy_manager_spec.rb +0 -535
  152. data/spec/lib/tcell_agent/agent/static_agent_spec.rb +0 -133
  153. data/spec/lib/tcell_agent/api/api_spec.rb +0 -39
  154. data/spec/lib/tcell_agent/appsensor/injections_reporter_spec.rb +0 -187
  155. data/spec/lib/tcell_agent/cmdi_spec.rb +0 -736
  156. data/spec/lib/tcell_agent/config/unknown_options_spec.rb +0 -213
  157. data/spec/lib/tcell_agent/instrumentation_spec.rb +0 -225
  158. data/spec/lib/tcell_agent/policies/appsensor_policy_spec.rb +0 -517
  159. data/spec/lib/tcell_agent/policies/http_tx_policy_spec.rb +0 -22
  160. data/spec/lib/tcell_agent/rails/middleware/appsensor_middleware_spec.rb +0 -293
  161. data/spec/lib/tcell_agent/rails/middleware/dlp_middleware_spec.rb +0 -198
  162. data/spec/lib/tcell_agent/rails/middleware/global_middleware_spec.rb +0 -180
  163. data/spec/lib/tcell_agent/rails/middleware/redirect_middleware_spec.rb +0 -116
  164. data/spec/lib/tcell_agent/rust/models_spec.rb +0 -120
  165. data/spec/lib/tcell_agent/rust/whisperer_spec.rb +0 -704
  166. data/spec/lib/tcell_agent/sensor_events/appsensor_meta_event_spec.rb +0 -45
  167. data/spec/lib/tcell_agent/sensor_events/sessions_metric_spec.rb +0 -272
  168. data/spec/lib/tcell_agent/utils/bounded_queue_spec.rb +0 -52
  169. data/spec/lib/tcell_agent/utils/passwords_spec.rb +0 -143
@@ -0,0 +1,435 @@
1
+ require 'spec_helper'
2
+
3
+ describe Kernel do
4
+ before(:each) do
5
+ native_agent = double('native_agent')
6
+ @command_injection_policy = TCellAgent::Policies::CommandInjectionPolicy.new(
7
+ native_agent, {}
8
+ )
9
+ end
10
+
11
+ describe '.backtick' do
12
+ context 'empty command' do
13
+ it 'should raise Errno::ENOENT' do
14
+ expect do
15
+ ``
16
+ end.to raise_error(Errno::ENOENT)
17
+ end
18
+ end
19
+
20
+ context 'with a non blocked command present' do
21
+ before(:each) do
22
+ allow_any_instance_of(TCellAgent::Agent).to receive(:safe_to_check_cmdi).and_return(true)
23
+ end
24
+
25
+ context 'with command injection disabled' do
26
+ it 'should execute the command' do
27
+ expect(TCellAgent).to receive(:policy).with(
28
+ TCellAgent::PolicyTypes::COMMANDINJECTION
29
+ ).and_return(@command_injection_policy)
30
+ expect(@command_injection_policy).to receive(:enabled).and_return(false)
31
+ expect(@command_injection_policy).to_not receive(:block_command?)
32
+
33
+ `echo test`
34
+ end
35
+ end
36
+
37
+ context 'with command injection enabled' do
38
+ it 'should execute the command' do
39
+ expect(TCellAgent).to receive(:policy).with(
40
+ TCellAgent::PolicyTypes::COMMANDINJECTION
41
+ ).and_return(@command_injection_policy)
42
+ expect(@command_injection_policy).to receive(:enabled).and_return(true)
43
+ expect(@command_injection_policy).to receive(:block_command?).with('echo test', nil).and_return(false)
44
+
45
+ `echo test`
46
+ end
47
+ end
48
+ end
49
+
50
+ context 'with a blocked command present' do
51
+ context 'with command injection enabled' do
52
+ it 'should raise a RuntimeError' do
53
+ allow_any_instance_of(TCellAgent::Agent).to receive(:safe_to_check_cmdi).and_return(true)
54
+ expect(TCellAgent).to receive(:policy).with(
55
+ TCellAgent::PolicyTypes::COMMANDINJECTION
56
+ ).and_return(@command_injection_policy)
57
+ expect(@command_injection_policy).to receive(:enabled).and_return(true)
58
+ expect(@command_injection_policy).to receive(:block_command?).with('echo test', nil).and_return(true)
59
+
60
+ expect do
61
+ `echo test`
62
+ end.to raise_error(RuntimeError)
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ describe '%x methods' do
69
+ context 'empty command' do
70
+ it 'should raise RuntimeError' do
71
+ expect do
72
+ ``
73
+ end.to raise_error(Errno::ENOENT)
74
+ end
75
+ end
76
+
77
+ context 'with a non blocked command present' do
78
+ before(:each) do
79
+ allow_any_instance_of(TCellAgent::Agent).to receive(:safe_to_check_cmdi).and_return(true)
80
+ end
81
+
82
+ context 'with command injection disabled' do
83
+ it 'should execute the command' do
84
+ expect(TCellAgent).to receive(:policy).with(
85
+ TCellAgent::PolicyTypes::COMMANDINJECTION
86
+ ).and_return(@command_injection_policy)
87
+ expect(@command_injection_policy).to receive(:enabled).and_return(false)
88
+ expect(@command_injection_policy).to_not receive(:block_command?)
89
+
90
+ `echo test`
91
+ end
92
+ end
93
+
94
+ context 'with command injection enabled' do
95
+ it 'should execute the command' do
96
+ expect(TCellAgent).to receive(:policy).with(
97
+ TCellAgent::PolicyTypes::COMMANDINJECTION
98
+ ).and_return(@command_injection_policy)
99
+ expect(@command_injection_policy).to receive(:enabled).and_return(true)
100
+ expect(@command_injection_policy).to receive(:block_command?).with('echo test', nil).and_return(false)
101
+
102
+ `echo test`
103
+ end
104
+ end
105
+ end
106
+
107
+ context 'with a blocked command present' do
108
+ context 'with command injection enabled' do
109
+ it 'should raise a RuntimeError' do
110
+ allow_any_instance_of(TCellAgent::Agent).to receive(:safe_to_check_cmdi).and_return(true)
111
+ expect(TCellAgent).to receive(:policy).with(
112
+ TCellAgent::PolicyTypes::COMMANDINJECTION
113
+ ).and_return(@command_injection_policy)
114
+ expect(@command_injection_policy).to receive(:enabled).and_return(true)
115
+ expect(@command_injection_policy).to receive(:block_command?).with('echo test', nil).and_return(true)
116
+
117
+ expect do
118
+ `echo test`
119
+ end.to raise_error(RuntimeError)
120
+ end
121
+ end
122
+ end
123
+ end
124
+
125
+ describe '::open and #open' do
126
+ context 'empty command' do
127
+ it 'should raise an error' do
128
+ expect do
129
+ Kernel.open
130
+ end.to raise_error(ArgumentError)
131
+ expect do
132
+ Kernel.open(nil)
133
+ end.to raise_error(TypeError)
134
+ expect do
135
+ Kernel.open('')
136
+ end.to raise_error(Errno::ENOENT)
137
+ end
138
+ end
139
+
140
+ context 'name starts with a | operator' do
141
+ context 'with an empty or invalid command' do
142
+ it 'should raise an error' do
143
+ expect do
144
+ Kernel.open('|')
145
+ end.to raise_error(Errno::ENOENT)
146
+
147
+ expect do
148
+ Kernel.open('|invalid command')
149
+ end.to raise_error(Errno::ENOENT)
150
+
151
+ expect do
152
+ Kernel.open('|invalid command', 10)
153
+ end.to raise_error(Errno::ENOENT)
154
+ end
155
+ end
156
+ context 'with a valid command' do
157
+ it 'should execute the command' do
158
+ expect(Kernel.open('|echo test').read).to eq("test\n")
159
+ end
160
+ end
161
+ context 'with a non blocked command present' do
162
+ before(:each) do
163
+ allow_any_instance_of(TCellAgent::Agent).to receive(:safe_to_check_cmdi).and_return(true)
164
+ end
165
+ context 'with command injection disabled' do
166
+ it 'should execute the command' do
167
+ expect(@command_injection_policy.enabled).to eq(false)
168
+
169
+ expect(TCellAgent).to receive(:policy).with(
170
+ TCellAgent::PolicyTypes::COMMANDINJECTION
171
+ ).and_return(@command_injection_policy)
172
+ expect(@command_injection_policy).to receive(:enabled).and_call_original
173
+ expect(@command_injection_policy).to_not receive(:block_command?)
174
+
175
+ expect(Kernel.open('|echo test').read).to eq("test\n")
176
+ end
177
+ end
178
+
179
+ context 'with command injection enabled' do
180
+ it 'should execute the command' do
181
+ expect(TCellAgent).to receive(:policy).with(
182
+ TCellAgent::PolicyTypes::COMMANDINJECTION
183
+ ).and_return(@command_injection_policy)
184
+ expect(@command_injection_policy).to receive(:enabled).and_return(true)
185
+ expect(@command_injection_policy).to receive(:block_command?).with('echo test', nil).and_return(false)
186
+
187
+ expect(Kernel.open('|echo test').read).to eq("test\n")
188
+ end
189
+ end
190
+ end
191
+
192
+ context 'with a blocked command present' do
193
+ context 'with command injection enabled' do
194
+ it 'should raise a RuntimeError' do
195
+ allow_any_instance_of(TCellAgent::Agent).to receive(:safe_to_check_cmdi).and_return(true)
196
+
197
+ expect(TCellAgent).to receive(:policy).with(
198
+ TCellAgent::PolicyTypes::COMMANDINJECTION
199
+ ).and_return(@command_injection_policy)
200
+ expect(@command_injection_policy).to receive(:enabled).and_return(true)
201
+ expect(@command_injection_policy).to receive(:block_command?).with('echo test', nil).and_return(true)
202
+
203
+ expect do
204
+ Kernel.open('|echo test')
205
+ end.to raise_error(RuntimeError)
206
+ end
207
+ end
208
+ end
209
+ end
210
+ end
211
+ describe '.spawn and Kernel.spawn' do
212
+ context 'empty command' do
213
+ it 'should raise an error' do
214
+ expect do
215
+ spawn
216
+ end.to raise_error(ArgumentError)
217
+ expect do
218
+ Kernel.spawn
219
+ end.to raise_error(ArgumentError)
220
+ expect do
221
+ spawn(nil)
222
+ end.to raise_error(TypeError)
223
+ expect do
224
+ Kernel.spawn(nil)
225
+ end.to raise_error(TypeError)
226
+ expect do
227
+ spawn('')
228
+ end.to raise_error(Errno::ENOENT)
229
+ expect do
230
+ Kernel.spawn('')
231
+ end.to raise_error(Errno::ENOENT)
232
+ end
233
+ end
234
+
235
+ context 'non existent command' do
236
+ it 'should raise error' do
237
+ expect do
238
+ spawn('foobar')
239
+ end.to raise_error(Errno::ENOENT)
240
+ expect do
241
+ Kernel.spawn('foobar')
242
+ end.to raise_error(Errno::ENOENT)
243
+ end
244
+ end
245
+
246
+ context 'with a valid command' do
247
+ it 'should execute command' do
248
+ pid = spawn('echo test > /dev/null 2>&1')
249
+ expect(pid).to_not be_nil
250
+
251
+ pid = spawn(RbConfig.ruby, "-e'Hello World!'", '>', '/dev/null', '2>&1')
252
+ expect(pid).to_not be_nil
253
+
254
+ pid = Kernel.spawn('echo test > /dev/null 2>&1')
255
+ expect(pid).to_not be_nil
256
+
257
+ pid = Kernel.spawn(RbConfig.ruby, "-e'Hello World!'", '>', '/dev/null', '2>&1')
258
+ expect(pid).to_not be_nil
259
+ end
260
+ end
261
+
262
+ context 'with a non blocked command present' do
263
+ before(:each) do
264
+ allow_any_instance_of(TCellAgent::Agent).to receive(:safe_to_check_cmdi).and_return(true)
265
+ end
266
+
267
+ context 'with command injection disabled' do
268
+ it 'should execute the command' do
269
+ expect(TCellAgent).to receive(:policy).with(
270
+ TCellAgent::PolicyTypes::COMMANDINJECTION
271
+ ).and_return(@command_injection_policy, @command_injection_policy)
272
+ expect(@command_injection_policy).to receive(:enabled).and_return(false, false)
273
+ expect(@command_injection_policy).to_not receive(:block_command?)
274
+
275
+ spawn('echo test > /dev/null 2>&1')
276
+ Kernel.spawn('echo test > /dev/null 2>&1')
277
+ end
278
+ end
279
+
280
+ context 'with command injection enabled' do
281
+ it 'should execute the command' do
282
+ expect(TCellAgent).to receive(:policy).with(
283
+ TCellAgent::PolicyTypes::COMMANDINJECTION
284
+ ).and_return(@command_injection_policy, @command_injection_policy)
285
+ expect(@command_injection_policy).to receive(:enabled).and_return(true, true)
286
+ expect(@command_injection_policy).to receive(:block_command?).with('echo test > /dev/null 2>&1', nil).and_return(false, false)
287
+
288
+ spawn('echo test > /dev/null 2>&1')
289
+ Kernel.spawn('echo test > /dev/null 2>&1')
290
+ end
291
+ end
292
+ end
293
+
294
+ context 'with a blocked command present' do
295
+ context 'with command injection enabled' do
296
+ it 'should raise a RuntimeError' do
297
+ allow_any_instance_of(TCellAgent::Agent).to receive(:safe_to_check_cmdi).and_return(true)
298
+ expect(TCellAgent).to receive(:policy).with(
299
+ TCellAgent::PolicyTypes::COMMANDINJECTION
300
+ ).and_return(@command_injection_policy, @command_injection_policy)
301
+ expect(@command_injection_policy).to receive(:enabled).and_return(true, true)
302
+ expect(@command_injection_policy).to receive(:block_command?).with('echo test', nil).and_return(true, true)
303
+
304
+ expect do
305
+ spawn('echo test')
306
+ end.to raise_error(RuntimeError)
307
+ expect do
308
+ Kernel.spawn('echo test')
309
+ end.to raise_error(RuntimeError)
310
+ end
311
+ end
312
+ end
313
+ end
314
+
315
+ describe '.system and Kernel.system' do
316
+ context 'empty command' do
317
+ it 'should raise an error' do
318
+ expect do
319
+ system
320
+ end.to raise_error(ArgumentError)
321
+ expect do
322
+ Kernel.system
323
+ end.to raise_error(ArgumentError)
324
+ expect do
325
+ system(nil)
326
+ end.to raise_error(TypeError)
327
+ expect do
328
+ Kernel.system(nil)
329
+ end.to raise_error(TypeError)
330
+ expect(system('')).to be_nil
331
+ expect(Kernel.system('')).to be_nil
332
+ end
333
+ end
334
+
335
+ context 'non existent command' do
336
+ it 'should return nil' do
337
+ expect(system('foobar')).to be_nil
338
+ expect(Kernel.system('foobar')).to be_nil
339
+ end
340
+ end
341
+
342
+ context 'with a valid command' do
343
+ it 'should execute command' do
344
+ pid = system('echo test > /dev/null 2>&1')
345
+ expect(pid).to eq(true)
346
+
347
+ pid = system(RbConfig.ruby, "-e'Hello World!'", '>', '/dev/null', '2>&1')
348
+ expect(pid).to eq(true)
349
+
350
+ pid = Kernel.system('echo test > /dev/null 2>&1')
351
+ expect(pid).to eq(true)
352
+
353
+ pid = Kernel.system(RbConfig.ruby, "-e'Hello World!'", '>', '/dev/null', '2>&1')
354
+ expect(pid).to eq(true)
355
+ end
356
+ end
357
+
358
+ context 'with a non blocked command present' do
359
+ before(:each) do
360
+ allow_any_instance_of(TCellAgent::Agent).to receive(:safe_to_check_cmdi).and_return(true)
361
+ end
362
+
363
+ context 'with command injection disabled' do
364
+ it 'should execute the command' do
365
+ expect(TCellAgent).to receive(:policy).with(
366
+ TCellAgent::PolicyTypes::COMMANDINJECTION
367
+ ).and_return(@command_injection_policy, @command_injection_policy)
368
+ expect(@command_injection_policy).to receive(:enabled).and_return(false, false)
369
+ expect(@command_injection_policy).to_not receive(:block_command?)
370
+
371
+ system('echo test > /dev/null 2>&1')
372
+ Kernel.system('echo test > /dev/null 2>&1')
373
+ end
374
+ end
375
+
376
+ context 'with command injection enabled' do
377
+ it 'should execute the command' do
378
+ expect(TCellAgent).to receive(:policy).with(
379
+ TCellAgent::PolicyTypes::COMMANDINJECTION
380
+ ).and_return(@command_injection_policy, @command_injection_policy)
381
+ expect(@command_injection_policy).to receive(:enabled).and_return(true, true)
382
+ expect(@command_injection_policy).to receive(:block_command?).with('echo test > /dev/null 2>&1', nil).and_return(false, false)
383
+
384
+ system('echo test > /dev/null 2>&1')
385
+ Kernel.system('echo test > /dev/null 2>&1')
386
+ end
387
+ end
388
+ end
389
+
390
+ context 'with a blocked command present' do
391
+ context 'with command injection enabled' do
392
+ it 'should raise a RuntimeError' do
393
+ allow_any_instance_of(TCellAgent::Agent).to receive(:safe_to_check_cmdi).and_return(true)
394
+
395
+ expect(TCellAgent).to receive(:policy).with(
396
+ TCellAgent::PolicyTypes::COMMANDINJECTION
397
+ ).and_return(@command_injection_policy, @command_injection_policy)
398
+ expect(@command_injection_policy).to receive(:enabled).and_return(true, true)
399
+ expect(@command_injection_policy).to receive(:block_command?).with('echo test', nil).and_return(true, true)
400
+
401
+ expect do
402
+ system('echo test')
403
+ end.to raise_error(RuntimeError)
404
+ expect do
405
+ Kernel.system('echo test')
406
+ end.to raise_error(RuntimeError)
407
+ end
408
+ end
409
+ end
410
+ end
411
+
412
+ describe '.exec' do
413
+ # can only test this case since exec replaces current process with new process
414
+ context 'with a blocked command present' do
415
+ context 'with command injection enabled' do
416
+ it 'should raise a RuntimeError' do
417
+ allow_any_instance_of(TCellAgent::Agent).to receive(:safe_to_check_cmdi).and_return(true)
418
+
419
+ expect(TCellAgent).to receive(:policy).with(
420
+ TCellAgent::PolicyTypes::COMMANDINJECTION
421
+ ).and_return(@command_injection_policy, @command_injection_policy)
422
+ expect(@command_injection_policy).to receive(:enabled).and_return(true, true)
423
+ expect(@command_injection_policy).to receive(:block_command?).with('echo test', nil).and_return(true, true)
424
+
425
+ expect do
426
+ exec('echo test')
427
+ end.to raise_error(RuntimeError)
428
+ expect do
429
+ Kernel.exec('echo test')
430
+ end.to raise_error(RuntimeError)
431
+ end
432
+ end
433
+ end
434
+ end
435
+ end
@@ -0,0 +1,201 @@
1
+ require 'spec_helper'
2
+
3
+ module TCellAgent
4
+ module Cmdi
5
+ describe '.parse_command' do
6
+ context 'with env' do
7
+ before(:each) do
8
+ @env = { 'TCELL_VAR' => 'enabled' }
9
+ end
10
+
11
+ context 'with string command' do
12
+ it 'should parse the command properly' do
13
+ cmd = TCellAgent::Cmdi.parse_command(@env, 'echo')
14
+ expect(cmd).to eq('echo')
15
+
16
+ cmd = TCellAgent::Cmdi.parse_command(@env, 'echo', :unsetenv_others => true)
17
+ expect(cmd).to eq('echo')
18
+ end
19
+ end
20
+
21
+ context 'with string command and arguments' do
22
+ it 'should parse the command' do
23
+ cmd = TCellAgent::Cmdi.parse_command(@env, 'echo', 'test', :unsetenv_others => true)
24
+ expect(cmd).to eq('echo test')
25
+
26
+ cmd = TCellAgent::Cmdi.parse_command(@env, 'echo', 'test', 'one', :unsetenv_others => true)
27
+ expect(cmd).to eq('echo test one')
28
+
29
+ cmd = TCellAgent::Cmdi.parse_command(
30
+ @env,
31
+ 'magick',
32
+ '-size',
33
+ '320x85',
34
+ 'canvas:none',
35
+ '-font',
36
+ 'Bookman-DemiItalic',
37
+ '-draw',
38
+ "\"text 25,60 \'Magick\'\"",
39
+ :unsetenv_others => true
40
+ )
41
+ expect(cmd).to eq(
42
+ "magick -size 320x85 canvas:none -font Bookman-DemiItalic -draw \"text 25,60 'Magick'\""
43
+ )
44
+ end
45
+ end
46
+
47
+ context 'with array command' do
48
+ it 'should parse the command properly' do
49
+ cmd = TCellAgent::Cmdi.parse_command(@env, %w[echo argv0], :unsetenv_others => true)
50
+ expect(cmd).to eq('echo')
51
+ end
52
+ end
53
+
54
+ context 'with array command and arguments' do
55
+ it 'should parse the command properly' do
56
+ cmd = TCellAgent::Cmdi.parse_command(@env, %w[echo argv0], 'test', :unsetenv_others => true)
57
+ expect(cmd).to eq('echo test')
58
+
59
+ cmd = TCellAgent::Cmdi.parse_command(@env, %w[echo argv0], 'test', 'one', :unsetenv_others => true)
60
+ expect(cmd).to eq('echo test one')
61
+
62
+ cmd = TCellAgent::Cmdi.parse_command(
63
+ @env,
64
+ %w[magick argv0],
65
+ '-size',
66
+ '320x85',
67
+ 'canvas:none',
68
+ '-font',
69
+ 'Bookman-DemiItalic',
70
+ '-draw',
71
+ "\"text 25,60 \'Magick\'\"",
72
+ :unsetenv_others => true
73
+ )
74
+ expect(cmd).to eq(
75
+ "magick -size 320x85 canvas:none -font Bookman-DemiItalic -draw \"text 25,60 'Magick'\""
76
+ )
77
+ end
78
+ end
79
+ end
80
+
81
+ context 'without env' do
82
+ context 'with string command' do
83
+ it 'should parse the command properly' do
84
+ cmd = TCellAgent::Cmdi.parse_command('echo')
85
+ expect(cmd).to eq('echo')
86
+
87
+ cmd = TCellAgent::Cmdi.parse_command('echo', :unsetenv_others => true)
88
+ expect(cmd).to eq('echo')
89
+ end
90
+ end
91
+
92
+ context 'with string command and arguments' do
93
+ it 'should parse the command' do
94
+ cmd = TCellAgent::Cmdi.parse_command('echo', 'test', :unsetenv_others => true)
95
+ expect(cmd).to eq('echo test')
96
+
97
+ cmd = TCellAgent::Cmdi.parse_command('echo', 'test', 'one', :unsetenv_others => true)
98
+ expect(cmd).to eq('echo test one')
99
+
100
+ cmd = TCellAgent::Cmdi.parse_command(
101
+ 'magick',
102
+ '-size',
103
+ '320x85',
104
+ 'canvas:none',
105
+ '-font',
106
+ 'Bookman-DemiItalic',
107
+ '-draw',
108
+ "\"text 25,60 \'Magick\'\"",
109
+ :unsetenv_others => true
110
+ )
111
+ expect(cmd).to eq(
112
+ "magick -size 320x85 canvas:none -font Bookman-DemiItalic -draw \"text 25,60 'Magick'\""
113
+ )
114
+ end
115
+ end
116
+
117
+ context 'with array command' do
118
+ it 'should parse the command properly' do
119
+ cmd = TCellAgent::Cmdi.parse_command(%w[echo argv0], :unsetenv_others => true)
120
+ expect(cmd).to eq('echo')
121
+ end
122
+ end
123
+
124
+ context 'with array command and arguments' do
125
+ it 'should parse the command properly' do
126
+ cmd = TCellAgent::Cmdi.parse_command(%w[echo argv0], 'test', :unsetenv_others => true)
127
+ expect(cmd).to eq('echo test')
128
+
129
+ cmd = TCellAgent::Cmdi.parse_command(%w[echo argv0], 'test', 'one', :unsetenv_others => true)
130
+ expect(cmd).to eq('echo test one')
131
+
132
+ cmd = TCellAgent::Cmdi.parse_command(
133
+ %w[magick argv0],
134
+ '-size',
135
+ '320x85',
136
+ 'canvas:none',
137
+ '-font',
138
+ 'Bookman-DemiItalic',
139
+ '-draw',
140
+ "\"text 25,60 \'Magick\'\"",
141
+ :unsetenv_others => true
142
+ )
143
+ expect(cmd).to eq(
144
+ "magick -size 320x85 canvas:none -font Bookman-DemiItalic -draw \"text 25,60 'Magick'\""
145
+ )
146
+ end
147
+ end
148
+ end
149
+ end
150
+ describe '.parse_command_from_open' do
151
+ context 'with empty parameters' do
152
+ it 'should not return a command' do
153
+ cmd = TCellAgent::Cmdi.parse_command_from_open
154
+ expect(cmd).to eq('')
155
+ end
156
+ end
157
+ context 'with empty array' do
158
+ it 'should not return a command' do
159
+ args = []
160
+ cmd = TCellAgent::Cmdi.parse_command_from_open(*args)
161
+ expect(cmd).to eq('')
162
+ end
163
+ end
164
+ context 'with a string command' do
165
+ context 'with an empty string' do
166
+ it 'should return an empty string' do
167
+ cmd = TCellAgent::Cmdi.parse_command_from_open('')
168
+ expect(cmd).to eq('')
169
+ end
170
+ end
171
+ context 'with an empty command' do
172
+ it 'should return an empty string' do
173
+ cmd = TCellAgent::Cmdi.parse_command_from_open('|')
174
+ expect(cmd).to eq('')
175
+ end
176
+ end
177
+ context 'with a non-empty command' do
178
+ it 'should parse the command properly' do
179
+ cmd = TCellAgent::Cmdi.parse_command_from_open('|echo')
180
+ expect(cmd).to eq('echo')
181
+
182
+ cmd = TCellAgent::Cmdi.parse_command_from_open('|ls -l /tmp')
183
+ expect(cmd).to eq('ls -l /tmp')
184
+ end
185
+ end
186
+ end
187
+ context 'with a filename argument' do
188
+ it 'should not return a command' do
189
+ cmd = TCellAgent::Cmdi.parse_command_from_open('/tmp')
190
+ expect(cmd).to eq('')
191
+ end
192
+ end
193
+ context 'with a non-string first argument' do
194
+ it 'should return an empty string' do
195
+ cmd = TCellAgent::Cmdi.parse_command_from_open({})
196
+ expect(cmd).to eq('')
197
+ end
198
+ end
199
+ end
200
+ end
201
+ end