aikido-zen 1.0.0.pre.beta.1 → 1.0.1.beta.2

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/.aikido +6 -0
  3. data/README.md +67 -83
  4. data/lib/aikido/zen/config.rb +11 -2
  5. data/lib/aikido/zen/context.rb +4 -0
  6. data/lib/aikido/zen/internals.rb +41 -7
  7. data/lib/aikido/zen/middleware/request_tracker.rb +6 -4
  8. data/lib/aikido/zen/rails_engine.rb +5 -9
  9. data/lib/aikido/zen/request/heuristic_router.rb +6 -0
  10. data/lib/aikido/zen/sink.rb +5 -0
  11. data/lib/aikido/zen/sinks/async_http.rb +35 -16
  12. data/lib/aikido/zen/sinks/curb.rb +52 -26
  13. data/lib/aikido/zen/sinks/em_http.rb +39 -25
  14. data/lib/aikido/zen/sinks/excon.rb +63 -45
  15. data/lib/aikido/zen/sinks/file.rb +67 -71
  16. data/lib/aikido/zen/sinks/http.rb +38 -19
  17. data/lib/aikido/zen/sinks/httpclient.rb +51 -22
  18. data/lib/aikido/zen/sinks/httpx.rb +37 -18
  19. data/lib/aikido/zen/sinks/kernel.rb +18 -57
  20. data/lib/aikido/zen/sinks/mysql2.rb +19 -7
  21. data/lib/aikido/zen/sinks/net_http.rb +37 -19
  22. data/lib/aikido/zen/sinks/patron.rb +41 -24
  23. data/lib/aikido/zen/sinks/pg.rb +50 -27
  24. data/lib/aikido/zen/sinks/resolv.rb +37 -16
  25. data/lib/aikido/zen/sinks/socket.rb +33 -17
  26. data/lib/aikido/zen/sinks/sqlite3.rb +31 -12
  27. data/lib/aikido/zen/sinks/trilogy.rb +19 -7
  28. data/lib/aikido/zen/sinks.rb +29 -20
  29. data/lib/aikido/zen/sinks_dsl.rb +226 -0
  30. data/lib/aikido/zen/version.rb +2 -2
  31. data/lib/aikido/zen.rb +18 -1
  32. data/placeholder/.gitignore +4 -0
  33. data/placeholder/README.md +11 -0
  34. data/placeholder/Rakefile +75 -0
  35. data/placeholder/lib/placeholder.rb.template +3 -0
  36. data/placeholder/placeholder.gemspec.template +20 -0
  37. data/tasklib/libzen.rake +70 -66
  38. metadata +16 -12
  39. data/CHANGELOG.md +0 -25
  40. data/lib/aikido.rb +0 -3
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rake"
4
+ require "rake/clean"
5
+ require "rubygems/package"
6
+ require "fileutils"
7
+
8
+ GEM_NAMES = %w[aikido]
9
+
10
+ # Clean up created files
11
+ CLEAN.include("LICENSE")
12
+ CLEAN.include(*GEM_NAMES.map { |name| "#{name}.gemspec" })
13
+ CLEAN.include(*GEM_NAMES.map { |name| "lib/#{name}.rb" })
14
+ CLOBBER.include(*GEM_NAMES.map { |name| "#{name}-*.gem" })
15
+
16
+ namespace :build do
17
+ GEM_NAMES.each do |gem_name|
18
+ file "LICENSE" => ["../LICENSE"] do
19
+ FileUtils.cp("../LICENSE", "LICENSE")
20
+ puts "Copied LICENSE"
21
+ end
22
+
23
+ entry_point_path = "lib/#{gem_name}.rb"
24
+
25
+ # Generate the entry point file from template if needed
26
+ file entry_point_path => ["lib/placeholder.rb.template"] do
27
+ template = File.read("lib/placeholder.rb.template")
28
+ content = template.gsub("@GEM_NAME", gem_name)
29
+ File.write(entry_point_path, content)
30
+ puts "Generated #{entry_point_path}"
31
+ end
32
+
33
+ gemspec_path = "#{gem_name}.gemspec"
34
+
35
+ # Generate gemspec file from template if needed
36
+ file gemspec_path => ["placeholder.gemspec.template"] do
37
+ template = File.read("placeholder.gemspec.template")
38
+ content = template.gsub("@GEM_NAME", gem_name)
39
+ File.write(gemspec_path, content)
40
+ puts "Generated #{gemspec_path}"
41
+ end
42
+
43
+ desc "Build the #{gem_name} gem"
44
+ task gem_name => [entry_point_path, gemspec_path, "LICENSE"] do
45
+ gemspec = Gem::Specification.load(gemspec_path)
46
+ raise "Failed to load gemspec: #{gemspec_path}" unless gemspec
47
+
48
+ gem_path = Gem::Package.build(gemspec)
49
+ puts "Built #{gem_path}"
50
+ end
51
+ end
52
+
53
+ desc "Build all gems"
54
+ task all: GEM_NAMES.map { |gem_name| "build:#{gem_name}" }
55
+ end
56
+
57
+ namespace :release do
58
+ GEM_NAMES.each do |gem_name|
59
+ gemspec_path = "#{gem_name}.gemspec"
60
+
61
+ desc "Build and publish the #{gem_name} to RubyGems"
62
+ task gem_name => ["build:#{gem_name}"] do
63
+ gemspec = Gem::Specification.load(gemspec_path)
64
+ raise "Failed to load gemspec: #{gemspec_path}" unless gemspec
65
+
66
+ gem_path = "#{gemspec.name}-#{gemspec.version}.gem"
67
+
68
+ puts "Publishing #{gem_path} to RubyGem..."
69
+ sh "gem push #{gem_path}"
70
+ end
71
+ end
72
+
73
+ desc "Build and publish all gems to RubyGems"
74
+ task all: GEM_NAMES.map { |gem_name| "release:#{gem_name}" }
75
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ raise LoadError, "This gem has been published by Aikido Security to help prevent supply chain attacks. It is not intended for direct use. Please use 'aikido-zen' instead."
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "@GEM_NAME"
5
+ spec.version = "0.0.2"
6
+ spec.authors = ["Aikido Security"]
7
+ spec.email = ["dev-admin@aikido.dev"]
8
+ spec.summary = "Security placeholder for 'aikido-zen'."
9
+ spec.description = "This gem has been published by Aikido Security to help prevent supply chain attacks. It is not intended for direct use. Please use 'aikido-zen' instead."
10
+ spec.homepage = "https://aikido.dev/zen"
11
+ spec.license = "AGPL-3.0-or-later"
12
+
13
+ spec.required_ruby_version = ">= 2.3"
14
+
15
+ spec.metadata["homepage_uri"] = spec.homepage
16
+ spec.metadata["source_code_uri"] = "https://github.com/aikidosec/firewall-ruby"
17
+
18
+ spec.files = ["lib/@GEM_NAME.rb", "README.md", "LICENSE"]
19
+ spec.require_paths = ["lib"]
20
+ end
data/tasklib/libzen.rake CHANGED
@@ -1,23 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "ffi"
3
4
  require "open-uri"
