aikido-zen 1.7.0 → 1.7.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 651c1ff033d7689d75fa83bc27e64249463e74ad5ecac534df46e2cae96fcda2
4
- data.tar.gz: 8232034fd237b6b4be9cde3cbea8d35c9a796d05b6f72bb90ff4cfc63888d037
3
+ metadata.gz: ddee51760626c0c9d7af69137f88286d0b49ac9d5aab02d17bebbff71136bb0f
4
+ data.tar.gz: 7b5ea9701c89111b1423c99750495b7a4d85b725e78008d93b110e4a2be9007c
5
5
  SHA512:
6
- metadata.gz: bf4940ca74224b195ddbe9447b5d14d61b6f677c152f484a5ed71b6fe100482e5bd71d917f57807b632b24e93e4b9f6d9dbb53f6cc5cdc280dcf3e3315fdbcfd
7
- data.tar.gz: f7746da3d5a9bb8e4c54be18c689fc3338ba7598fe59a683921ff47a8455b6800572016a4ad1103bc42aa0f01e09f34d9e38aecf957474c8dbd18847632ac937
6
+ metadata.gz: edada0391a4cc9f6982dddedd67e6972a13ddb60fad9c723cd1c369e36c3ba5699637dbfacce686c1472e6009e9927f69dcb16945ae7c41c65745e110cff614d
7
+ data.tar.gz: aa43771cf0fb387c55d35fc1f26b3e765ce0c36ed29764ad677fca7d4f69459310a3115088f73a2df65e35d2bc145dc6a6e2294d20ec4aed35cc81fce96de80a
data/docs/config.md CHANGED
@@ -77,7 +77,9 @@ Aikido::Zen.rate_limited_responder = ->(request) {
77
77
  }
78
78
  ```
79
79
 
80
- By default, Zen emits a `text/plain` 429 response that says "Too many requests".
80
+ By default, Zen emits a `text/plain` 429 response that says "Too many requests"
81
+ and includes a `Retry-After` header with the number of seconds until the rate
82
+ limit window resets.
81
83
 
82
84
  ### Providing details about the rate limiting
83
85
 
@@ -409,7 +409,13 @@ module Aikido::Zen
409
409
 
410
410
  # @!visibility private
411
411
  DEFAULT_RATE_LIMITED_RESPONDER = ->(request) do
412
- [429, {"Content-Type" => "text/plain"}, ["Too many requests."]]
412
+ rate_limit = request.env["aikido.rate_limiting"]
413
+ headers = {
414
+ "Content-Type" => "text/plain",
415
+ "Retry-After" => rate_limit.time_remaining.to_s
416
+ }
417
+
418
+ [429, headers, ["Too many requests."]]
413
419
  end
414
420
 
415
421
  # @!visibility private
@@ -4,6 +4,31 @@ require "action_dispatch"
4
4
 
5
5
  module Aikido::Zen
6
6
  class RailsEngine < ::Rails::Engine
7
+ # ActionController::Live runs the whole action in a new Thread so that
8
+ # the original thread can be freed to handle the next request once the
9
+ # response headers are committed.
10
+ #
11
+ # Zen stores the current context on the current Fiber, and propagates
12
+ # this context to new Fibers created with Fiber.new. The root Fiber of
13
+ # a new Thread is not created with Fiber.new so the current context is
14
+ # not propagated automatically.
15
+ #
16
+ # Propagate the current context to the root Fiber of the new Thread
17
+ # created by ActionController::Live to run the action.
18
+ module LiveThreadContextSetter
19
+ private
20
+
21
+ def new_controller_thread(&blk)
22
+ context = Aikido::Zen.current_context
23
+
24
+ super do
25
+ Fiber.current.aikido_current_context = context
26
+
27
+ blk.call
28
+ end
29
+ end
30
+ end
31
+
7
32
  config.before_configuration do
8
33
  # Access library configuration at `Rails.application.config.zen`.
9
34
  config.zen = Aikido::Zen.config
@@ -39,6 +64,8 @@ module Aikido::Zen
39
64
  end
40
65
 
41
66
  ActiveSupport.on_load(:action_controller) do
67
+ ::ActionController::Live.prepend(Aikido::Zen::RailsEngine::LiveThreadContextSetter)
68
+
42
69
  before_action do
43
70
  Aikido::Zen.enable_idor_protection if Aikido::Zen.config.idor_protection_enabled?
44
71
  end
@@ -50,7 +77,7 @@ module Aikido::Zen
50
77
  # This way, we overwrite the Request object as early as we can in the
51
78
  # request handling, so that by the time we start evaluating inputs, we
52
79
  # have assigned the request correctly.
53
- before_action { Aikido::Zen.current_context.update_request(request) }
80
+ before_action { Aikido::Zen.current_context&.update_request(request) }
54
81
  end
55
82
  end
56
83
 
@@ -26,6 +26,8 @@ module Aikido::Zen
26
26
  return false unless controller.respond_to?(:request)
27
27
 
28
28
  context = controller.request.env[Aikido::Zen::ENV_KEY]
29
+ return false if context.nil?
30
+
29
31
  request = context.request
30
32
 
31
33
  return false if @settings.bypassed_ips.include?(request.client_ip)
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Aikido
4
4
  module Zen
5
- VERSION = "1.7.0"
5
+ VERSION = "1.7.1"
6
6
 
7
7
  # The version of libzen_internals that we build against.
8
8
  LIBZEN_VERSION = "0.1.61"
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.7.0
4
+ version: 1.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aikido Security
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-08-04 00:00:00.000000000 Z
11
+ date: 2026-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby