sqreen 1.14.1 → 1.14.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: a44b9da6464b0a61db469f75d4b2ff4409aaa60c994c5770b30067c374fbf5c4
4
- data.tar.gz: c8f6c266dc33f646c647dd614706acc496c8140325fc03b1401f1d0151750cdf
3
+ metadata.gz: 1e50a974c4a6de258f73e1f7a99ad000a87a9a78a3a439211cba1aceaa08d44c
4
+ data.tar.gz: b2b6d9f85d26270b242febf553ae0311ecb923faa36ea840e03e5dc747f7c1b8
5
5
  SHA512:
6
- metadata.gz: e610db595536d1370a6f4c56da23dc2144332fba297f65b1e64187d53a535857e9bb6769fd4653f8fe18d866fa2b96d93641f02d51c067ca0012bcfe9820029d
7
- data.tar.gz: 618f2a1454edab5fe1df062506c3cdb766e32579ae7874fb47f938e53d326a463415b7729c275aded79f2cb073b1c7b13c1af6f4ed6c628b496445d6bd7cdd65
6
+ metadata.gz: 22f29bcd92e5f4a0e91422ec1490b8e3c32f9f0254d0fdaf1337a3b3a0f1f1b664b5e079449b382b722b0209acecf80d6677b9d6f7232c5985b34f567aaf94ca
7
+ data.tar.gz: a52c91b15cd6d5c56e8167b2ca05f1fa65aa929b43671bbbfe54d0047f536750d8500ed69c76671958f224253c741ce2069b1adb59d875ff428ede4f2c760116
@@ -17,6 +17,10 @@ require 'thread'
17
17
  # Auto start the instrumentation.
18
18
 
19
19
  Sqreen.framework.on_start do |framework|
20
+ if RUBY_VERSION =~ /\A2\.5\.[01]\z/ && Sqreen.framework.on_pre_fork_preload?
21
+ STDERR.puts("Avoiding launching sqreen thread pre-fork") # sqreen log unavailable
22
+ next
23
+ end
20
24
  Thread.new do
21
25
  begin
22
26
  runner = nil
@@ -422,6 +422,15 @@ module Sqreen
422
422
  end
423
423
  end
424
424
 
425
+ def on_pre_fork_preload?
426
+ # unlike with worker_fork_detection, we can't be instrument Puma::Cluster
427
+ # in time for intercepting run
428
+ stack = Kernel.caller_locations
429
+
430
+ puma_preload?(stack) || unicorn_preload?(stack)
431
+ end
432
+
433
+
425
434
  protected
426
435
 
427
436
  # Is this a whitelisted path?
@@ -519,6 +528,7 @@ module Sqreen
519
528
  Sqreen.log.warn "Failed ignoring AttackBlocked on NewRelic: #{e.inspect}"
520
529
  end
521
530
 
531
+ # if it doesn't detect the fork it's not a problem
522
532
  def worker_fork_detection
523
533
  # only Puma currently supported
524
534
  return unless defined?(Puma::Cluster) && Puma::Cluster.instance_methods.include?(:worker)
@@ -533,6 +543,22 @@ module Sqreen
533
543
 
534
544
  private
535
545
 
546
+ def puma_preload?(stack)
547
+ cluster_run = stack.each_with_index.find { |b, _i| b.path =~ /puma\/cluster\.rb\z/ && b.label == 'run' }
548
+ return false unless cluster_run
549
+ frame_atop = stack[cluster_run[1] - 1]
550
+ frame_atop.label == 'load_and_bind'
551
+ end
552
+
553
+ def unicorn_preload?(stack)
554
+ build_app = stack.each_with_index.find do |b, _i|
555
+ b.path =~ /unicorn\/http_server\.rb\z/ && b.label == 'build_app!'
556
+ end
557
+ return false unless build_app
558
+ frame_below = stack[build_app[1] + 1]
559
+ frame_below.label == 'start'
560
+ end
561
+
536
562
  def split_ip_addresses(ip_addresses)
537
563
  ip_addresses ? ip_addresses.strip.split(/[,\s]+/) : []
538
564
  end
@@ -1,15 +1,26 @@
1
1
  require 'execjs'
2
+ require 'weakref'
2
3
 
3
4
  module Sqreen
4
5
  module Js
5
6
  class ExecjsAdapter < JsServiceAdapter
6
- def preprocess(_rule_name, code)
7
- ExecJsRunnable.new(ExecJS.compile(code))
7
+ def preprocess(rule_name, code)
8
+ if thread_safe?
9
+ ExecJsRunnable.new(ExecJS.compile(code))
10
+ else
11
+ ThreadLocalExecJsRunnable.new(code)
12
+ end
8
13
  end
9
14
 
10
15
  def variant_name
11
16
  ExecJS.runtime.name + ' (ExecJS)'
12
17
  end
18
+
19
+ private
20
+
21
+ def thread_safe?
22
+ ExecJS.runtime.name != 'therubyrhino (Rhino)'
23
+ end
13
24
  end
14
25
 
15
26
  class ExecJsRunnable < ExecutableJs
