aikido-zen 1.0.2.beta.5-arm64-linux-musl → 1.0.2.beta.6-arm64-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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.simplecov +6 -0
  3. data/README.md +1 -0
  4. data/benchmarks/README.md +0 -1
  5. data/benchmarks/rails7.1_benchmark.js +1 -0
  6. data/benchmarks/rails7.1_sql_injection.js +52 -20
  7. data/docs/rails.md +5 -7
  8. data/lib/aikido/zen/actor.rb +34 -4
  9. data/lib/aikido/zen/agent/heartbeats_manager.rb +5 -5
  10. data/lib/aikido/zen/agent.rb +17 -15
  11. data/lib/aikido/zen/collector/event.rb +209 -0
  12. data/lib/aikido/zen/collector/routes.rb +13 -8
  13. data/lib/aikido/zen/collector/stats.rb +16 -19
  14. data/lib/aikido/zen/collector/users.rb +3 -1
  15. data/lib/aikido/zen/collector.rb +94 -29
  16. data/lib/aikido/zen/config.rb +4 -10
  17. data/lib/aikido/zen/context.rb +8 -7
  18. data/lib/aikido/zen/detached_agent/agent.rb +28 -27
  19. data/lib/aikido/zen/detached_agent/front_object.rb +10 -6
  20. data/lib/aikido/zen/internals.rb +23 -3
  21. data/lib/aikido/zen/libzen-v0.1.48-arm64-linux-musl.so +0 -0
  22. data/lib/aikido/zen/middleware/fork_detector.rb +23 -0
  23. data/lib/aikido/zen/middleware/request_tracker.rb +1 -1
  24. data/lib/aikido/zen/outbound_connection.rb +7 -0
  25. data/lib/aikido/zen/rails_engine.rb +2 -6
  26. data/lib/aikido/zen/route.rb +7 -0
  27. data/lib/aikido/zen/runtime_settings.rb +1 -1
  28. data/lib/aikido/zen/scanners/path_traversal/helpers.rb +10 -7
  29. data/lib/aikido/zen/scanners/path_traversal_scanner.rb +2 -2
  30. data/lib/aikido/zen/sink.rb +1 -1
  31. data/lib/aikido/zen/sinks/file.rb +43 -4
  32. data/lib/aikido/zen/sinks/kernel.rb +1 -1
  33. data/lib/aikido/zen/version.rb +2 -2
  34. data/lib/aikido/zen.rb +8 -9
  35. metadata +6 -3
  36. data/lib/aikido/zen/libzen-v0.1.39-arm64-linux-musl.so +0 -0
@@ -4,7 +4,8 @@ module Aikido::Zen
4
4
  module Scanners
5
5
  module PathTraversal
6
6
  DANGEROUS_PATH_PARTS = ["../", "..\\"]
7
- LINUX_ROOT_FOLDERS = [
7
+
8
+ LINUX_PATH_STARTS = [
8
9
  "/bin/",
9
10
  "/boot/",
10
11
  "/dev/",
@@ -26,10 +27,12 @@ module Aikido::Zen
26
27
  "/var/"
27
28
  ]
28
29
 
29
- DANGEROUS_PATH_STARTS = LINUX_ROOT_FOLDERS + ["c:/", "c:\\"]
30
+ WINDOWS_PATH_STARTS = ["c:/", "c:\\"]
31
+
32
+ DANGEROUS_PATH_STARTS = LINUX_PATH_STARTS + WINDOWS_PATH_STARTS
30
33
 
31
34
  module Helpers
32
- def self.contains_unsafe_path_parts(filepath)
35
+ def self.include_unsafe_path_parts?(filepath)
33
36
  DANGEROUS_PATH_PARTS.each do |dangerous_part|
34
37
  return true if filepath.include?(dangerous_part)
35
38
  end
@@ -37,7 +40,7 @@ module Aikido::Zen
37
40
  false
38
41
  end
39
42
 
40
- def self.starts_with_unsafe_path(filepath, user_input)
43
+ def self.start_with_unsafe_path?(filepath, user_input)
41
44
  # Check if path is relative (not absolute or drive letter path)
42
45
  # Required because `expand_path` will build absolute paths from relative paths
43
46
  return false if Pathname.new(filepath).relative? || Pathname.new(user_input).relative?
@@ -51,12 +54,12 @@ module Aikido::Zen
51
54
  # to prevent false positives.
52
55
  # e.g., if user input is /etc/ and the path is /etc/passwd, we don't want to flag it,
53
56
  # as long as the user input does not contain a subdirectory or filename
54
- if user_input == dangerous_start || user_input == dangerous_start.chomp("/")
55
- return false
56
- end
57
+ return false if user_input == dangerous_start || user_input == dangerous_start.chomp("/")
58
+
57
59
  return true
58
60
  end
59
61
  end
62
+
60
63
  false
61
64
  end
62
65
  end
@@ -51,12 +51,12 @@ module Aikido::Zen
51
51
  # We ignore cases where the user input is not part of the file path.
52
52
  return false unless @filepath.include?(@input)
53
53
 
54
- if PathTraversal::Helpers.contains_unsafe_path_parts(@filepath) && PathTraversal::Helpers.contains_unsafe_path_parts(@input)
54
+ if PathTraversal::Helpers.include_unsafe_path_parts?(@filepath) && PathTraversal::Helpers.include_unsafe_path_parts?(@input)
55
55
  return true
56
56
  end
57
57
 
58
58
  # Check for absolute path traversal
59
- PathTraversal::Helpers.starts_with_unsafe_path(@filepath, @input)
59
+ PathTraversal::Helpers.start_with_unsafe_path?(@filepath, @input)
60
60
  end
61
61
  end
62
62
  end
@@ -4,7 +4,7 @@ require_relative "scan"
4
4
 
5
5
  module Aikido::Zen
6
6
  module Sinks
7
- # @api internal
7
+ # @api private
8
8
  # @return [Hash<String, Sink>]
9
9
  def self.registry
10
10
  @registry ||= {}
@@ -18,11 +18,12 @@ module Aikido::Zen
18
18
  ::File.singleton_class.class_eval do
19
19
  extend Sinks::DSL
20
20
 
21
- # Create a copy of the original method for internal use only to prevent
21
+ # Create a copy of the original methods for internal use only to prevent
22
22
  # recursion in PathTraversalScanner.
23
23
  #
24
- # IMPORTANT: The alias must be created before the method is overridden.
24
+ # IMPORTANT: The aliases must be created before the method is overridden.
25
25
  alias_method :expand_path__internal_for_aikido_zen, :expand_path
26
+ alias_method :join__internal_for_aikido_zen, :join
26
27
 
27
28
  sink_before :open do |path|
28
29
  Helpers.scan(path, "open")
@@ -80,8 +81,46 @@ module Aikido::Zen
80
81
  end
81
82
  end
82
83
 
83
- sink_after :join do |result|
84
- Helpers.scan(result, "join")
84
+ def join(*args, **kwargs, &blk)
85
+ # IMPORTANT: THE BEHAVIOR OF THIS METHOD IS CHANGED!
86
+ #
87
+ # File.join has undocumented behavior:
88
+ #
89
+ # File.join recursively joins nested string arrays.
90
+ #
91
+ # This prevents path traversal detection when an array originates
92
+ # from user input that was assumed to be a string.
93
+ #
94
+ # This undocumented behavior has been restricted to support path
95
+ # traversal detection.
96
+ #
97
+ # File.join no longer joins nested string arrays, but still accepts
98
+ # a single string array argument.
99
+
100
+ # File.join is often incorrectly called with a single array argument.
101
+ #
102
+ # i.e.
103
+ #
104
+ # File.join(["prefix", "filename"])
105
+ #
106
+ # This is considered acceptable.
107
+ #
108
+ # Calling File.join with a single string argument returns the string
109
+ # argument itself, having no practical effect. Therefore, it can be
110
+ # presumed that if File.join is called with a single array argument
111
+ # then this was its intended usage, and the array did not originate
112
+ # from user input that was assumed to be a string.
113
+ strings = args
114
+ strings = args.first if args.size == 1 && args.first.is_a?(Array)
115
+ strings.each do |string|
116
+ raise TypeError.new("Zen prevented implicit conversion of Array to String") if string.is_a?(Array)
117
+ end
118
+
119
+ result = join__internal_for_aikido_zen(*args, **kwargs, &blk)
120
+ Sinks::DSL.safe do
121
+ Helpers.scan(result, "join")
122
+ end
123
+ result
85
124
  end
86
125
 
87
126
  sink_before :expand_path do |file_name|
@@ -16,7 +16,7 @@ module Aikido::Zen
16
16
  klass.class_eval do
17
17
  extend Sinks::DSL
18
18
 
19
- %i[system spawn].each do |method_name|
19
+ %i[system spawn `].each do |method_name|
20
20
  sink_before method_name do |*args|
21
21
  # Remove the optional environment argument before the command-line.
22
22
  args.shift if args.first.is_a?(Hash)
@@ -2,9 +2,9 @@
2
2
 
3
3
  module Aikido
4
4
  module Zen
5
- VERSION = "1.0.2.beta.5"
5
+ VERSION = "1.0.2.beta.6"
6
6
 
7
7
  # The version of libzen_internals that we build against.
8
- LIBZEN_VERSION = "0.1.39"
8
+ LIBZEN_VERSION = "0.1.48"
9
9
  end
10
10
  end
data/lib/aikido/zen.rb CHANGED
@@ -11,10 +11,11 @@ require_relative "zen/agent"
11
11
  require_relative "zen/api_client"
12
12
  require_relative "zen/context"
13
13
  require_relative "zen/detached_agent"
14
- require_relative "zen/middleware/check_allowed_addresses"
15
14
  require_relative "zen/middleware/middleware"
16
- require_relative "zen/middleware/request_tracker"
15
+ require_relative "zen/middleware/fork_detector"
17
16
  require_relative "zen/middleware/set_context"
17
+ require_relative "zen/middleware/check_allowed_addresses"
18
+ require_relative "zen/middleware/request_tracker"
18
19
  require_relative "zen/outbound_connection"
19
20
  require_relative "zen/outbound_connection_monitor"
20
21
  require_relative "zen/runtime_settings"
@@ -36,8 +37,6 @@ module Aikido
36
37
  return
37
38
  end
38
39
 
39
- return unless config.protect?
40
-
41
40
  unless load_sources! && load_sinks!
42
41
  config.logger.warn("Zen could not find any supported libraries or frameworks. Visit https://github.com/AikidoSec/firewall-ruby for more information.")
43
42
  return
@@ -87,12 +86,10 @@ module Aikido
87
86
  # Manages runtime metrics extracted from your app, which are uploaded to the
88
87
  # Aikido servers if configured to do so.
89
88
  def self.collector
90
- check_and_handle_fork
91
89
  @collector ||= Collector.new
92
90
  end
93
91
 
94
92
  def self.detached_agent
95
- check_and_handle_fork
96
93
  @detached_agent ||= DetachedAgent::Agent.new
97
94
  end
98
95
 
@@ -231,9 +228,7 @@ module Aikido
231
228
  end
232
229
 
233
230
  def check_and_handle_fork
234
- if has_forked
235
- @detached_agent&.handle_fork
236
- end
231
+ handle_fork if has_forked
237
232
  end
238
233
 
239
234
  def has_forked
@@ -241,6 +236,10 @@ module Aikido
241
236
  @pid = Process.pid
242
237
  pid_changed
243
238
  end
239
+
240
+ def handle_fork
241
+ @detached_agent&.handle_fork
242
+ end
244
243
  end
245
244
  end
246
245
  end
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.2.beta.5
4
+ version: 1.0.2.beta.6
5
5
  platform: arm64-linux-musl
6
6
  authors:
7
7
  - Aikido Security
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-09-09 00:00:00.000000000 Z
11
+ date: 2025-10-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -71,6 +71,7 @@ files:
71
71
  - README.md
72
72
  - Rakefile
73
73
  - benchmarks/README.md
74
+ - benchmarks/rails7.1_benchmark.js
74
75
  - benchmarks/rails7.1_sql_injection.js
75
76
  - docs/banner.svg
76
77
  - docs/config.md
@@ -86,6 +87,7 @@ files:
86
87
  - lib/aikido/zen/background_worker.rb
87
88
  - lib/aikido/zen/capped_collections.rb
88
89
  - lib/aikido/zen/collector.rb
90
+ - lib/aikido/zen/collector/event.rb
89
91
  - lib/aikido/zen/collector/hosts.rb
90
92
  - lib/aikido/zen/collector/routes.rb
91
93
  - lib/aikido/zen/collector/sink_stats.rb
@@ -102,8 +104,9 @@ files:
102
104
  - lib/aikido/zen/errors.rb
103
105
  - lib/aikido/zen/event.rb
104
106
  - lib/aikido/zen/internals.rb
105
- - lib/aikido/zen/libzen-v0.1.39-arm64-linux-musl.so
107
+ - lib/aikido/zen/libzen-v0.1.48-arm64-linux-musl.so
106
108
  - lib/aikido/zen/middleware/check_allowed_addresses.rb
109
+ - lib/aikido/zen/middleware/fork_detector.rb
107
110
  - lib/aikido/zen/middleware/middleware.rb
108
111
  - lib/aikido/zen/middleware/rack_throttler.rb
109
112
  - lib/aikido/zen/middleware/request_tracker.rb