aikido-zen 1.0.1.beta.4-x86_64-linux-musl → 1.0.2.beta.1-x86_64-linux-musl
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 +4 -4
- data/docs/rails.md +49 -5
- data/lib/aikido/zen/config.rb +3 -4
- data/lib/aikido/zen/detached_agent/agent.rb +1 -1
- data/lib/aikido/zen/detached_agent/server.rb +63 -26
- data/lib/aikido/zen/sinks/async_http.rb +40 -42
- data/lib/aikido/zen/sinks/curb.rb +56 -58
- data/lib/aikido/zen/sinks/em_http.rb +27 -29
- data/lib/aikido/zen/sinks/excon.rb +62 -65
- data/lib/aikido/zen/sinks/file.rb +66 -70
- data/lib/aikido/zen/sinks/http.rb +26 -28
- data/lib/aikido/zen/sinks/httpclient.rb +27 -29
- data/lib/aikido/zen/sinks/httpx.rb +27 -29
- data/lib/aikido/zen/sinks/kernel.rb +11 -12
- data/lib/aikido/zen/sinks/mysql2.rb +10 -12
- data/lib/aikido/zen/sinks/net_http.rb +25 -27
- data/lib/aikido/zen/sinks/patron.rb +56 -58
- data/lib/aikido/zen/sinks/pg.rb +23 -25
- data/lib/aikido/zen/sinks/resolv.rb +21 -21
- data/lib/aikido/zen/sinks/socket.rb +10 -12
- data/lib/aikido/zen/sinks/sqlite3.rb +18 -21
- data/lib/aikido/zen/sinks/trilogy.rb +10 -12
- data/lib/aikido/zen/sinks.rb +1 -4
- data/lib/aikido/zen/sinks_dsl.rb +39 -15
- data/lib/aikido/zen/version.rb +1 -1
- data/lib/aikido/zen.rb +7 -2
- metadata +2 -2
@@ -7,13 +7,6 @@ module Aikido::Zen
|
|
7
7
|
module Sinks
|
8
8
|
module Net
|
9
9
|
module HTTP
|
10
|
-
def self.load_sinks!
|
11
|
-
# In stdlib but not always required
|
12
|
-
require "net/http"
|
13
|
-
|
14
|
-
::Net::HTTP.prepend(Net::HTTP::HTTPExtensions)
|
15
|
-
end
|
16
|
-
|
17
10
|
SINK = Sinks.add("net-http", scanners: [
|
18
11
|
Scanners::SSRFScanner,
|
19
12
|
OutboundConnectionMonitor
|
@@ -66,33 +59,38 @@ module Aikido::Zen
|
|
66
59
|
end
|
67
60
|
end
|
68
61
|
|
69
|
-
|
70
|
-
|
62
|
+
def self.load_sinks!
|
63
|
+
# In stdlib but not always required
|
64
|
+
require "net/http"
|
71
65
|
|
72
|
-
|
73
|
-
|
66
|
+
::Net::HTTP.class_eval do
|
67
|
+
extend Sinks::DSL
|
74
68
|
|
75
|
-
|
76
|
-
|
77
|
-
if context
|
78
|
-
prev_request = context["ssrf.request"]
|
79
|
-
context["ssrf.request"] = wrapped_request
|
80
|
-
end
|
69
|
+
sink_around :request do |original_call, req|
|
70
|
+
wrapped_request = Helpers.wrap_request(req, self)
|
81
71
|
|
82
|
-
|
72
|
+
# Store the request information so the DNS sinks can pick it up.
|
73
|
+
context = Aikido::Zen.current_context
|
74
|
+
if context
|
75
|
+
prev_request = context["ssrf.request"]
|
76
|
+
context["ssrf.request"] = wrapped_request
|
77
|
+
end
|
83
78
|
|
84
|
-
|
79
|
+
connection = Helpers.build_outbound(self)
|
85
80
|
|
86
|
-
|
81
|
+
Helpers.scan(wrapped_request, connection, "request")
|
87
82
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
83
|
+
response = original_call.call
|
84
|
+
|
85
|
+
Scanners::SSRFScanner.track_redirects(
|
86
|
+
request: wrapped_request,
|
87
|
+
response: Helpers.wrap_response(response)
|
88
|
+
)
|
92
89
|
|
93
|
-
|
94
|
-
|
95
|
-
|
90
|
+
response
|
91
|
+
ensure
|
92
|
+
context["ssrf.request"] = prev_request if context
|
93
|
+
end
|
96
94
|
end
|
97
95
|
end
|
98
96
|
end
|
@@ -6,14 +6,6 @@ require_relative "../outbound_connection_monitor"
|
|
6
6
|
module Aikido::Zen
|
7
7
|
module Sinks
|
8
8
|
module Patron
|
9
|
-
def self.load_sinks!
|
10
|
-
if Aikido::Zen.satisfy "patron", ">= 0.6.4"
|
11
|
-
require "patron"
|
12
|
-
|
13
|
-
::Patron::Session.prepend(SessionExtensions)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
9
|
SINK = Sinks.add("patron", scanners: [
|
18
10
|
Scanners::SSRFScanner,
|
19
11
|
OutboundConnectionMonitor
|
@@ -44,58 +36,64 @@ module Aikido::Zen
|
|
44
36
|
end
|
45
37
|
end
|
46
38
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
sink_around :handle_request do |super_call, request|
|
51
|
-
wrapped_request = Scanners::SSRFScanner::Request.new(
|
52
|
-
verb: request.action,
|
53
|
-
uri: URI(request.url),
|
54
|
-
headers: request.headers
|
55
|
-
)
|
56
|
-
|
57
|
-
# Store the request information so the DNS sinks can pick it up.
|
58
|
-
context = Aikido::Zen.current_context
|
59
|
-
if context
|
60
|
-
prev_request = context["ssrf.request"]
|
61
|
-
context["ssrf.request"] = wrapped_request
|
62
|
-
end
|
63
|
-
|
64
|
-
connection = OutboundConnection.from_uri(URI(request.url))
|
65
|
-
|
66
|
-
Helpers.scan(wrapped_request, connection, "request")
|
67
|
-
|
68
|
-
response = super_call.call
|
69
|
-
|
70
|
-
Scanners::SSRFScanner.track_redirects(
|
71
|
-
request: wrapped_request,
|
72
|
-
response: Helpers.wrap_response(request, response)
|
73
|
-
)
|
74
|
-
|
75
|
-
# When libcurl has follow_location set, it will handle redirections
|
76
|
-
# internally, and expose the response.url as the URI that was last
|
77
|
-
# requested in the redirect chain.
|
78
|
-
#
|
79
|
-
# In this case, we can't actually stop the request from happening, but
|
80
|
-
# we can scan again (now that we know another request happened), to
|
81
|
-
# stop the response from being exposed to the user. This downgrades
|
82
|
-
# the SSRF into a blind SSRF, which is better than doing nothing.
|
83
|
-
if request.url != response.url && !response.url.to_s.empty?
|
84
|
-
last_effective_request = Scanners::SSRFScanner::Request.new(
|
85
|
-
verb: request.action,
|
86
|
-
uri: URI(response.url),
|
87
|
-
headers: request.headers
|
88
|
-
)
|
89
|
-
context["ssrf.request"] = last_effective_request if context
|
90
|
-
|
91
|
-
connection = OutboundConnection.from_uri(URI(response.url))
|
39
|
+
def self.load_sinks!
|
40
|
+
if Aikido::Zen.satisfy "patron", ">= 0.6.4"
|
41
|
+
require "patron"
|
92
42
|
|
93
|
-
|
43
|
+
::Patron::Session.class_eval do
|
44
|
+
extend Sinks::DSL
|
45
|
+
|
46
|
+
sink_around :handle_request do |original_call, request|
|
47
|
+
wrapped_request = Scanners::SSRFScanner::Request.new(
|
48
|
+
verb: request.action,
|
49
|
+
uri: URI(request.url),
|
50
|
+
headers: request.headers
|
51
|
+
)
|
52
|
+
|
53
|
+
# Store the request information so the DNS sinks can pick it up.
|
54
|
+
context = Aikido::Zen.current_context
|
55
|
+
if context
|
56
|
+
prev_request = context["ssrf.request"]
|
57
|
+
context["ssrf.request"] = wrapped_request
|
58
|
+
end
|
59
|
+
|
60
|
+
connection = OutboundConnection.from_uri(URI(request.url))
|
61
|
+
|
62
|
+
Helpers.scan(wrapped_request, connection, "request")
|
63
|
+
|
64
|
+
response = original_call.call
|
65
|
+
|
66
|
+
Scanners::SSRFScanner.track_redirects(
|
67
|
+
request: wrapped_request,
|
68
|
+
response: Helpers.wrap_response(request, response)
|
69
|
+
)
|
70
|
+
|
71
|
+
# When libcurl has follow_location set, it will handle redirections
|
72
|
+
# internally, and expose the response.url as the URI that was last
|
73
|
+
# requested in the redirect chain.
|
74
|
+
#
|
75
|
+
# In this case, we can't actually stop the request from happening, but
|
76
|
+
# we can scan again (now that we know another request happened), to
|
77
|
+
# stop the response from being exposed to the user. This downgrades
|
78
|
+
# the SSRF into a blind SSRF, which is better than doing nothing.
|
79
|
+
if request.url != response.url && !response.url.to_s.empty?
|
80
|
+
last_effective_request = Scanners::SSRFScanner::Request.new(
|
81
|
+
verb: request.action,
|
82
|
+
uri: URI(response.url),
|
83
|
+
headers: request.headers
|
84
|
+
)
|
85
|
+
context["ssrf.request"] = last_effective_request if context
|
86
|
+
|
87
|
+
connection = OutboundConnection.from_uri(URI(response.url))
|
88
|
+
|
89
|
+
Helpers.scan(last_effective_request, connection, "request")
|
90
|
+
end
|
91
|
+
|
92
|
+
response
|
93
|
+
ensure
|
94
|
+
context["ssrf.request"] = prev_request if context
|
95
|
+
end
|
94
96
|
end
|
95
|
-
|
96
|
-
response
|
97
|
-
ensure
|
98
|
-
context["ssrf.request"] = prev_request if context
|
99
97
|
end
|
100
98
|
end
|
101
99
|
end
|
data/lib/aikido/zen/sinks/pg.rb
CHANGED
@@ -3,14 +3,6 @@
|
|
3
3
|
module Aikido::Zen
|
4
4
|
module Sinks
|
5
5
|
module PG
|
6
|
-
def self.load_sinks!
|
7
|
-
if Aikido::Zen.satisfy "pg", ">= 1.0"
|
8
|
-
require "pg"
|
9
|
-
|
10
|
-
::PG::Connection.prepend(PG::ConnectionExtensions)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
6
|
SINK = Sinks.add("pg", scanners: [Scanners::SQLInjectionScanner])
|
15
7
|
|
16
8
|
module Helpers
|
@@ -43,26 +35,32 @@ module Aikido::Zen
|
|
43
35
|
end
|
44
36
|
end
|
45
37
|
|
46
|
-
|
47
|
-
|
38
|
+
def self.load_sinks!
|
39
|
+
if Aikido::Zen.satisfy "pg", ">= 1.0"
|
40
|
+
require "pg"
|
48
41
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
42
|
+
::PG::Connection.class_eval do
|
43
|
+
extend Sinks::DSL
|
44
|
+
|
45
|
+
%i[
|
46
|
+
send_query exec sync_exec async_exec
|
47
|
+
send_query_params exec_params sync_exec_params async_exec_params
|
48
|
+
].each do |method_name|
|
49
|
+
presafe_sink_before method_name do |query|
|
50
|
+
Helpers.safe do
|
51
|
+
Helpers.scan(query, method_name)
|
52
|
+
end
|
53
|
+
end
|
56
54
|
end
|
57
|
-
end
|
58
|
-
end
|
59
55
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
56
|
+
%i[
|
57
|
+
send_prepare prepare async_prepare sync_prepare
|
58
|
+
].each do |method_name|
|
59
|
+
presafe_sink_before method_name do |_, query|
|
60
|
+
Helpers.safe do
|
61
|
+
Helpers.scan(query, method_name)
|
62
|
+
end
|
63
|
+
end
|
66
64
|
end
|
67
65
|
end
|
68
66
|
end
|
@@ -6,13 +6,6 @@ require_relative "../scanners/ssrf_scanner"
|
|
6
6
|
module Aikido::Zen
|
7
7
|
module Sinks
|
8
8
|
module Resolv
|
9
|
-
def self.load_sinks!
|
10
|
-
# In stdlib but not always required
|
11
|
-
require "resolv"
|
12
|
-
|
13
|
-
::Resolv.prepend(ResolvExtensions)
|
14
|
-
end
|
15
|
-
|
16
9
|
SINK = Sinks.add("resolv", scanners: [
|
17
10
|
Scanners::StoredSSRFScanner,
|
18
11
|
Scanners::SSRFScanner
|
@@ -35,23 +28,30 @@ module Aikido::Zen
|
|
35
28
|
end
|
36
29
|
end
|
37
30
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
# is applicable.
|
31
|
+
def self.load_sinks!
|
32
|
+
# In stdlib but not always required
|
33
|
+
require "resolv"
|
42
34
|
|
43
|
-
|
35
|
+
::Resolv.class_eval do
|
36
|
+
alias_method :each_address__internal_for_aikido_zen, :each_address
|
44
37
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
38
|
+
def each_address(*args, **kwargs, &blk)
|
39
|
+
# each_address is defined "manually" because no sink method pattern
|
40
|
+
# is applicable.
|
41
|
+
|
42
|
+
name, = args
|
43
|
+
|
44
|
+
addresses = []
|
45
|
+
each_address__internal_for_aikido_zen(*args, **kwargs) do |address|
|
46
|
+
addresses << address
|
47
|
+
blk.call(address)
|
48
|
+
end
|
49
|
+
ensure
|
50
|
+
# Ensure partial results are scanned.
|
52
51
|
|
53
|
-
|
54
|
-
|
52
|
+
Sinks::DSL.safe do
|
53
|
+
Helpers.scan(name, addresses, "lookup")
|
54
|
+
end
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
@@ -10,10 +10,6 @@ module Aikido::Zen
|
|
10
10
|
# there's no way to access the internal DNS resolution that happens in C
|
11
11
|
# when using the socket primitives.
|
12
12
|
module Socket
|
13
|
-
def self.load_sinks!
|
14
|
-
::IPSocket.singleton_class.prepend(Socket::IPSocketExtensions)
|
15
|
-
end
|
16
|
-
|
17
13
|
SINK = Sinks.add("socket", scanners: [
|
18
14
|
Scanners::StoredSSRFScanner,
|
19
15
|
Scanners::SSRFScanner
|
@@ -62,15 +58,17 @@ module Aikido::Zen
|
|
62
58
|
end
|
63
59
|
end
|
64
60
|
|
65
|
-
|
66
|
-
|
61
|
+
def self.load_sinks!
|
62
|
+
::IPSocket.singleton_class.class_eval do
|
63
|
+
extend Sinks::DSL
|
67
64
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
65
|
+
sink_after :open do |socket, remote_host|
|
66
|
+
# Code coverage is disabled here because the tests are contrived and
|
67
|
+
# intentionally do not call open.
|
68
|
+
# :nocov:
|
69
|
+
Helpers.scan(remote_host, socket, "open")
|
70
|
+
# :nocov:
|
71
|
+
end
|
74
72
|
end
|
75
73
|
end
|
76
74
|
end
|
@@ -3,15 +3,6 @@
|
|
3
3
|
module Aikido::Zen
|
4
4
|
module Sinks
|
5
5
|
module SQLite3
|
6
|
-
def self.load_sinks!
|
7
|
-
if Aikido::Zen.satisfy "sqlite3", ">= 1.0"
|
8
|
-
require "sqlite3"
|
9
|
-
|
10
|
-
::SQLite3::Database.prepend(DatabaseExtensions)
|
11
|
-
::SQLite3::Statement.prepend(StatementExtensions)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
6
|
SINK = Sinks.add("sqlite3", scanners: [Scanners::SQLInjectionScanner])
|
16
7
|
|
17
8
|
module Helpers
|
@@ -24,22 +15,28 @@ module Aikido::Zen
|
|
24
15
|
end
|
25
16
|
end
|
26
17
|
|
27
|
-
|
28
|
-
|
18
|
+
def self.load_sinks!
|
19
|
+
if Aikido::Zen.satisfy "sqlite3", ">= 1.0"
|
20
|
+
require "sqlite3"
|
29
21
|
|
30
|
-
|
22
|
+
::SQLite3::Database.class_eval do
|
23
|
+
extend Sinks::DSL
|
31
24
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
25
|
+
private
|
26
|
+
|
27
|
+
# SQLite3::Database#exec_batch is an internal native private method.
|
28
|
+
sink_before :exec_batch do |sql|
|
29
|
+
Helpers.scan(sql, "exec_batch")
|
30
|
+
end
|
31
|
+
end
|
37
32
|
|
38
|
-
|
39
|
-
|
33
|
+
::SQLite3::Statement.class_eval do
|
34
|
+
extend Sinks::DSL
|
40
35
|
|
41
|
-
|
42
|
-
|
36
|
+
sink_before :initialize do |_db, sql|
|
37
|
+
Helpers.scan(sql, "statement.execute")
|
38
|
+
end
|
39
|
+
end
|
43
40
|
end
|
44
41
|
end
|
45
42
|
end
|
@@ -3,14 +3,6 @@
|
|
3
3
|
module Aikido::Zen
|
4
4
|
module Sinks
|
5
5
|
module Trilogy
|
6
|
-
def self.load_sinks!
|
7
|
-
if Aikido::Zen.satisfy "trilogy", ">= 2.0"
|
8
|
-
require "trilogy"
|
9
|
-
|
10
|
-
::Trilogy.prepend(TrilogyExtensions)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
6
|
SINK = Sinks.add("trilogy", scanners: [Scanners::SQLInjectionScanner])
|
15
7
|
|
16
8
|
module Helpers
|
@@ -19,11 +11,17 @@ module Aikido::Zen
|
|
19
11
|
end
|
20
12
|
end
|
21
13
|
|
22
|
-
|
23
|
-
|
14
|
+
def self.load_sinks!
|
15
|
+
if Aikido::Zen.satisfy "trilogy", ">= 2.0"
|
16
|
+
require "trilogy"
|
17
|
+
|
18
|
+
::Trilogy.class_eval do
|
19
|
+
extend Sinks::DSL
|
24
20
|
|
25
|
-
|
26
|
-
|
21
|
+
sink_before :query do |query|
|
22
|
+
Helpers.scan(query, "query")
|
23
|
+
end
|
24
|
+
end
|
27
25
|
end
|
28
26
|
end
|
29
27
|
end
|
data/lib/aikido/zen/sinks.rb
CHANGED
@@ -9,10 +9,7 @@ require_relative "sinks_dsl"
|
|
9
9
|
|
10
10
|
require_relative "sinks/action_controller" if defined?(::ActionController)
|
11
11
|
|
12
|
-
|
13
|
-
# Kernel module because how the `prepend` method is applied
|
14
|
-
# (https://stackoverflow.com/questions/78110397/prepend-kernel-module-function-globally#comment137713906_78112924)
|
15
|
-
require_relative "sinks/kernel" if RUBY_VERSION >= "3.0"
|
12
|
+
require_relative "sinks/kernel"
|
16
13
|
|
17
14
|
require_relative "sinks/file"
|
18
15
|
require_relative "sinks/socket"
|
data/lib/aikido/zen/sinks_dsl.rb
CHANGED
@@ -109,10 +109,16 @@ module Aikido::Zen
|
|
109
109
|
#
|
110
110
|
# @return [void]
|
111
111
|
def presafe_sink_before(method_name, &block)
|
112
|
+
raise ArgumentError, "block required" unless block
|
113
|
+
|
114
|
+
original = instance_method(method_name)
|
115
|
+
|
112
116
|
define_method(method_name) do |*args, **kwargs, &blk|
|
113
117
|
instance_exec(*args, **kwargs, &block)
|
114
|
-
|
118
|
+
original.bind_call(self, *args, **kwargs, &blk)
|
115
119
|
end
|
120
|
+
rescue NameError
|
121
|
+
Aikido::Zen.config.logger.warn("cannot wrap method `#{method_name}' for class `#{self}'")
|
116
122
|
end
|
117
123
|
|
118
124
|
# Define a method `method_name` that safely executes the given block before
|
@@ -127,6 +133,8 @@ module Aikido::Zen
|
|
127
133
|
#
|
128
134
|
# @note the block is executed within `safe` to handle errors safely; the original method is executed outside of `safe` to preserve the original behavior
|
129
135
|
def sink_before(method_name, &block)
|
136
|
+
raise ArgumentError, "block required" unless block
|
137
|
+
|
130
138
|
presafe_sink_before(method_name) do |*args, **kwargs|
|
131
139
|
DSL.safe do
|
132
140
|
instance_exec(*args, **kwargs, &block)
|
@@ -145,11 +153,17 @@ module Aikido::Zen
|
|
145
153
|
#
|
146
154
|
# @return [void]
|
147
155
|
def presafe_sink_after(method_name, &block)
|
156
|
+
raise ArgumentError, "block required" unless block
|
157
|
+
|
158
|
+
original = instance_method(method_name)
|
159
|
+
|
148
160
|
define_method(method_name) do |*args, **kwargs, &blk|
|
149
|
-
result =
|
161
|
+
result = original.bind_call(self, *args, **kwargs, &blk)
|
150
162
|
instance_exec(result, *args, **kwargs, &block)
|
151
163
|
result
|
152
164
|
end
|
165
|
+
rescue NameError
|
166
|
+
Aikido::Zen.config.logger.warn("cannot wrap method `#{method_name}' for class `#{self}'")
|
153
167
|
end
|
154
168
|
|
155
169
|
# Define a method `method_name` that safely executes the given block after
|
@@ -165,6 +179,8 @@ module Aikido::Zen
|
|
165
179
|
#
|
166
180
|
# @note the block is executed within `safe` to handle errors safely; the original method is executed outside of `safe` to preserve the original behavior
|
167
181
|
def sink_after(method_name, &block)
|
182
|
+
raise ArgumentError, "block required" unless block
|
183
|
+
|
168
184
|
presafe_sink_after(method_name) do |result, *args, **kwargs|
|
169
185
|
DSL.safe do
|
170
186
|
instance_exec(result, *args, **kwargs, &block)
|
@@ -177,20 +193,26 @@ module Aikido::Zen
|
|
177
193
|
#
|
178
194
|
# @param method_name [Symbol, String] the name of the method to define
|
179
195
|
# @yield the block to execute around the original method
|
180
|
-
# @yieldparam
|
196
|
+
# @yieldparam original_call [Proc] the proc that calls the original method
|
181
197
|
# @yieldparam args [Array] the positional arguments passed to the original method
|
182
198
|
# @yieldparam kwargs [Hash] the keyword arguments passed to the original method
|
183
199
|
#
|
184
200
|
# @return [void]
|
185
201
|
def presafe_sink_around(method_name, &block)
|
202
|
+
raise ArgumentError, "block required" unless block
|
203
|
+
|
204
|
+
original = instance_method(method_name)
|
205
|
+
|
186
206
|
define_method(method_name) do |*args, **kwargs, &blk|
|
187
207
|
result = nil
|
188
|
-
|
189
|
-
result =
|
208
|
+
original_call = proc do
|
209
|
+
result = original.bind_call(self, *args, **kwargs, &blk)
|
190
210
|
end
|
191
|
-
instance_exec(
|
211
|
+
instance_exec(original_call, *args, **kwargs, &block)
|
192
212
|
result
|
193
213
|
end
|
214
|
+
rescue NameError
|
215
|
+
Aikido::Zen.config.logger.warn("cannot wrap method `#{method_name}' for class `#{self}'")
|
194
216
|
end
|
195
217
|
|
196
218
|
# Define a method `method_name` that safely executes the given block around
|
@@ -198,27 +220,29 @@ module Aikido::Zen
|
|
198
220
|
#
|
199
221
|
# @param method_name [Symbol, String] the name of the method to define
|
200
222
|
# @yield the block to execute around the original method
|
201
|
-
# @yieldparam
|
223
|
+
# @yieldparam original_call [Proc] the proc that calls the original method
|
202
224
|
# @yieldparam args [Array] the positional arguments passed to the original method
|
203
225
|
# @yieldparam kwargs [Hash] the keyword arguments passed to the original method
|
204
226
|
#
|
205
227
|
# @return [void]
|
206
228
|
#
|
207
229
|
# @note the block is executed within `safe` to handle errors safely; the original method is executed within `presafe` to preserve the original behavior
|
208
|
-
# @note if the block does not call `
|
230
|
+
# @note if the block does not call `original_call`, the original method is called automatically after the block is executed
|
209
231
|
def sink_around(method_name, &block)
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
232
|
+
raise ArgumentError, "block required" unless block
|
233
|
+
|
234
|
+
presafe_sink_around(method_name) do |presafe_original_call, *args, **kwargs|
|
235
|
+
original_called = false
|
236
|
+
original_call = proc do
|
237
|
+
original_called = true
|
214
238
|
DSL.presafe do
|
215
|
-
|
239
|
+
presafe_original_call.call
|
216
240
|
end
|
217
241
|
end
|
218
242
|
DSL.safe do
|
219
|
-
instance_exec(
|
243
|
+
instance_exec(original_call, *args, **kwargs, &block)
|
220
244
|
end
|
221
|
-
|
245
|
+
presafe_original_call.call unless original_called
|
222
246
|
end
|
223
247
|
end
|
224
248
|
end
|
data/lib/aikido/zen/version.rb
CHANGED
data/lib/aikido/zen.rb
CHANGED
@@ -39,7 +39,7 @@ module Aikido
|
|
39
39
|
return unless config.protect?
|
40
40
|
|
41
41
|
unless load_sources! && load_sinks!
|
42
|
-
config.logger.warn
|
42
|
+
config.logger.warn("Zen could not find any supported libraries or frameworks. Visit https://github.com/AikidoSec/firewall-ruby for more information.")
|
43
43
|
return
|
44
44
|
end
|
45
45
|
|
@@ -165,6 +165,11 @@ module Aikido
|
|
165
165
|
end
|
166
166
|
end
|
167
167
|
|
168
|
+
# Align with other Zen implementations, while keeping internal consistency.
|
169
|
+
class << self
|
170
|
+
alias_method :set_user, :track_user
|
171
|
+
end
|
172
|
+
|
168
173
|
# Marks that the Zen middleware was installed properly
|
169
174
|
# @return void
|
170
175
|
def self.middleware_installed!
|
@@ -209,7 +214,7 @@ module Aikido
|
|
209
214
|
end
|
210
215
|
|
211
216
|
def self.detached_agent_server
|
212
|
-
@detached_agent_server ||= DetachedAgent::Server.start
|
217
|
+
@detached_agent_server ||= DetachedAgent::Server.start
|
213
218
|
end
|
214
219
|
|
215
220
|
class << self
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aikido-zen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2.beta.1
|
5
5
|
platform: x86_64-linux-musl
|
6
6
|
authors:
|
7
7
|
- Aikido Security
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-08-
|
11
|
+
date: 2025-08-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|