@@ -21,5 +32,42 @@ module Sqreen
21
32
  @compiled.call(cbname, *arguments)
22
33
  end
23
34
  end
35
+
36
+ class ThreadLocalExecJsRunnable < ExecutableJs
37
+ def initialize(code)
38
+ @code = code
39
+ @tl_key = "SQREEN_EXECJS_CONTEXT_#{object_id}".freeze
40
+ @runtimes = [] # place where to keep strong references
41
+ @runtimes_mutex = Mutex.new
42
+ end
43
+
44
+ def run_js_cb(cbname, _budget, arguments)
45
+ tl_exec_js_runnable.call(cbname, *arguments)
46
+ end
47
+
48
+ def with_runtimes_mutex
49
+ @runtimes_mutex.synchronize { yield }
50
+ end
51
+
52
+ private
53
+
54
+ def dispose_from_dead_threads
55
+ with_runtimes_mutex do
56
+ @runtimes.delete_if { |th, _runtime| !th.alive? }
57
+ end
58
+ end
59
+
60
+ def tl_exec_js_runnable
61
+ runnable = Thread.current[@tl_key]
62
+ return runnable if runnable && runnable.weakref_alive?
63
+
64
+ dispose_from_dead_threads
65
+ runtime = ExecJS.compile(@code)
66
+ with_runtimes_mutex do
67
+ @runtimes << [Thread.current, runtime]
68
+ end
69
+ Thread.current[@tl_key] = WeakRef.new(runtime)
70
+ end
71
+ end
24
72
  end
25
73
  end
@@ -5,7 +5,7 @@ module Sqreen
5
5
  # start public interface
6
6
 
7
7
  class JsService
8
- include Singleton
8
+ include ::Singleton
9
9
 
10
10
  def initialize
11
11
  detect_adapter
@@ -75,7 +75,7 @@ module Sqreen
75
75
  # end public interface
76
76
 
77
77
  class JsServiceAdapter
78
- def preprocess(code)
78
+ def preprocess(rule_name, code)
79
79
  raise Sqreen::NotImplementedYet
80
80
  end
81
81
 
@@ -1,4 +1,5 @@
1
1
  require 'weakref'
2
+ require 'sqreen/runner' # for Sqreen.on_forked_worker?
2
3
 
3
4
  module Sqreen
4
5
  module Js
@@ -63,8 +64,9 @@ module Sqreen
63
64
 
64
65
  mini_racer_context[:c] += 1
65
66
  begin
67
+ json_args = "[#{arguments.map(&method(:fixup_bad_encoding)).map(&:to_json).join(',')}]"
66
68
  mini_racer_context[:r].eval_unsafe(
67
- "#{cb_name}.apply(this, #{::JSON.generate(arguments)})", nil, budget)
69
+ "#{cb_name}.apply(this, #{json_args})", nil, budget)
68
70
  rescue @module::ScriptTerminatedError
69
71
  nil
70
72
  end
@@ -72,6 +74,23 @@ module Sqreen
72
74
 
73
75
  private
74
76
 
77
+ def fixup_bad_encoding(arg)
78
+ # NOTE: we don't fix encoding problems in deeper structures
79
+ return arg unless arg.is_a?(String)
80
+ unless arg.valid_encoding?
81
+ return arg.dup.force_encoding(Encoding::ISO_8859_1)
82
+ end
83
+
84
+ # encoding is valid if it reaches this point
85
+ return arg if arg.encoding == Encoding::UTF_8
86
+
87
+ begin
88
+ arg.encode(Encoding::UTF_8)
89
+ rescue Encoding::UndefinedConversionError
90
+ arg.dup.force_encoding(Encoding::ISO_8859_1)
91
+ end
92
+ end
93
+
75
94
  def snapshot
76
95
  @snapshot ||= @module::Snapshot.new(@source)
77
96
  end
@@ -58,6 +58,8 @@ module Sqreen
58
58
 
59
59
  finish_time = SQREEN_MONO_TIME ? Time.now.utc : finish
60
60
  time_millis = (finish - start) * 1000
61
+ # Ensure we always have a timings if we somehow missed the request start
62
+ SharedStorage[:sqreen_request_time] ||= 0
61
63
  SharedStorage[:sqreen_request_time] += time_millis
62
64
  metrics_store.update(metric_name, finish_time, nil, time_millis)
63
65
  end
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
2
  # Please refer to our terms for more information: https://www.sqreen.io/terms.html
3
3
  module Sqreen
4
- VERSION = '1.14.1'.freeze
4
+ VERSION = '1.14.2'.freeze
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sqreen
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.14.1
4
+ version: 1.14.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sqreen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-21 00:00:00.000000000 Z
11
+ date: 2018-10-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sq_mini_racer
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.2.0.beta3
19
+ version: 0.2.2.sqreen1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.2.0.beta3
26
+ version: 0.2.2.sqreen1
27
27
  description: Sqreen is a SaaS based Application protection and monitoring platform
28
28
  that integrates directly into your Ruby applications. Learn more at https://sqreen.io.
29
29
  email: contact@sqreen.io