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 +4 -4
- data/lib/sqreen.rb +4 -0
- data/lib/sqreen/frameworks/generic.rb +26 -0
- data/lib/sqreen/js/execjs_adapter.rb +50 -2
- data/lib/sqreen/js/js_service.rb +2 -2
- data/lib/sqreen/js/mini_racer_adapter.rb +20 -1
- data/lib/sqreen/performance_notifications/binned_metrics.rb +2 -0
- data/lib/sqreen/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e50a974c4a6de258f73e1f7a99ad000a87a9a78a3a439211cba1aceaa08d44c
|
4
|
+
data.tar.gz: b2b6d9f85d26270b242febf553ae0311ecb923faa36ea840e03e5dc747f7c1b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 22f29bcd92e5f4a0e91422ec1490b8e3c32f9f0254d0fdaf1337a3b3a0f1f1b664b5e079449b382b722b0209acecf80d6677b9d6f7232c5985b34f567aaf94ca
|
7
|
+
data.tar.gz: a52c91b15cd6d5c56e8167b2ca05f1fa65aa929b43671bbbfe54d0047f536750d8500ed69c76671958f224253c741ce2069b1adb59d875ff428ede4f2c760116
|
data/lib/sqreen.rb
CHANGED
@@ -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(
|
7
|
-
|
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
|
data/lib/sqreen/js/js_service.rb
CHANGED
@@ -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, #{
|
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
|
data/lib/sqreen/version.rb
CHANGED
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.
|
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-
|
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.
|
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.
|
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
|