4
5
  require "rubygems/package_task"
5
6
 
6
7
  require_relative "../lib/aikido/zen/version"
7
8
 
8
- LibZenDL = Struct.new(:os, :arch, :artifact) do
9
- def download
10
- puts "Downloading #{path}"
11
- File.open(path, "wb") { |file| FileUtils.copy_stream(URI(url).open("rb"), file) }
12
- end
13
-
14
- def verify
15
- expected = URI(url + ".sha256sum").read.split(/\s+/).first
16
- actual = Digest::SHA256.file(path).to_s
9
+ class LibZen
10
+ attr_reader :platform, :suffix, :artifact
17
11
 
18
- if expected != actual
19
- abort "Checksum mismatch on #{path}: Expected #{expected}, got #{actual}."
20
- end
12
+ def initialize(platform_suffix, artifact = nil)
13
+ platform, suffix = platform_suffix.split(".", 2)
14
+ @platform = Gem::Platform.new(platform)
15
+ @suffix = suffix
16
+ @artifact = artifact
21
17
  end
22
18
 
23
19
  def version
@@ -25,79 +21,90 @@ LibZenDL = Struct.new(:os, :arch, :artifact) do
25
21
  end
26
22
 
27
23
  def path
28
- [prefix, arch, ext].join(".")
24
+ "lib/aikido/zen/libzen-#{version}-#{platform}.#{suffix}"
29
25
  end
30
26
 
31
- def gem_path
32
- platform = "-#{gemspec.platform}" unless gemspec.platform.to_s == "ruby"
33
- "pkg/#{gemspec.name}-#{gemspec.version}#{platform}.gem"
27
+ def url
28
+ File.join("https://github.com/AikidoSec/zen-internals/releases/download", version, artifact)
34
29
  end
35
30
 
36
- def pkg_dir
37
- File.dirname(gem_path)
31
+ def gemspec(source = Bundler.load_gemspec("aikido-zen.gemspec"))
32
+ return @spec if defined?(@spec)
33
+
34
+ @spec = source.dup
35
+ @spec.platform = platform
36
+ @spec.files << path
37
+ @spec
38
38
  end
39
39
 
40
- def prefix
41
- "lib/aikido/zen/libzen-#{version}"
40
+ def gem_path
41
+ "pkg/#{gemspec.name}-#{gemspec.version}-#{gemspec.platform}.gem"
42
42
  end
43
43
 
44
- def ext
45
- case os
46
- when :darwin then "dylib"
47
- when :linux then "so"
48
- when :windows then "dll"
49
- end
44
+ def resolvable?
45
+ downloadable? || File.exist?(path)
50
46
  end
51
47
 
52
- def url
53
- File.join("https://github.com/AikidoSec/zen-internals/releases/download", version, artifact)
48
+ def downloadable?
49
+ !artifact.nil?
54
50
  end
55
51
 
56
- def gem_platform
57
- gem_os = (os == :windows) ? "mingw64" : os
58
- platform = (arch == "aarch64") ? "arm64" : arch
59
- Gem::Platform.new("#{platform}-#{gem_os}")
52
+ def download
53
+ puts "Downloading #{path}"
54
+ File.open(path, "wb") { |file| FileUtils.copy_stream(URI(url).open("rb"), file) }
60
55
  end
61
56
 
62
- def gemspec(source = Bundler.load_gemspec("aikido-zen.gemspec"))
63
- return @spec if defined?(@spec)
57
+ def verify
58
+ expected = URI(url + ".sha256sum").read.split(/\s+/).first
59
+ actual = Digest::SHA256.file(path).to_s
64
60
 
65
- @spec = source.dup
66
- @spec.platform = gem_platform
67
- @spec.files << path
68
- @spec
61
+ if expected != actual
62
+ abort "Checksum verification failed for #{path}: expected #{expected}, but got #{actual}"
63
+ end
69
64
  end
70
65
 
71
66
  def namespace
72
- "#{os}:#{arch}"
67
+ platform.to_s
68
+ end
69
+
70
+ def pkg_dir
71
+ File.dirname(gem_path)
73
72
  end
74
73
  end
75
74
 
76
- LIBZEN = [
77
- LibZenDL.new(:darwin, "aarch64", "libzen_internals_aarch64-apple-darwin.dylib"),
78
- LibZenDL.new(:darwin, "x86_64", "libzen_internals_x86_64-apple-darwin.dylib"),
79
- LibZenDL.new(:linux, "aarch64", "libzen_internals_aarch64-unknown-linux-gnu.so"),
80
- LibZenDL.new(:linux, "x86_64", "libzen_internals_x86_64-unknown-linux-gnu.so"),
81
- LibZenDL.new(:windows, "x86_64", "libzen_internals_x86_64-pc-windows-gnu.dll")
82
- ]
75
+ LIBZENS = [
76
+ LibZen.new("arm64-darwin.dylib", "libzen_internals_aarch64-apple-darwin.dylib"),
77
+ LibZen.new("arm64-linux.so", "libzen_internals_aarch64-unknown-linux-gnu.so"),
78
+ LibZen.new("arm64-linux-musl.so", "libzen_internals_aarch64-unknown-linux-musl.so"),
79
+ LibZen.new("x86_64-darwin.dylib", "libzen_internals_x86_64-apple-darwin.dylib"),
80
+ LibZen.new("x86_64-linux.so", "libzen_internals_x86_64-unknown-linux-gnu.so"),
81
+ LibZen.new("x86_64-linux-musl.so", "libzen_internals_x86_64-unknown-linux-musl.so"),
82
+ LibZen.new("x86_64-mingw64.dll", "libzen_internals_x86_64-pc-windows-gnu.dll"),
83
+ # Not officially supported, but used during testing:
84
+ LibZen.new("x86_64-freebsd.so"),
85
+ LibZen.new("x86_64-solaris.so")
86
+ ].filter(&:resolvable?)
87
+
83
88
  namespace :libzen do
84
- LIBZEN.each do |lib|
85
- desc "Download libzen for #{lib.os}-#{lib.arch} if necessary"
89
+ LIBZENS.each do |lib|
90
+ desc "Download libzen for #{lib.platform} if necessary"
86
91
  task(lib.namespace => lib.path)
87
92
 
88
- file(lib.path) {
89
- lib.download
90
- lib.verify
91
- }
92
- CLEAN.include(lib.path)
93
+ if lib.downloadable?
94
+ file(lib.path) do
95
+ lib.download
96
+ lib.verify
97
+ end
98
+ CLEAN.include(lib.path)
99
+ end
93
100
 
94
101
  directory lib.pkg_dir
95
102
  CLOBBER.include(lib.pkg_dir)
96
103
 
97
- file(lib.gem_path => [lib.path, lib.pkg_dir]) {
104
+ file(lib.gem_path => [lib.path, lib.pkg_dir]) do
98
105
  path = Gem::Package.build(lib.gemspec)
99
106
  mv path, lib.pkg_dir
100
- }
107
+ end
101
108
  CLOBBER.include(lib.pkg_dir)
102
109
 
103
110
  task "#{lib.namespace}:release" => [lib.gem_path, "release:guard_clean"] do
@@ -105,24 +112,21 @@ namespace :libzen do
105
112
  end
106
113
  end
107
114
 
108
- desc "Build all the native gems for the different libzen versions"
109
- task gems: LIBZEN.map(&:gem_path)
115
+ desc "Build all the native gems"
116
+ task gems: LIBZENS.map(&:gem_path)
110
117
 
111
118
  desc "Push all the native gems to RubyGems"
112
- task release: LIBZEN.map { |lib| "#{lib.namespace}:release" }
119
+ task release: LIBZENS.map { |lib| "#{lib.namespace}:release" }
113
120
 
114
121
  desc "Download the libzen pre-built library for all platforms"
115
- task "download:all" => LIBZEN.map(&:path)
122
+ task "download:all" => LIBZENS.map(&:path)
116
123
 
117
124
  desc "Downloads the libzen library for the current platform"
118
125
  task "download:current" do
119
- require "rbconfig"
120
- os = case RbConfig::CONFIG["host_os"]
121
- when /darwin/ then :darwin
122
- when /mingw|cygwin|mswin/ then :windows
123
- else :linux
124
- end
126
+ platform = Gem::Platform.local.dup
127
+ platform.version = nil unless Rake::Task.task_defined?("libzen:#{platform}")
125
128
 
126
- Rake::Task["libzen:#{os}:#{RbConfig::CONFIG["build_cpu"]}"].invoke
129
+ # Invoke the most specific task
130
+ Rake::Task["libzen:#{platform}"].invoke
127
131
  end
128
132
  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.0.pre.beta.1
4
+ version: 1.0.1.beta.2
5
5
  platform: ruby
6
6
  authors:
7
- - Nicolas Sanguinetti
7
+ - Aikido Security
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-06-04 00:00:00.000000000 Z
11
+ date: 2025-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -52,17 +52,18 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- description:
55
+ description: Zen by Aikido is an embedded Web Application Firewall that autonomously
56
+ protects Ruby apps against common and critical attacks.
56
57
  email:
57
- - foca@foca.io
58
+ - dev-admin@aikido.dev
58
59
  executables: []
59
60
  extensions: []
60
61
  extra_rdoc_files: []
61
62
  files:
63
+ - ".aikido"
62
64
  - ".ruby-version"
63
65
  - ".simplecov"
64
66
  - ".standard.yml"
65
- - CHANGELOG.md
66
67
  - LICENSE
67
68
  - README.md
68
69
  - Rakefile
@@ -72,7 +73,6 @@ files:
72
73
  - docs/config.md
73
74
  - docs/rails.md
74
75
  - lib/aikido-zen.rb
75
- - lib/aikido.rb
76
76
  - lib/aikido/zen.rb
77
77
  - lib/aikido/zen/actor.rb
78
78
  - lib/aikido/zen/agent.rb
@@ -159,20 +159,25 @@ files:
159
159
  - lib/aikido/zen/sinks/sqlite3.rb
160
160
  - lib/aikido/zen/sinks/trilogy.rb
161
161
  - lib/aikido/zen/sinks/typhoeus.rb
162
+ - lib/aikido/zen/sinks_dsl.rb
162
163
  - lib/aikido/zen/synchronizable.rb
163
164
  - lib/aikido/zen/system_info.rb
164
165
  - lib/aikido/zen/version.rb
165
166
  - lib/aikido/zen/worker.rb
167
+ - placeholder/.gitignore
168
+ - placeholder/README.md
169
+ - placeholder/Rakefile
170
+ - placeholder/lib/placeholder.rb.template
171
+ - placeholder/placeholder.gemspec.template
166
172
  - tasklib/bench.rake
167
173
  - tasklib/libzen.rake
168
174
  - tasklib/wrk.rb
169
- homepage: https://aikido.dev
175
+ homepage: https://aikido.dev/zen
170
176
  licenses:
171
177
  - AGPL-3.0-or-later
172
178
  metadata:
173
- homepage_uri: https://aikido.dev
179
+ homepage_uri: https://aikido.dev/zen
174
180
  source_code_uri: https://github.com/aikidosec/firewall-ruby
175
- changelog_uri: https://github.com/aikidosec/firewall-ruby/blob/main/CHANGELOG.md
176
181
  post_install_message:
177
182
  rdoc_options: []
178
183
  require_paths:
@@ -191,6 +196,5 @@ requirements: []
191
196
  rubygems_version: 3.5.22
192
197
  signing_key:
193
198
  specification_version: 4
194
- summary: Embedded Web Application Firewall that autonomously protects Ruby apps against
195
- common and critical attacks.
199
+ summary: Embedded Web Application Firewall.
196
200
  test_files: []
data/CHANGELOG.md DELETED
@@ -1,25 +0,0 @@
1
- # Changelog
2
-
3
- ## [Unreleased]
4
-
5
- ### Fixed
6
-
7
- - Avoid an infinite loop when checking for SSRFs in a circular redirects loop.
8
-
9
- ## 0.1.1
10
-
11
- ### Fixed
12
-
13
- - Avoid an error when sending the initial heartbeat if the Aikido server hasn't
14
- received stats yet.
15
- - Fix the SSRF scanner to ensure the port in the user-supplied payload matches
16
- the port in the request.
17
- - Don't break the HTTP.rb sink when a Zen context isn't set.
18
- - Don't break the Typhoeus sink when a Zen context isn't set.
19
- - Don't break the PG sink outside of Rails.
20
- - Updated [libzen](https://github.com/AikidoSec/zen-internals) to v0.1.31 to
21
- prevent flagging false positives in SQL queries with comments.
22
-
23
- ## 0.1.0
24
-
25
- - Initial version
data/lib/aikido.rb DELETED
@@ -1,3 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "aikido/zen"