From 5b47fc8affc2a8234483a1165aca91a6fc9e8c84 Mon Sep 17 00:00:00 2001 From: Wout Feys Date: Thu, 20 Mar 2025 14:24:46 +0100 Subject: [PATCH 01/60] Create new process worker script and run it on context creation --- aikido_zen/context/__init__.py | 2 ++ aikido_zen/process_worker/__init__.py | 38 +++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 aikido_zen/process_worker/__init__.py diff --git a/aikido_zen/context/__init__.py b/aikido_zen/context/__init__.py index 296bc68e..9ecfd1ab 100644 --- a/aikido_zen/context/__init__.py +++ b/aikido_zen/context/__init__.py @@ -14,6 +14,7 @@ from .wsgi import set_wsgi_attributes_on_context from .asgi import set_asgi_attributes_on_context from .extract_route_params import extract_route_params +from .. import process_worker UINPUT_SOURCES = ["body", "cookies", "query", "headers", "xml", "route_params"] current_context = contextvars.ContextVar("current_context", default=None) @@ -37,6 +38,7 @@ class Context: """ def __init__(self, context_obj=None, body=None, req=None, source=None): + process_worker.start_worker() if context_obj: logger.debug("Creating Context instance based on dict object.") self.__dict__.update(context_obj) diff --git a/aikido_zen/process_worker/__init__.py b/aikido_zen/process_worker/__init__.py new file mode 100644 index 00000000..fe635aba --- /dev/null +++ b/aikido_zen/process_worker/__init__.py @@ -0,0 +1,38 @@ +""" +process worker -> When a web server like gUnicorn makes new processes, and those have multiple threads, +Aikido's process worker is linked to those new processes, so in essence it's 1 extra thread. This thread +is responsible for syncing statistics, route data, ... +""" +import multiprocessing +import threading +import time + +from aikido_zen.helpers.logging import logger + + +def start_worker(): + # Find out the running process: + logger.info("[%s](%s) <-- `%s`", + multiprocessing.current_process().name, + multiprocessing.current_process().pid, + threading.current_thread().name) + + # The name is aikido-process-worker- + the current PID + thread_name = "aikido-process-worker-" + str(multiprocessing.current_process().pid) + if any([thread.name == thread_name for thread in threading.enumerate()]): + return # The thread already exists, returning. + + # Create a new daemon thread tht will handle communication to and from background agent + thread = threading.Thread(target=aikido_process_worker_thread, name=thread_name) + thread.daemon = True + thread.start() + + +def aikido_process_worker_thread(): + # Get the current process + current_process = multiprocessing.current_process() + + while True: + # Print information about the process + logger.info(f"Process ID: {current_process.pid}, Name: {current_process.name}") + time.sleep(5) From 6aa778ba9502790e6319fe1a5222ed40f1feb2b2 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Fri, 21 Mar 2025 10:06:12 +0100 Subject: [PATCH 02/60] Remove INITIALIZE_ROUTE command --- .../background_process/commands/__init__.py | 2 - .../commands/initialize_route.py | 11 ------ .../commands/initialize_route_test.py | 37 ------------------- 3 files changed, 50 deletions(-) delete mode 100644 aikido_zen/background_process/commands/initialize_route.py delete mode 100644 aikido_zen/background_process/commands/initialize_route_test.py diff --git a/aikido_zen/background_process/commands/__init__.py b/aikido_zen/background_process/commands/__init__.py index dd244219..0cd75ccc 100644 --- a/aikido_zen/background_process/commands/__init__.py +++ b/aikido_zen/background_process/commands/__init__.py @@ -3,7 +3,6 @@ from aikido_zen.helpers.logging import logger from .attack import process_attack from .read_property import process_read_property -from .initialize_route import process_initialize_route from .user import process_user from .should_ratelimit import process_should_ratelimit from .kill import process_kill @@ -16,7 +15,6 @@ # This maps to a tuple : (function, returns_data?) # Commands that don't return data : "ATTACK": (process_attack, False), - "INITIALIZE_ROUTE": (process_initialize_route, False), "USER": (process_user, False), "KILL": (process_kill, False), "STATISTICS": (process_statistics, False), diff --git a/aikido_zen/background_process/commands/initialize_route.py b/aikido_zen/background_process/commands/initialize_route.py deleted file mode 100644 index 83737e98..00000000 --- a/aikido_zen/background_process/commands/initialize_route.py +++ /dev/null @@ -1,11 +0,0 @@ -"""Exports `process_initialize_route`""" - - -def process_initialize_route(connection_manager, data, queue=None): - """ - This is called the first time a route is discovered to initialize it and add one hit. - data is a dictionary called route_metadata which includes: route, method and url. - """ - if connection_manager: - connection_manager.routes.initialize_route(route_metadata=data) - connection_manager.routes.increment_route(route_metadata=data) diff --git a/aikido_zen/background_process/commands/initialize_route_test.py b/aikido_zen/background_process/commands/initialize_route_test.py deleted file mode 100644 index 69e7abbb..00000000 --- a/aikido_zen/background_process/commands/initialize_route_test.py +++ /dev/null @@ -1,37 +0,0 @@ -import pytest -from unittest.mock import MagicMock, patch -from .initialize_route import process_initialize_route - - -@pytest.fixture -def mock_connection_manager(): - """Fixture to create a mock connection_manager with a routes attribute.""" - connection_manager = MagicMock() - connection_manager.routes = MagicMock() - return connection_manager - - -def test_process_initialize_route(mock_connection_manager): - """Test that process_initialize_route adds a route when connection_manager is present.""" - data = 123456 - - process_initialize_route( - mock_connection_manager, data, None - ) # conn is not used in this function - - # Check that increment_route and initialize_route methods were called with the correct arguments - mock_connection_manager.routes.initialize_route.assert_called_once_with( - route_metadata=123456 - ) - mock_connection_manager.routes.increment_route.assert_called_once_with( - route_metadata=123456 - ) - - -def test_process_initialize_route_no_connection_manager(): - """Test that process_initialize_route does nothing when connection_manager is not present.""" - data = 123456 - - process_initialize_route(None, data, None) # conn is not used in this function - - # Check that no error occurs From ead26f850c6d9c9e7878a7d3d3411b8d671b6849 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Fri, 21 Mar 2025 10:06:41 +0100 Subject: [PATCH 03/60] Cleanup of process_worker logic --- aikido_zen/context/__init__.py | 2 -- aikido_zen/process_worker/__init__.py | 38 --------------------------- 2 files changed, 40 deletions(-) delete mode 100644 aikido_zen/process_worker/__init__.py diff --git a/aikido_zen/context/__init__.py b/aikido_zen/context/__init__.py index 9ecfd1ab..296bc68e 100644 --- a/aikido_zen/context/__init__.py +++ b/aikido_zen/context/__init__.py @@ -14,7 +14,6 @@ from .wsgi import set_wsgi_attributes_on_context from .asgi import set_asgi_attributes_on_context from .extract_route_params import extract_route_params -from .. import process_worker UINPUT_SOURCES = ["body", "cookies", "query", "headers", "xml", "route_params"] current_context = contextvars.ContextVar("current_context", default=None) @@ -38,7 +37,6 @@ class Context: """ def __init__(self, context_obj=None, body=None, req=None, source=None): - process_worker.start_worker() if context_obj: logger.debug("Creating Context instance based on dict object.") self.__dict__.update(context_obj) diff --git a/aikido_zen/process_worker/__init__.py b/aikido_zen/process_worker/__init__.py deleted file mode 100644 index fe635aba..00000000 --- a/aikido_zen/process_worker/__init__.py +++ /dev/null @@ -1,38 +0,0 @@ -""" -process worker -> When a web server like gUnicorn makes new processes, and those have multiple threads, -Aikido's process worker is linked to those new processes, so in essence it's 1 extra thread. This thread -is responsible for syncing statistics, route data, ... -""" -import multiprocessing -import threading -import time - -from aikido_zen.helpers.logging import logger - - -def start_worker(): - # Find out the running process: - logger.info("[%s](%s) <-- `%s`", - multiprocessing.current_process().name, - multiprocessing.current_process().pid, - threading.current_thread().name) - - # The name is aikido-process-worker- + the current PID - thread_name = "aikido-process-worker-" + str(multiprocessing.current_process().pid) - if any([thread.name == thread_name for thread in threading.enumerate()]): - return # The thread already exists, returning. - - # Create a new daemon thread tht will handle communication to and from background agent - thread = threading.Thread(target=aikido_process_worker_thread, name=thread_name) - thread.daemon = True - thread.start() - - -def aikido_process_worker_thread(): - # Get the current process - current_process = multiprocessing.current_process() - - while True: - # Print information about the process - logger.info(f"Process ID: {current_process.pid}, Name: {current_process.name}") - time.sleep(5) From 932d840d6233fc571a6c628093d8591e5159f252 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Fri, 21 Mar 2025 10:07:01 +0100 Subject: [PATCH 04/60] Create a process_worker and process_worker_loader in thread --- aikido_zen/thread/process_worker.py | 28 ++++++++++++++++++++++ aikido_zen/thread/process_worker_loader.py | 20 ++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 aikido_zen/thread/process_worker.py create mode 100644 aikido_zen/thread/process_worker_loader.py diff --git a/aikido_zen/thread/process_worker.py b/aikido_zen/thread/process_worker.py new file mode 100644 index 00000000..bff09780 --- /dev/null +++ b/aikido_zen/thread/process_worker.py @@ -0,0 +1,28 @@ +import multiprocessing +import time + +from aikido_zen.helpers.logging import logger +from aikido_zen.thread import thread_cache + +# Renew the cache from this background worker every 5 seconds +RENEW_CACHE_EVERY_X_SEC = 5 + + +def aikido_process_worker_thread(): + """ + process worker -> When a web server like gUnicorn makes new processes, and those have multiple threads, + Aikido process worker is linked to those new processes, so in essence it's 1 extra thread. This thread + is responsible for syncing statistics, route data, configuration, ... + """ + # Get the current process + current_process = multiprocessing.current_process() + + while True: + # Print information about the process + logger.debug( + f"Process ID: {current_process.pid}, Name: {current_process.name} - process_worker running." + ) + + # Renew the cache every 5 seconds + thread_cache.renew() + time.sleep(RENEW_CACHE_EVERY_X_SEC) diff --git a/aikido_zen/thread/process_worker_loader.py b/aikido_zen/thread/process_worker_loader.py new file mode 100644 index 00000000..a1f87bbb --- /dev/null +++ b/aikido_zen/thread/process_worker_loader.py @@ -0,0 +1,20 @@ +import multiprocessing +import threading + +from aikido_zen.thread.process_worker import aikido_process_worker_thread + + +def load_worker(): + """ + Loads in a new process worker if one does not already exist for the current process + """ + + # The name is aikido-process-worker- + the current PID + thread_name = "aikido-process-worker-" + str(multiprocessing.current_process().pid) + if any([thread.name == thread_name for thread in threading.enumerate()]): + return # The thread already exists, returning. + + # Create a new daemon thread tht will handle communication to and from background agent + thread = threading.Thread(target=aikido_process_worker_thread, name=thread_name) + thread.daemon = True + thread.start() From c10d834e87f188da07ae810a33484815b1421427 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Fri, 21 Mar 2025 10:07:11 +0100 Subject: [PATCH 05/60] make thread_cache process-llocal --- aikido_zen/thread/thread_cache.py | 61 +++++++++++++------------------ 1 file changed, 25 insertions(+), 36 deletions(-) diff --git a/aikido_zen/thread/thread_cache.py b/aikido_zen/thread/thread_cache.py index 0dd8dcc1..257b95fd 100644 --- a/aikido_zen/thread/thread_cache.py +++ b/aikido_zen/thread/thread_cache.py @@ -1,39 +1,19 @@ """Exports class ThreadConfig""" -from threading import local import aikido_zen.background_process.comms as comms -import aikido_zen.helpers.get_current_unixtime_ms as t -from aikido_zen.context import get_current_context from aikido_zen.background_process.routes import Routes from aikido_zen.background_process.service_config import ServiceConfig from aikido_zen.helpers.logging import logger - -THREAD_CONFIG_TTL_MS = 60 * 1000 # Time-To-Live is 60 seconds for the thread cache - -threadlocal_storage = local() - - -def get_cache(): - """Returns the current ThreadCache""" - cache = getattr(threadlocal_storage, "cache", None) - if not cache: - return ThreadCache() - return cache +from aikido_zen.thread import process_worker_loader class ThreadCache: """ - A thread-local cache object that holds routes, bypassed ips, endpoints amount of requests - With a Time-To-Live given by THREAD_CONFIG_TTL_MS + A process-local cache object that holds routes, bypassed ips, endpoints amount of requests """ def __init__(self): - # Load initial data : - self.reset() - self.renew() - - # Save as a thread-local object : - threadlocal_storage.cache = self + self.reset() # Initialize values def is_bypassed_ip(self, ip): """Checks the given IP against the list of bypassed ips""" @@ -43,14 +23,6 @@ def is_user_blocked(self, user_id): """Checks if the user id is blocked""" return user_id in self.config.blocked_uids - def renew_if_ttl_expired(self): - """Renews the data only if TTL has expired""" - ttl_has_expired = ( - t.get_unixtime_ms(monotonic=True) - self.last_renewal > THREAD_CONFIG_TTL_MS - ) - if ttl_has_expired: - self.renew() - def get_endpoints(self): return self.config.endpoints @@ -65,16 +37,14 @@ def reset(self): received_any_stats=False, ) self.reqs = 0 - self.last_renewal = 0 self.middleware_installed = False def renew(self): """ Makes an IPC call to store the amount of hits and requests and renew the config """ - # Don't try to fetch a thread cache if communications don't work or - # if we are not inside the context of a web request - if not comms.get_comms() or not get_current_context(): + + if not comms.get_comms(): return res = comms.get_comms().send_data_to_bg_process( @@ -95,9 +65,28 @@ def renew(self): self.routes.routes = res["data"]["routes"] for route in self.routes.routes.values(): route["hits_delta_since_sync"] = 0 - self.last_renewal = t.get_unixtime_ms(monotonic=True) logger.debug("Renewed thread cache") def increment_stats(self): """Increments the requests""" self.reqs += 1 + + +# For these 2 functions and the data they process, we rely on Python's GIL +# See here: https://wiki.python.org/moin/GlobalInterpreterLock +global_thread_cache = ThreadCache() + + +def get_cache(): + """ + Returns the cache, protected by Python's GIL (so not our own mutex), + and starts the process worker (which syncs info between the cache and agent), if it doesn't already exist. + """ + global global_thread_cache + process_worker_loader.load_worker() + return global_thread_cache + + +def renew(): + global global_thread_cache + global_thread_cache.renew() From 312c115f21bf086ce1fae7d94dbcf175a07263a6 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Fri, 21 Mar 2025 10:07:34 +0100 Subject: [PATCH 06/60] Improve route increment stuff --- aikido_zen/background_process/routes/__init__.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/aikido_zen/background_process/routes/__init__.py b/aikido_zen/background_process/routes/__init__.py index 27b21d53..094ff6e6 100644 --- a/aikido_zen/background_process/routes/__init__.py +++ b/aikido_zen/background_process/routes/__init__.py @@ -19,20 +19,17 @@ def __init__(self, max_size=1000): def initialize_route(self, route_metadata): """ - Initializes a route for the first time. + Initializes a route for the first time. `hits_delta_since_sync` counts delta between syncs. """ self.manage_routes_size() key = route_to_key(route_metadata) - if self.routes.get(key): - return self.routes[key] = { "method": route_metadata.get("method"), "path": route_metadata.get("route"), "hits": 0, + "hits_delta_since_sync": 0, "apispec": {}, } - # This field counts the difference in hits in between synchronisation for threads : - self.routes[key]["hits_delta_since_sync"] = 0 def increment_route(self, route_metadata): """ @@ -41,8 +38,8 @@ def increment_route(self, route_metadata): """ key = route_to_key(route_metadata) if not self.routes.get(key): - return - # Add a hit to the route : + self.initialize_route(route_metadata) + # Add hits to route = self.routes.get(key) route["hits"] += 1 route["hits_delta_since_sync"] += 1 From a1f9a2574b638cd3efe299b0ea877d4924dc3035 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Fri, 21 Mar 2025 10:10:23 +0100 Subject: [PATCH 07/60] fix thread_cache_test test cases --- aikido_zen/thread/thread_cache_test.py | 145 +------------------------ 1 file changed, 3 insertions(+), 142 deletions(-) diff --git a/aikido_zen/thread/thread_cache_test.py b/aikido_zen/thread/thread_cache_test.py index 284ad56e..7259d227 100644 --- a/aikido_zen/thread/thread_cache_test.py +++ b/aikido_zen/thread/thread_cache_test.py @@ -1,7 +1,7 @@ import pytest from unittest.mock import patch, MagicMock from aikido_zen.background_process.routes import Routes -from .thread_cache import ThreadCache, THREAD_CONFIG_TTL_MS, threadlocal_storage +from .thread_cache import ThreadCache, get_cache from ..background_process.service_config import ServiceConfig from ..context import current_context, Context from aikido_zen.helpers.iplist import IPList @@ -24,7 +24,7 @@ def run_around_tests(): yield # Make sure to reset thread cache after every test so it does not # interfere with other tests - setattr(threadlocal_storage, "cache", None) + get_cache().reset() current_context.set(None) @@ -35,7 +35,6 @@ def test_initialization(thread_cache: ThreadCache): assert thread_cache.get_endpoints() == [] assert thread_cache.config.blocked_uids == set() assert thread_cache.reqs == 0 - assert thread_cache.last_renewal == 0 def test_is_bypassed_ip(thread_cache: ThreadCache): @@ -55,70 +54,6 @@ def test_is_user_blocked(thread_cache: ThreadCache): assert thread_cache.is_user_blocked("user456") is False -@patch("aikido_zen.background_process.comms.get_comms") -@patch("aikido_zen.helpers.get_current_unixtime_ms.get_unixtime_ms") -def test_renew_if_ttl_expired( - mock_get_unixtime_ms, mock_get_comms, thread_cache: ThreadCache -): - """Test renewing the cache if TTL has expired.""" - mock_get_unixtime_ms.return_value = ( - THREAD_CONFIG_TTL_MS + 1 - ) # Simulate TTL expiration - mock_get_comms.return_value = MagicMock() - mock_get_comms.return_value.send_data_to_bg_process.return_value = { - "success": True, - "data": { - "config": ServiceConfig( - endpoints=[ - { - "graphql": False, - "method": "POST", - "route": "/v2", - "rate_limiting": { - "enabled": False, - }, - "force_protection_off": False, - } - ], - bypassed_ips=["192.168.1.1"], - blocked_uids={"user123"}, - last_updated_at=-1, - received_any_stats=True, - ), - "routes": {}, - }, - } - - thread_cache.renew_if_ttl_expired() - assert thread_cache.is_bypassed_ip("192.168.1.1") - assert thread_cache.get_endpoints() == [ - { - "graphql": False, - "method": "POST", - "route": "/v2", - "rate_limiting": { - "enabled": False, - }, - "force_protection_off": False, - } - ] - assert thread_cache.is_user_blocked("user123") - assert thread_cache.last_renewal > 0 - - -@patch("aikido_zen.background_process.comms.get_comms") -@patch("aikido_zen.helpers.get_current_unixtime_ms.get_unixtime_ms") -def test_renew_if_ttl_not_expired( - mock_get_unixtime_ms, mock_get_comms, thread_cache: ThreadCache -): - """Test that renew is not called if TTL has not expired.""" - mock_get_unixtime_ms.return_value = 0 # Simulate TTL not expired - thread_cache.last_renewal = 0 # Set last renewal to 0 - - thread_cache.renew_if_ttl_expired() - assert thread_cache.last_renewal == 0 # Should not change - - def test_reset(thread_cache: ThreadCache): """Test that reset empties the cache.""" thread_cache.config.bypassed_ips.add("192.168.1.1") @@ -128,7 +63,6 @@ def test_reset(thread_cache: ThreadCache): assert isinstance(thread_cache.config.bypassed_ips, IPList) assert thread_cache.config.blocked_uids == set() assert thread_cache.reqs == 0 - assert thread_cache.last_renewal == 0 def test_increment_stats(thread_cache): @@ -148,7 +82,6 @@ def test_renew_with_no_comms(thread_cache: ThreadCache): assert thread_cache.get_endpoints() == [] assert thread_cache.config.blocked_uids == set() assert thread_cache.reqs == 0 - assert thread_cache.last_renewal == 0 @patch("aikido_zen.background_process.comms.get_comms") @@ -167,7 +100,6 @@ def test_renew_with_invalid_response(mock_get_comms, thread_cache: ThreadCache): assert isinstance(thread_cache.config.bypassed_ips, IPList) assert thread_cache.get_endpoints() == [] assert thread_cache.config.blocked_uids == set() - assert thread_cache.last_renewal > 0 # Should update last_renewal def test_is_bypassed_ip_case_insensitivity(thread_cache: ThreadCache): @@ -194,83 +126,12 @@ def increment_in_thread(): assert thread_cache.reqs == 1000 # 10 threads incrementing 100 times -@patch("aikido_zen.background_process.comms.get_comms") -@patch("aikido_zen.helpers.get_current_unixtime_ms.get_unixtime_ms") -def test_renew_if_ttl_expired_multiple_times( - mock_get_unixtime_ms, mock_get_comms, thread_cache: ThreadCache -): - """Test renewing the cache multiple times if TTL has expired.""" - mock_get_unixtime_ms.return_value = ( - THREAD_CONFIG_TTL_MS + 1 - ) # Simulate TTL expiration - mock_get_comms.return_value = MagicMock() - mock_get_comms.return_value.send_data_to_bg_process.return_value = { - "success": True, - "data": { - "config": ServiceConfig( - endpoints=[ - { - "graphql": False, - "method": "POST", - "route": "/v2", - "rate_limiting": { - "enabled": False, - }, - "force_protection_off": False, - } - ], - bypassed_ips=["192.168.1.1"], - blocked_uids={"user123"}, - last_updated_at=-1, - received_any_stats=True, - ), - "routes": {}, - }, - } - - # First renewal - thread_cache.renew_if_ttl_expired() - assert thread_cache.is_bypassed_ip("192.168.1.1") - assert thread_cache.get_endpoints() == [ - { - "graphql": False, - "method": "POST", - "route": "/v2", - "rate_limiting": { - "enabled": False, - }, - "force_protection_off": False, - } - ] - assert thread_cache.is_user_blocked("user123") - - # Simulate another TTL expiration - mock_get_unixtime_ms.return_value += THREAD_CONFIG_TTL_MS + 1 - thread_cache.renew_if_ttl_expired() - assert thread_cache.is_bypassed_ip("192.168.1.1") - assert thread_cache.get_endpoints() == [ - { - "graphql": False, - "method": "POST", - "route": "/v2", - "rate_limiting": { - "enabled": False, - }, - "force_protection_off": False, - } - ] - assert thread_cache.is_user_blocked("user123") - - @patch("aikido_zen.background_process.comms.get_comms") @patch("aikido_zen.helpers.get_current_unixtime_ms.get_unixtime_ms") def test_parses_routes_correctly( mock_get_unixtime_ms, mock_get_comms, thread_cache: ThreadCache ): """Test renewing the cache multiple times if TTL has expired.""" - mock_get_unixtime_ms.return_value = ( - THREAD_CONFIG_TTL_MS + 1 - ) # Simulate TTL expiration mock_get_comms.return_value = MagicMock() mock_get_comms.return_value.send_data_to_bg_process.return_value = { "success": True, @@ -312,7 +173,7 @@ def test_parses_routes_correctly( } # First renewal - thread_cache.renew_if_ttl_expired() + thread_cache.renew() assert thread_cache.is_bypassed_ip("192.168.1.1") assert thread_cache.get_endpoints() == [ { From a74b3463f6882987b48e16cbf89fb07373523781 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Fri, 21 Mar 2025 10:21:11 +0100 Subject: [PATCH 08/60] Fix all test cases that relied on internal thread cache logic --- aikido_zen/middleware/init_test.py | 15 ++++++--------- aikido_zen/sinks/tests/requests_test.py | 6 +++--- aikido_zen/sinks/tests/urrlib3_test.py | 6 +++--- aikido_zen/vulnerabilities/init_test.py | 16 ++++++---------- 4 files changed, 18 insertions(+), 25 deletions(-) diff --git a/aikido_zen/middleware/init_test.py b/aikido_zen/middleware/init_test.py index dea1e69a..8ee6f2a2 100644 --- a/aikido_zen/middleware/init_test.py +++ b/aikido_zen/middleware/init_test.py @@ -2,16 +2,18 @@ import pytest from aikido_zen.context import current_context, Context, get_current_context -from aikido_zen.thread.thread_cache import ThreadCache, threadlocal_storage +from aikido_zen.thread.thread_cache import ThreadCache, get_cache from . import should_block_request @pytest.fixture(autouse=True) def run_around_tests(): + get_cache().reset() yield # Make sure to reset context and cache after every test so it does not # interfere with other tests current_context.set(None) + get_cache().reset() def test_without_context(): @@ -39,20 +41,15 @@ def set_context(user=None, executed_middleware=False): ).set_as_current_context() -class MyThreadCache(ThreadCache): - def renew_if_ttl_expired(self): - return - - def test_with_context_without_cache(): set_context() - threadlocal_storage.cache = None + get_cache().cache = None assert should_block_request() == {"block": False} def test_with_context_with_cache(): set_context(user={"id": "123"}) - thread_cache = MyThreadCache() + thread_cache = get_cache() thread_cache.config.blocked_uids = ["123"] assert get_current_context().executed_middleware == False @@ -76,7 +73,7 @@ def test_with_context_with_cache(): def test_cache_comms_with_endpoints(): set_context(user={"id": "456"}) - thread_cache = MyThreadCache() + thread_cache = get_cache() thread_cache.config.blocked_uids = ["123"] thread_cache.config.endpoints = [ { diff --git a/aikido_zen/sinks/tests/requests_test.py b/aikido_zen/sinks/tests/requests_test.py index ebc04dfd..628a78c7 100644 --- a/aikido_zen/sinks/tests/requests_test.py +++ b/aikido_zen/sinks/tests/requests_test.py @@ -1,7 +1,7 @@ import os import pytest from aikido_zen.context import Context, current_context -from aikido_zen.thread.thread_cache import ThreadCache, threadlocal_storage +from aikido_zen.thread.thread_cache import ThreadCache, get_cache from aikido_zen.errors import AikidoSSRF from aikido_zen.background_process.comms import reset_comms import aikido_zen.sinks.socket @@ -19,11 +19,12 @@ @pytest.fixture(autouse=True) def run_around_tests(): + get_cache().reset() yield # Make sure to reset context and cache after every test so it does not # interfere with other tests current_context.set(None) - setattr(threadlocal_storage, "cache", None) + get_cache().reset() def set_context_and_lifecycle(url): @@ -48,7 +49,6 @@ def set_context_and_lifecycle(url): source="flask", ) context.set_as_current_context() - ThreadCache() def test_srrf_test(monkeypatch): diff --git a/aikido_zen/sinks/tests/urrlib3_test.py b/aikido_zen/sinks/tests/urrlib3_test.py index 3bcc8122..411c3135 100644 --- a/aikido_zen/sinks/tests/urrlib3_test.py +++ b/aikido_zen/sinks/tests/urrlib3_test.py @@ -1,7 +1,7 @@ import os import pytest from aikido_zen.context import Context, current_context -from aikido_zen.thread.thread_cache import ThreadCache, threadlocal_storage +from aikido_zen.thread.thread_cache import get_cache from aikido_zen.errors import AikidoSSRF from aikido_zen.background_process.comms import reset_comms import aikido_zen.sinks.socket @@ -19,11 +19,12 @@ @pytest.fixture(autouse=True) def run_around_tests(): + get_cache().reset() yield # Make sure to reset context and cache after every test so it does not # interfere with other tests current_context.set(None) - setattr(threadlocal_storage, "cache", None) + get_cache().reset() def set_context_and_lifecycle(url): @@ -48,7 +49,6 @@ def set_context_and_lifecycle(url): source="flask", ) context.set_as_current_context() - ThreadCache() def test_srrf_test(monkeypatch): diff --git a/aikido_zen/vulnerabilities/init_test.py b/aikido_zen/vulnerabilities/init_test.py index 32264c46..c5d6062b 100644 --- a/aikido_zen/vulnerabilities/init_test.py +++ b/aikido_zen/vulnerabilities/init_test.py @@ -3,17 +3,18 @@ from . import run_vulnerability_scan from aikido_zen.context import current_context, Context from aikido_zen.errors import AikidoSQLInjection -from aikido_zen.thread.thread_cache import ThreadCache, threadlocal_storage +from aikido_zen.thread.thread_cache import get_cache from aikido_zen.helpers.iplist import IPList @pytest.fixture(autouse=True) def run_around_tests(): + get_cache().reset() yield # Make sure to reset context and cache after every test so it does not # interfere with other tests current_context.set(None) - setattr(threadlocal_storage, "cache", None) + get_cache().reset() @pytest.fixture @@ -49,14 +50,14 @@ def get_context(): def test_run_vulnerability_scan_no_context(caplog): current_context.set(None) - threadlocal_storage.cache = 1 + get_cache().cache = 1 run_vulnerability_scan(kind="test", op="test", args=tuple()) assert len(caplog.text) == 0 def test_run_vulnerability_scan_no_context_no_lifecycle(caplog): current_context.set(None) - threadlocal_storage.cache = None + get_cache().cache = None run_vulnerability_scan(kind="test", op="test", args=tuple()) assert len(caplog.text) == 0 @@ -64,13 +65,12 @@ def test_run_vulnerability_scan_no_context_no_lifecycle(caplog): def test_run_vulnerability_scan_context_no_lifecycle(caplog): with pytest.raises(Exception): current_context.set(1) - threadlocal_storage.cache = None + get_cache().cache = None run_vulnerability_scan(kind="test", op="test", args=tuple()) def test_lifecycle_cache_ok(caplog, get_context): get_context.set_as_current_context() - cache = ThreadCache() run_vulnerability_scan(kind="test", op="test", args=tuple()) assert "Vulnerability type test currently has no scans implemented" in caplog.text @@ -92,7 +92,6 @@ def test_lifecycle_cache_bypassed_ip(caplog, get_context): def test_sql_injection(caplog, get_context, monkeypatch): get_context.set_as_current_context() - cache = ThreadCache() monkeypatch.setenv("AIKIDO_BLOCK", "1") with pytest.raises(AikidoSQLInjection): run_vulnerability_scan( @@ -104,7 +103,6 @@ def test_sql_injection(caplog, get_context, monkeypatch): def test_sql_injection_with_route_params(caplog, get_context, monkeypatch): get_context.set_as_current_context() - cache = ThreadCache() monkeypatch.setenv("AIKIDO_BLOCK", "1") with pytest.raises(AikidoSQLInjection): run_vulnerability_scan( @@ -116,8 +114,6 @@ def test_sql_injection_with_route_params(caplog, get_context, monkeypatch): def test_sql_injection_with_comms(caplog, get_context, monkeypatch): get_context.set_as_current_context() - cache = ThreadCache() - cache.last_renewal = 9999999999999999999999 monkeypatch.setenv("AIKIDO_BLOCK", "1") with patch("aikido_zen.background_process.comms.get_comms") as mock_get_comms: # Create a mock comms object From 2f08b88c87de660e80eaff51a5a3c9abd2d6f419 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Fri, 21 Mar 2025 10:23:34 +0100 Subject: [PATCH 09/60] Cleanup thread_cache.py --- aikido_zen/thread/thread_cache.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/aikido_zen/thread/thread_cache.py b/aikido_zen/thread/thread_cache.py index 257b95fd..9da965f6 100644 --- a/aikido_zen/thread/thread_cache.py +++ b/aikido_zen/thread/thread_cache.py @@ -40,13 +40,10 @@ def reset(self): self.middleware_installed = False def renew(self): - """ - Makes an IPC call to store the amount of hits and requests and renew the config - """ - if not comms.get_comms(): return + # send stored data and receive new config and routes res = comms.get_comms().send_data_to_bg_process( action="SYNC_DATA", obj={ @@ -56,16 +53,19 @@ def renew(self): }, receive=True, ) + if not res["success"] and res["data"]: + return self.reset() - if res["success"] and res["data"]: - if isinstance(res["data"].get("config"), ServiceConfig): - self.config = res["data"]["config"] - if isinstance(res["data"].get("routes"), dict): - self.routes.routes = res["data"]["routes"] - for route in self.routes.routes.values(): - route["hits_delta_since_sync"] = 0 - logger.debug("Renewed thread cache") + # update config + if isinstance(res["data"].get("config"), ServiceConfig): + self.config = res["data"]["config"] + + # update routes + if isinstance(res["data"].get("routes"), dict): + self.routes.routes = res["data"]["routes"] + for route in self.routes.routes.values(): + route["hits_delta_since_sync"] = 0 def increment_stats(self): """Increments the requests""" From 950849c6797a190ed5bdcf402ccc39c7150cfa10 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Fri, 21 Mar 2025 10:24:02 +0100 Subject: [PATCH 10/60] make log message make some sense --- aikido_zen/thread/process_worker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aikido_zen/thread/process_worker.py b/aikido_zen/thread/process_worker.py index bff09780..bdf14b7b 100644 --- a/aikido_zen/thread/process_worker.py +++ b/aikido_zen/thread/process_worker.py @@ -20,7 +20,7 @@ def aikido_process_worker_thread(): while True: # Print information about the process logger.debug( - f"Process ID: {current_process.pid}, Name: {current_process.name} - process_worker running." + f"Process ID: {current_process.pid}, Name: {current_process.name} - process_worker renewing thread cache." ) # Renew the cache every 5 seconds From 436f6300b6c590a4a0f129020bdbd9bbba461649 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Fri, 21 Mar 2025 10:29:32 +0100 Subject: [PATCH 11/60] fix thread_cache res check and only start process_worker with context --- aikido_zen/thread/process_worker_loader.py | 3 +++ aikido_zen/thread/thread_cache.py | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/aikido_zen/thread/process_worker_loader.py b/aikido_zen/thread/process_worker_loader.py index a1f87bbb..bfb6a183 100644 --- a/aikido_zen/thread/process_worker_loader.py +++ b/aikido_zen/thread/process_worker_loader.py @@ -1,6 +1,7 @@ import multiprocessing import threading +from aikido_zen.context import get_current_context from aikido_zen.thread.process_worker import aikido_process_worker_thread @@ -8,6 +9,8 @@ def load_worker(): """ Loads in a new process worker if one does not already exist for the current process """ + if get_current_context() is None: + return # don't start a worker if it's not related to a request. # The name is aikido-process-worker- + the current PID thread_name = "aikido-process-worker-" + str(multiprocessing.current_process().pid) diff --git a/aikido_zen/thread/thread_cache.py b/aikido_zen/thread/thread_cache.py index 9da965f6..0b6fe1ef 100644 --- a/aikido_zen/thread/thread_cache.py +++ b/aikido_zen/thread/thread_cache.py @@ -3,6 +3,7 @@ import aikido_zen.background_process.comms as comms from aikido_zen.background_process.routes import Routes from aikido_zen.background_process.service_config import ServiceConfig +from aikido_zen.context import get_current_context from aikido_zen.helpers.logging import logger from aikido_zen.thread import process_worker_loader @@ -53,7 +54,7 @@ def renew(self): }, receive=True, ) - if not res["success"] and res["data"]: + if not res["success"] or not res["data"]: return self.reset() From f6d6cfc63397c1e4adf24c81af31f86e1c0a4408 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Fri, 21 Mar 2025 11:03:26 +0100 Subject: [PATCH 12/60] Fix broken routes test --- aikido_zen/background_process/routes/init_test.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/aikido_zen/background_process/routes/init_test.py b/aikido_zen/background_process/routes/init_test.py index 73dd9dd5..44471f62 100644 --- a/aikido_zen/background_process/routes/init_test.py +++ b/aikido_zen/background_process/routes/init_test.py @@ -102,13 +102,6 @@ def test_increment_route_twice(): assert routes.routes["GET:/api/resource"]["hits"] == 2 -def test_increment_route_that_does_not_exist(): - routes = Routes(max_size=3) - routes.increment_route(gen_route_metadata(route="/api/resource")) - routes.increment_route(gen_route_metadata(route="/api/resource")) - assert len(routes.routes) == 0 - - def test_clear_routes(): routes = Routes(max_size=3) routes.initialize_route(gen_route_metadata(route="/api/resource")) From 3f570f382708c815afc91194c614a96625afffc3 Mon Sep 17 00:00:00 2001 From: Wout Feys Date: Tue, 25 Mar 2025 11:03:35 +0100 Subject: [PATCH 13/60] Fix django mysql e2e test --- end2end/django_mysql_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/end2end/django_mysql_test.py b/end2end/django_mysql_test.py index 7e499be4..de5b4366 100644 --- a/end2end/django_mysql_test.py +++ b/end2end/django_mysql_test.py @@ -81,7 +81,7 @@ def test_initial_heartbeat(): [{ "apispec": {}, "hits": 1, - "hits_delta_since_sync": 1, + "hits_delta_since_sync": 0, "method": "POST", "path": "/app/create" }], From f41512e403b98125c8be22cb772c79613fd000f1 Mon Sep 17 00:00:00 2001 From: Wout Feys Date: Tue, 25 Mar 2025 11:18:58 +0100 Subject: [PATCH 14/60] Also add apispec to e2e test --- end2end/django_mysql_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/end2end/django_mysql_test.py b/end2end/django_mysql_test.py index de5b4366..5443caf6 100644 --- a/end2end/django_mysql_test.py +++ b/end2end/django_mysql_test.py @@ -79,7 +79,7 @@ def test_initial_heartbeat(): assert len(heartbeat_events) == 1 validate_heartbeat(heartbeat_events[0], [{ - "apispec": {}, + "apispec": {'body': {'type': 'form-urlencoded', 'schema': {'type': 'object', 'properties': {'dog_name': {'type': 'string'}}}}, 'query': None, 'auth': None}, "hits": 1, "hits_delta_since_sync": 0, "method": "POST", From 19c7b62e5d8a814e049bc6261cee15eaf1e606a1 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Wed, 26 Mar 2025 11:21:06 +0100 Subject: [PATCH 15/60] Total is 3 requests for django_mysql e2e --- end2end/django_mysql_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/end2end/django_mysql_test.py b/end2end/django_mysql_test.py index 5443caf6..95c8f456 100644 --- a/end2end/django_mysql_test.py +++ b/end2end/django_mysql_test.py @@ -85,5 +85,5 @@ def test_initial_heartbeat(): "method": "POST", "path": "/app/create" }], - {"aborted":0,"attacksDetected":{"blocked":2,"total":2},"total":0} + {"aborted":0,"attacksDetected":{"blocked":2,"total":2},"total":3} ) From 5b83da45acbab4f903b6820546897de6a679e5f5 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Wed, 26 Mar 2025 11:25:48 +0100 Subject: [PATCH 16/60] Fix request_handler --- aikido_zen/sources/functions/request_handler.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/aikido_zen/sources/functions/request_handler.py b/aikido_zen/sources/functions/request_handler.py index 0ea7cb00..00cae7a7 100644 --- a/aikido_zen/sources/functions/request_handler.py +++ b/aikido_zen/sources/functions/request_handler.py @@ -15,12 +15,9 @@ def request_handler(stage, status_code=0): """This will check for rate limiting, Allowed IP's, useful routes, etc.""" try: if stage == "init": - # Initial stage of the request, called after context is stored. thread_cache = get_cache() - thread_cache.renew_if_ttl_expired() # Only check TTL at the start of a request. if ctx.get_current_context() and thread_cache: thread_cache.increment_stats() # Increment request statistics if a context exists. - if stage == "pre_response": return pre_response() if stage == "post_response": @@ -79,6 +76,8 @@ def post_response(status_code): comms = communications.get_comms() if not context or not comms: return + route_metadata = context.get_route_metadata() + is_curr_route_useful = is_useful_route( status_code, context.route, @@ -86,17 +85,12 @@ def post_response(status_code): ) if not is_curr_route_useful: return - route_metadata = context.get_route_metadata() + cache = get_cache() if cache: - route = cache.routes.get(route_metadata) - if not route: - # This route does not exist yet, initialize it: - cache.routes.initialize_route(route_metadata) - comms.send_data_to_bg_process("INITIALIZE_ROUTE", route_metadata) + cache.routes.increment_route(route_metadata) + # Run API Discovery : update_route_info( new_apispec=get_api_info(context), route=cache.routes.get(route_metadata) ) - # Add hit : - cache.routes.increment_route(route_metadata) From 0c929cc9d12de43ca6e92d69f63020861612cc54 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Wed, 26 Mar 2025 11:29:42 +0100 Subject: [PATCH 17/60] Fix test cases of request_handler --- aikido_zen/sources/functions/request_handler_test.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/aikido_zen/sources/functions/request_handler_test.py b/aikido_zen/sources/functions/request_handler_test.py index f85c1688..826f0c72 100644 --- a/aikido_zen/sources/functions/request_handler_test.py +++ b/aikido_zen/sources/functions/request_handler_test.py @@ -1,6 +1,6 @@ import pytest from unittest.mock import patch, MagicMock -from aikido_zen.thread.thread_cache import get_cache, ThreadCache, threadlocal_storage +from aikido_zen.thread.thread_cache import get_cache, ThreadCache from .request_handler import request_handler, post_response from ...background_process.service_config import ServiceConfig from ...context import Context, current_context @@ -22,9 +22,10 @@ def mock_context(): @pytest.fixture(autouse=True) def run_around_tests(): + get_cache().reset() current_context.set(None) yield - setattr(threadlocal_storage, "cache", None) + get_cache().reset() current_context.set(None) From 05a87f56603196aaf9432c4d536c3d6aa9481a81 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Wed, 26 Mar 2025 11:36:36 +0100 Subject: [PATCH 18/60] Fix request_handler and it's test cases --- .../sources/functions/request_handler.py | 4 +--- .../sources/functions/request_handler_test.py | 20 ++++--------------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/aikido_zen/sources/functions/request_handler.py b/aikido_zen/sources/functions/request_handler.py index 00cae7a7..16b58788 100644 --- a/aikido_zen/sources/functions/request_handler.py +++ b/aikido_zen/sources/functions/request_handler.py @@ -1,6 +1,5 @@ """Exports request_handler function""" -import aikido_zen.background_process as communications import aikido_zen.context as ctx from aikido_zen.api_discovery.get_api_info import get_api_info from aikido_zen.api_discovery.update_route_info import update_route_info @@ -73,8 +72,7 @@ def pre_response(): def post_response(status_code): """Checks if the current route is useful""" context = ctx.get_current_context() - comms = communications.get_comms() - if not context or not comms: + if not context: return route_metadata = context.get_route_metadata() diff --git a/aikido_zen/sources/functions/request_handler_test.py b/aikido_zen/sources/functions/request_handler_test.py index 826f0c72..855ff6b0 100644 --- a/aikido_zen/sources/functions/request_handler_test.py +++ b/aikido_zen/sources/functions/request_handler_test.py @@ -1,7 +1,7 @@ import pytest from unittest.mock import patch, MagicMock from aikido_zen.thread.thread_cache import get_cache, ThreadCache -from .request_handler import request_handler, post_response +from .request_handler import request_handler from ...background_process.service_config import ServiceConfig from ...context import Context, current_context @@ -29,13 +29,10 @@ def run_around_tests(): current_context.set(None) -@patch("aikido_zen.background_process.get_comms") -def test_post_response_useful_route(mock_get_comms, mock_context): +def test_post_response_useful_route(mock_context): """Test post_response when the route is useful.""" - comms = MagicMock() - mock_get_comms.return_value = comms - cache = ThreadCache() # Creates a new cache + cache = get_cache() # Creates a new cache assert cache.routes.routes == {} with patch("aikido_zen.context.get_current_context", return_value=mock_context): request_handler("post_response", status_code=200) @@ -51,15 +48,6 @@ def test_post_response_useful_route(mock_get_comms, mock_context): } } - comms.send_data_to_bg_process.assert_called_once_with( - "INITIALIZE_ROUTE", - { - "route": "/test/route", - "method": "GET", - "url": "http://localhost:8080/test/route", - }, - ) - @patch("aikido_zen.background_process.get_comms") def test_post_response_not_useful_route(mock_get_comms, mock_context): @@ -130,7 +118,7 @@ def create_service_config(blocked_ips=None): ) if blocked_ips: config.set_blocked_ips(blocked_ips) - ThreadCache().config = config + get_cache().config = config return config From 4ddd294d1342c4df7060435a8dad33f31d920a76 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Wed, 26 Mar 2025 11:39:26 +0100 Subject: [PATCH 19/60] Fix broken test case for vulnerability scanner --- aikido_zen/vulnerabilities/init_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aikido_zen/vulnerabilities/init_test.py b/aikido_zen/vulnerabilities/init_test.py index c5d6062b..21d2ac9a 100644 --- a/aikido_zen/vulnerabilities/init_test.py +++ b/aikido_zen/vulnerabilities/init_test.py @@ -82,7 +82,7 @@ def test_ssrf(caplog, get_context): def test_lifecycle_cache_bypassed_ip(caplog, get_context): get_context.set_as_current_context() - cache = ThreadCache() + cache = get_cache() cache.config.bypassed_ips = IPList() cache.config.bypassed_ips.add("198.51.100.23") assert cache.is_bypassed_ip("198.51.100.23") From c43ab2f837444d34203a356c5fadbb64e90c5bc9 Mon Sep 17 00:00:00 2001 From: Wout Feys Date: Wed, 26 Mar 2025 14:06:24 +0100 Subject: [PATCH 20/60] validate the firewall lists API response correctly --- .../cloud_connection_manager/update_firewall_lists.py | 11 +++++------ end2end/server/mock_aikido_core.py | 2 ++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/aikido_zen/background_process/cloud_connection_manager/update_firewall_lists.py b/aikido_zen/background_process/cloud_connection_manager/update_firewall_lists.py index c4a95515..41b6cf3c 100644 --- a/aikido_zen/background_process/cloud_connection_manager/update_firewall_lists.py +++ b/aikido_zen/background_process/cloud_connection_manager/update_firewall_lists.py @@ -17,12 +17,11 @@ def update_firewall_lists(connection_manager): blocked_user_agents = res.get("blockedUserAgents") # Validate response - if ( - not res.get("success") - and blocked_ips - and allowed_ips - and blocked_user_agents - ): + if not res.get("success"): + return + if not isinstance(blocked_ips, list) or not isinstance(allowed_ips, list): + return + if not isinstance(blocked_user_agents, str): return connection_manager.conf.set_blocked_ips(blocked_ips) diff --git a/end2end/server/mock_aikido_core.py b/end2end/server/mock_aikido_core.py index cb7f2567..4fbc2748 100644 --- a/end2end/server/mock_aikido_core.py +++ b/end2end/server/mock_aikido_core.py @@ -36,6 +36,8 @@ "ips": ["1.2.3.4"] } ], + "allowedIPAddresses": [], + "blockedUserAgents": "", }, "configUpdatedAt": {}, } From 57825879b6464032a7bacacd772fcaa89e0247f2 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Tue, 1 Apr 2025 11:10:13 +0200 Subject: [PATCH 21/60] Improves heartbeat event validation Enhances heartbeat event validation by adding informative assertion messages, making debugging easier when validation fails. --- end2end/server/check_events_from_mock.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/end2end/server/check_events_from_mock.py b/end2end/server/check_events_from_mock.py index af8724be..8da473f3 100644 --- a/end2end/server/check_events_from_mock.py +++ b/end2end/server/check_events_from_mock.py @@ -22,6 +22,7 @@ def validate_started_event(event, stack, dry_mode=False, serverless=False, os_na # assert set(event["agent"]["stack"]) == set(stack) def validate_heartbeat(event, routes, req_stats): - assert event["type"] == "heartbeat" - assert event["routes"] == routes - assert event["stats"]["requests"] == req_stats + assert event["type"] == "heartbeat", f"Expected event type 'heartbeat', but got '{event['type']}'" + assert event["routes"] == routes, f"Expected routes '{routes}', but got '{event['routes']}'" + assert event["stats"]["requests"] == req_stats, f"Expected request stats '{req_stats}', but got '{event['stats']['requests']}'" + From 116d7b24159d04a51c9fa4bd4d4ae3f1d0f0fcaa Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 10:16:28 +0200 Subject: [PATCH 22/60] Test 3.13 as well for unit tests and e2e tests --- .github/workflows/end2end.yml | 2 +- .github/workflows/unit-test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/end2end.yml b/.github/workflows/end2end.yml index 92fabfeb..05d16c68 100644 --- a/.github/workflows/end2end.yml +++ b/.github/workflows/end2end.yml @@ -35,7 +35,7 @@ jobs: - { name: flask-postgres-xml, testfile: end2end/flask_postgres_xml_lxml_test.py } - { name: quart-postgres-uvicorn, testfile: end2end/quart_postgres_uvicorn_test.py } - { name: starlette-postgres-uvicorn, testfile: end2end/starlette_postgres_uvicorn_test.py } - python-version: ["3.10", "3.11", "3.12"] + python-version: ["3.10", "3.11", "3.12", "3.13"] steps: - name: Install packages run: sudo apt update && sudo apt install python3-dev libmysqlclient-dev diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 9ed88da3..03bed046 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -10,7 +10,7 @@ jobs: # Don't cancel jobs if one fails fail-fast: false matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] steps: - name: Checkout code uses: actions/checkout@v4 From 9d9ad25113e72e4ebafbb877ffeaa2c3a8e31d2b Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 10:21:37 +0200 Subject: [PATCH 23/60] Benchmarks for all supported python versions --- .github/workflows/benchmark.yml | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 663e4ac5..74a001b5 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -1,7 +1,8 @@ -name: Benchmark +name: 📊 Benchmarks on: push: {} workflow_call: {} + jobs: benchmark_sql_algorithm: runs-on: ubuntu-latest @@ -30,15 +31,24 @@ jobs: run: | poetry run python ./benchmarks/sql_benchmark/sql_benchmark_fw.py poetry run python ./benchmarks/sql_benchmark/sql_benchmark_no_fw.py + benchmark_with_flask_mysql: runs-on: ubuntu-latest timeout-minutes: 10 + strategy: + fail-fast: false + matrix: + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] steps: - name: Checkout code uses: actions/checkout@v4 - name: Start databases working-directory: ./sample-apps/databases run: docker compose up --build -d + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} - name: Install dependencies & build run: | python -m pip install --upgrade pip @@ -51,15 +61,24 @@ jobs: - name: Run flask-mysql k6 Benchmark run: | k6 run -q ./benchmarks/flask-mysql-benchmarks.js + benchmark_with_starlette_app: runs-on: ubuntu-latest timeout-minutes: 10 + strategy: + fail-fast: false + matrix: + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] steps: - name: Checkout code uses: actions/checkout@v4 - name: Start databases working-directory: ./sample-apps/databases run: docker compose up --build -d + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} - name: Install dependencies & build run: | python -m pip install --upgrade pip @@ -71,9 +90,5 @@ jobs: run: | sudo apt-get update sudo apt-get install -y wrk - - name: Set up Python 3.9 - uses: actions/setup-python@v2 - with: - python-version: 3.9 - name: Run benchmark run: python ./benchmarks/starlette_benchmark.py From 72cd57deb2dde0dd5475dc9c35970a5218a0a407 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 12:28:18 +0200 Subject: [PATCH 24/60] init tests as a module --- aikido_zen/sinks/tests/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 aikido_zen/sinks/tests/__init__.py diff --git a/aikido_zen/sinks/tests/__init__.py b/aikido_zen/sinks/tests/__init__.py new file mode 100644 index 00000000..e69de29b From 8336b97e3d78f968c846a6a9967a694c0643b5e2 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 12:28:46 +0200 Subject: [PATCH 25/60] Refactor pymysql to use wrapt --- aikido_zen/sinks/__init__.py | 10 ++++++ aikido_zen/sinks/pymysql.py | 68 +++++++++++++++++++----------------- 2 files changed, 45 insertions(+), 33 deletions(-) diff --git a/aikido_zen/sinks/__init__.py b/aikido_zen/sinks/__init__.py index e69de29b..1ead752c 100644 --- a/aikido_zen/sinks/__init__.py +++ b/aikido_zen/sinks/__init__.py @@ -0,0 +1,10 @@ +from wrapt import wrap_object, FunctionWrapper + +from aikido_zen.helpers.logging import logger + + +def try_wrap_function_wrapper(module, name, wrapper): + try: + wrap_object(module, name, FunctionWrapper, (wrapper,)) + except Exception as e: + logger.info("Failed to wrap %s, due to: %s", module, e) diff --git a/aikido_zen/sinks/pymysql.py b/aikido_zen/sinks/pymysql.py index ae1e5fdb..bc99cc06 100644 --- a/aikido_zen/sinks/pymysql.py +++ b/aikido_zen/sinks/pymysql.py @@ -2,47 +2,49 @@ Sink module for `pymysql` """ -import copy -import logging -import aikido_zen.importhook as importhook +from wrapt import when_imported from aikido_zen.background_process.packages import is_package_compatible import aikido_zen.vulnerabilities as vulns +from aikido_zen.helpers.get_argument import get_argument +from aikido_zen.sinks import try_wrap_function_wrapper -logger = logging.getLogger("aikido_zen") REQUIRED_PYMYSQL_VERSION = "0.9.0" -@importhook.on_import("pymysql.cursors") -def on_pymysql_import(mysql): +def _execute(func, instance, args, kwargs): + query = get_argument(args, kwargs, 0, "query") + if isinstance(query, bytearray): + # If query is type bytearray, it will be picked up by our wrapping of executemany + return func(*args, **kwargs) + + vulns.run_vulnerability_scan( + kind="sql_injection", op="pymysql.Cursor.execute", args=(query, "mysql") + ) + + return func(*args, **kwargs) + + +def _executemany(func, instance, args, kwargs): + query = get_argument(args, kwargs, 0, "query") + + vulns.run_vulnerability_scan( + kind="sql_injection", op="pymysql.Cursor.executemany", args=(query, "mysql") + ) + + return func(*args, **kwargs) + + +@when_imported("pymysql.cursors") +def patch(m): """ - Hook 'n wrap on `pymysql.cursors` - Our goal is to wrap execute() and executemany() on Cursor class + patching `pymysql.cursors` + - patches Cursor.execute(query) + - patches Cursor.executemany(query) https://github.com/PyMySQL/PyMySQL/blob/95635f587ba9076e71a223b113efb08ac34a361d/pymysql/cursors.py#L133 - Returns : Modified pymysql.cursors object """ if not is_package_compatible("pymysql", REQUIRED_PYMYSQL_VERSION): - return mysql - modified_mysql = importhook.copy_module(mysql) - - prev_execute_func = copy.deepcopy(mysql.Cursor.execute) - prev_executemany_func = copy.deepcopy(mysql.Cursor.executemany) - - def aikido_new_execute(self, query, args=None): - if isinstance(query, bytearray): - logger.debug("Query is bytearray, normally comes from executemany.") - return prev_execute_func(self, query, args) - vulns.run_vulnerability_scan( - kind="sql_injection", op="pymysql.Cursor.execute", args=(query, "mysql") - ) - return prev_execute_func(self, query, args) - - def aikido_new_executemany(self, query, args): - op = "pymysql.Cursor.executemany" - vulns.run_vulnerability_scan(kind="sql_injection", op=op, args=(query, "mysql")) - return prev_executemany_func(self, query, args) - - setattr(mysql.Cursor, "execute", aikido_new_execute) - setattr(mysql.Cursor, "executemany", aikido_new_executemany) - - return modified_mysql + return + + try_wrap_function_wrapper(m, "Cursor.execute", _execute) + try_wrap_function_wrapper(m, "Cursor.executemany", _executemany) From dde3ba943515584382b2fed2f01ceadb27a01ba3 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 12:29:49 +0200 Subject: [PATCH 26/60] (poetry) install wrapt --- poetry.lock | 91 +++++++++++++++++++++++++++++++++++++++++++++++++- pyproject.toml | 1 + 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index dfa00ac3..53b99419 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1470,6 +1470,95 @@ MarkupSafe = ">=2.1.1" [package.extras] watchdog = ["watchdog (>=2.3)"] +[[package]] +name = "wrapt" +version = "1.17.2" +description = "Module for decorators, wrappers and monkey patching." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984"}, + {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22"}, + {file = "wrapt-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62"}, + {file = "wrapt-1.17.2-cp310-cp310-win32.whl", hash = "sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563"}, + {file = "wrapt-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72"}, + {file = "wrapt-1.17.2-cp311-cp311-win32.whl", hash = "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317"}, + {file = "wrapt-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9"}, + {file = "wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9"}, + {file = "wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504"}, + {file = "wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a"}, + {file = "wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f"}, + {file = "wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555"}, + {file = "wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c803c401ea1c1c18de70a06a6f79fcc9c5acfc79133e9869e730ad7f8ad8ef9"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f917c1180fdb8623c2b75a99192f4025e412597c50b2ac870f156de8fb101119"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ecc840861360ba9d176d413a5489b9a0aff6d6303d7e733e2c4623cfa26904a6"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb87745b2e6dc56361bfde481d5a378dc314b252a98d7dd19a651a3fa58f24a9"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58455b79ec2661c3600e65c0a716955adc2410f7383755d537584b0de41b1d8a"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4e42a40a5e164cbfdb7b386c966a588b1047558a990981ace551ed7e12ca9c2"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:91bd7d1773e64019f9288b7a5101f3ae50d3d8e6b1de7edee9c2ccc1d32f0c0a"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:bb90fb8bda722a1b9d48ac1e6c38f923ea757b3baf8ebd0c82e09c5c1a0e7a04"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:08e7ce672e35efa54c5024936e559469436f8b8096253404faeb54d2a878416f"}, + {file = "wrapt-1.17.2-cp38-cp38-win32.whl", hash = "sha256:410a92fefd2e0e10d26210e1dfb4a876ddaf8439ef60d6434f21ef8d87efc5b7"}, + {file = "wrapt-1.17.2-cp38-cp38-win_amd64.whl", hash = "sha256:95c658736ec15602da0ed73f312d410117723914a5c91a14ee4cdd72f1d790b3"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99039fa9e6306880572915728d7f6c24a86ec57b0a83f6b2491e1d8ab0235b9a"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2696993ee1eebd20b8e4ee4356483c4cb696066ddc24bd70bcbb80fa56ff9061"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:612dff5db80beef9e649c6d803a8d50c409082f1fedc9dbcdfde2983b2025b82"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62c2caa1585c82b3f7a7ab56afef7b3602021d6da34fbc1cf234ff139fed3cd9"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c958bcfd59bacc2d0249dcfe575e71da54f9dcf4a8bdf89c4cb9a68a1170d73f"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc78a84e2dfbc27afe4b2bd7c80c8db9bca75cc5b85df52bfe634596a1da846b"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba0f0eb61ef00ea10e00eb53a9129501f52385c44853dbd6c4ad3f403603083f"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1e1fe0e6ab7775fd842bc39e86f6dcfc4507ab0ffe206093e76d61cde37225c8"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c86563182421896d73858e08e1db93afdd2b947a70064b813d515d66549e15f9"}, + {file = "wrapt-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f393cda562f79828f38a819f4788641ac7c4085f30f1ce1a68672baa686482bb"}, + {file = "wrapt-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:36ccae62f64235cf8ddb682073a60519426fdd4725524ae38874adf72b5f2aeb"}, + {file = "wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8"}, + {file = "wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3"}, +] + [[package]] name = "zipp" version = "3.20.1" @@ -1494,4 +1583,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.1" python-versions = "^3.8" -content-hash = "d9471b4f306520b4bfc37611755b0a82a267d7dc2be4f404c70ebc894a8e9c48" +content-hash = "a2e0dbe0a2ae24755e6ab9729d16192672bb2faf9e77f2acc4b26dc0f3deea00" diff --git a/pyproject.toml b/pyproject.toml index 2d7fbf0e..fa6c90ac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -60,6 +60,7 @@ python-dotenv = "^1.0.1" regex = "^2024.5.15" requests = "^2.32.3" packaging = "^24.1" +wrapt = "^1.17" [tool.poetry.group.dev.dependencies] black = "^24.4.2" From 47058fdbbd14d3eed1178dc3bd0265fd5ea3e7e4 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 13:03:33 +0200 Subject: [PATCH 27/60] Update subprocess patching --- aikido_zen/sinks/subprocess.py | 84 ++++++++--------------- aikido_zen/sinks/tests/subprocess_test.py | 4 +- 2 files changed, 31 insertions(+), 57 deletions(-) diff --git a/aikido_zen/sinks/subprocess.py b/aikido_zen/sinks/subprocess.py index 92c8b0a6..cb8ee33c 100644 --- a/aikido_zen/sinks/subprocess.py +++ b/aikido_zen/sinks/subprocess.py @@ -2,71 +2,45 @@ Sink module for `subprocess` """ -import copy -import aikido_zen.importhook as importhook +from wrapt import when_imported import aikido_zen.vulnerabilities as vulns from aikido_zen.helpers.get_argument import get_argument +from aikido_zen.sinks import try_wrap_function_wrapper -SUBPROCESS_OPERATIONS = ["check_output"] -# check_call, call, and run all call Popen class - -def generate_aikido_function(op, former_func): +@when_imported("subprocess") +def patch(m): """ - Generates an aikido shell function given - an operation and a former function + patching subprocess module + - patches Popen.__init__ constructor + - does not patch: check_output, check_call, call, and run (call Popen class) """ + try_wrap_function_wrapper(m, "Popen.__init__", _subprocess_init) - def aikido_new_func(*args, op=op, former_func=former_func, **kwargs): - shell_enabled = kwargs.get("shell") - - position = ( - 1 if op == "Popen" else 0 - ) # If it's a constructor, first argument is self - shell_arguments = get_argument(args, kwargs, pos=position, name="args") - - command = None - if isinstance(shell_arguments, str): - command = shell_arguments - elif hasattr(shell_arguments, "__iter__"): - # Check if args is an iterable i.e. list, dict, tuple - # If it is we join it with spaces to run the shell_injection algorithm. - command = " ".join(shell_arguments) - - # For all operations above: call, run, check_call, Popen, check_output, default value - # of the shell property is False. - if command and shell_enabled: - vulns.run_vulnerability_scan( - kind="shell_injection", - op=f"subprocess.{op}", - args=(command,), - ) - return former_func(*args, **kwargs) - return aikido_new_func +def _subprocess_init(func, instance, args, kwargs): + shell_arguments = get_argument(args, kwargs, 0, "args") + shell_enabled = get_argument(args, kwargs, 8, "shell") + if not shell_enabled: + # default shell property is False, we only want to scan if it's True + return func(*args, **kwargs) + command = try_join_iterable(shell_arguments) + if isinstance(shell_arguments, str): + command = shell_arguments -@importhook.on_import("subprocess") -def on_subprocess_import(subprocess): - """ - Hook 'n wrap on `subproccess`, wrapping multiple functions - Returns : Modified subprocess object - """ - modified_subprocess = importhook.copy_module(subprocess) - for op in SUBPROCESS_OPERATIONS: - former_func = copy.deepcopy(getattr(subprocess, op)) - setattr( - modified_subprocess, - op, - generate_aikido_function(op=op, former_func=former_func), + if command: + vulns.run_vulnerability_scan( + kind="shell_injection", + op=f"subprocess.Popen", + args=(command,), ) - # Wrap Class Popen seperately: - former_popen_constructor = copy.deepcopy(subprocess.Popen.__init__) - setattr( - getattr(modified_subprocess, "Popen"), - "__init__", # Popen is a class, modify it's constructor - generate_aikido_function(op="Popen", former_func=former_popen_constructor), - ) + return func(*args, **kwargs) + - return modified_subprocess +def try_join_iterable(iterable): + try: + return " ".join(iterable) + except Exception: + return None diff --git a/aikido_zen/sinks/tests/subprocess_test.py b/aikido_zen/sinks/tests/subprocess_test.py index a155725b..df0485d8 100644 --- a/aikido_zen/sinks/tests/subprocess_test.py +++ b/aikido_zen/sinks/tests/subprocess_test.py @@ -171,7 +171,7 @@ def test_subprocess_check_output(): ) as mock_run_vulnerability_scan: import subprocess - op = "subprocess.check_output" + op = "subprocess.Popen" subprocess.check_output(["ls", "-la"], shell=True) args = ("ls -la",) @@ -198,7 +198,7 @@ def test_subprocess_check_output(): mock_run_vulnerability_scan.assert_called_with(kind=kind, op=op, args=args) -def test_subprocess_check_output(): +def test_subprocess_check_output_2(): with patch( "aikido_zen.vulnerabilities.run_vulnerability_scan" ) as mock_run_vulnerability_scan: From 32034d475072f36fafcb2d1c566ca3ec54c3cf34 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 13:03:46 +0200 Subject: [PATCH 28/60] pymysql patches change order --- aikido_zen/sinks/pymysql.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/aikido_zen/sinks/pymysql.py b/aikido_zen/sinks/pymysql.py index bc99cc06..765d0ae7 100644 --- a/aikido_zen/sinks/pymysql.py +++ b/aikido_zen/sinks/pymysql.py @@ -12,6 +12,21 @@ REQUIRED_PYMYSQL_VERSION = "0.9.0" +@when_imported("pymysql.cursors") +def patch(m): + """ + patching `pymysql.cursors` + - patches Cursor.execute(query) + - patches Cursor.executemany(query) + https://github.com/PyMySQL/PyMySQL/blob/95635f587ba9076e71a223b113efb08ac34a361d/pymysql/cursors.py#L133 + """ + if not is_package_compatible("pymysql", REQUIRED_PYMYSQL_VERSION): + return + + try_wrap_function_wrapper(m, "Cursor.execute", _execute) + try_wrap_function_wrapper(m, "Cursor.executemany", _executemany) + + def _execute(func, instance, args, kwargs): query = get_argument(args, kwargs, 0, "query") if isinstance(query, bytearray): @@ -33,18 +48,3 @@ def _executemany(func, instance, args, kwargs): ) return func(*args, **kwargs) - - -@when_imported("pymysql.cursors") -def patch(m): - """ - patching `pymysql.cursors` - - patches Cursor.execute(query) - - patches Cursor.executemany(query) - https://github.com/PyMySQL/PyMySQL/blob/95635f587ba9076e71a223b113efb08ac34a361d/pymysql/cursors.py#L133 - """ - if not is_package_compatible("pymysql", REQUIRED_PYMYSQL_VERSION): - return - - try_wrap_function_wrapper(m, "Cursor.execute", _execute) - try_wrap_function_wrapper(m, "Cursor.executemany", _executemany) From 7dc0a6f925e17d232a8e1502b7b0b8be3b7123d7 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 16:23:09 +0200 Subject: [PATCH 29/60] move back to bottom, python order for pymysql, subprocess --- aikido_zen/sinks/pymysql.py | 31 +++++++++++++++---------------- aikido_zen/sinks/subprocess.py | 26 +++++++++++++------------- 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/aikido_zen/sinks/pymysql.py b/aikido_zen/sinks/pymysql.py index 765d0ae7..193eb0bc 100644 --- a/aikido_zen/sinks/pymysql.py +++ b/aikido_zen/sinks/pymysql.py @@ -8,25 +8,9 @@ from aikido_zen.helpers.get_argument import get_argument from aikido_zen.sinks import try_wrap_function_wrapper - REQUIRED_PYMYSQL_VERSION = "0.9.0" -@when_imported("pymysql.cursors") -def patch(m): - """ - patching `pymysql.cursors` - - patches Cursor.execute(query) - - patches Cursor.executemany(query) - https://github.com/PyMySQL/PyMySQL/blob/95635f587ba9076e71a223b113efb08ac34a361d/pymysql/cursors.py#L133 - """ - if not is_package_compatible("pymysql", REQUIRED_PYMYSQL_VERSION): - return - - try_wrap_function_wrapper(m, "Cursor.execute", _execute) - try_wrap_function_wrapper(m, "Cursor.executemany", _executemany) - - def _execute(func, instance, args, kwargs): query = get_argument(args, kwargs, 0, "query") if isinstance(query, bytearray): @@ -48,3 +32,18 @@ def _executemany(func, instance, args, kwargs): ) return func(*args, **kwargs) + + +@when_imported("pymysql.cursors") +def patch(m): + """ + patching `pymysql.cursors` + - patches Cursor.execute(query) + - patches Cursor.executemany(query) + https://github.com/PyMySQL/PyMySQL/blob/95635f587ba9076e71a223b113efb08ac34a361d/pymysql/cursors.py#L133 + """ + if not is_package_compatible("pymysql", REQUIRED_PYMYSQL_VERSION): + return + + try_wrap_function_wrapper(m, "Cursor.execute", _execute) + try_wrap_function_wrapper(m, "Cursor.executemany", _executemany) diff --git a/aikido_zen/sinks/subprocess.py b/aikido_zen/sinks/subprocess.py index cb8ee33c..3da552c7 100644 --- a/aikido_zen/sinks/subprocess.py +++ b/aikido_zen/sinks/subprocess.py @@ -8,14 +8,11 @@ from aikido_zen.sinks import try_wrap_function_wrapper -@when_imported("subprocess") -def patch(m): - """ - patching subprocess module - - patches Popen.__init__ constructor - - does not patch: check_output, check_call, call, and run (call Popen class) - """ - try_wrap_function_wrapper(m, "Popen.__init__", _subprocess_init) +def try_join_iterable(iterable): + try: + return " ".join(iterable) + except Exception: + return None def _subprocess_init(func, instance, args, kwargs): @@ -39,8 +36,11 @@ def _subprocess_init(func, instance, args, kwargs): return func(*args, **kwargs) -def try_join_iterable(iterable): - try: - return " ".join(iterable) - except Exception: - return None +@when_imported("subprocess") +def patch(m): + """ + patching subprocess module + - patches Popen.__init__ constructor + - does not patch: check_output, check_call, call, and run (call Popen class) + """ + try_wrap_function_wrapper(m, "Popen.__init__", _subprocess_init) From e16b8ed86e72380f34c3df087d79ac1b9d5e0474 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 16:26:25 +0200 Subject: [PATCH 30/60] convert os_system patch --- aikido_zen/sinks/os_system.py | 43 +++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/aikido_zen/sinks/os_system.py b/aikido_zen/sinks/os_system.py index 942973b0..387c2f2d 100644 --- a/aikido_zen/sinks/os_system.py +++ b/aikido_zen/sinks/os_system.py @@ -2,28 +2,31 @@ Sink module for `os`, wrapping os.system """ -import aikido_zen.importhook as importhook +from wrapt import when_imported + import aikido_zen.vulnerabilities as vulns +from aikido_zen.helpers.get_argument import get_argument +from aikido_zen.sinks import try_wrap_function_wrapper -@importhook.on_import("os") -def on_os_import(os): - """ - Hook 'n wrap on `os.system()` function - Returns : Modified os object - We don't wrap os.popen() since this command uses subprocess.Popen, which we - already wrap and protect in the subprocess.py sink. - We also don't wrap os.execl, os.execle, os.execlp, ... because these should only be vulnerable - to argument injection, which we currently don't protect against. - """ - modified_os = importhook.copy_module(os) +def _system(func, instance, args, kwargs): + command = get_argument(args, kwargs, 0, "command") + if not isinstance(command, str): + return func(*args, **kwargs) + + vulns.run_vulnerability_scan( + kind="shell_injection", op="os.system", args=(command,) + ) - def aikido_new_system(command, *args, **kwargs): - if isinstance(command, str): - vulns.run_vulnerability_scan( - kind="shell_injection", op="os.system", args=(command,) - ) - return os.system(command, *args, **kwargs) + return func(*args, **kwargs) - setattr(modified_os, "system", aikido_new_system) - return modified_os + +@when_imported("os") +def patch(m): + """ + patching os module + - patches os.system for shell injection + - does not patch: os.popen -> uses subprocess.Popen + - does not patch: os.execl, os.execle, os.execlp, ... -> only argument injection + """ + try_wrap_function_wrapper(m, "system", _system) From 15a28eb5cf2846a82ac23b84a1547c193fa31705 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 16:35:31 +0200 Subject: [PATCH 31/60] pymongo convert code to wrapt code --- aikido_zen/sinks/pymongo.py | 182 ++++++++++++++++++++---------------- 1 file changed, 102 insertions(+), 80 deletions(-) diff --git a/aikido_zen/sinks/pymongo.py b/aikido_zen/sinks/pymongo.py index 0db9bebe..a20b7a1d 100644 --- a/aikido_zen/sinks/pymongo.py +++ b/aikido_zen/sinks/pymongo.py @@ -2,92 +2,114 @@ Sink module for `pymongo` """ -from copy import deepcopy -import aikido_zen.importhook as importhook -from aikido_zen.helpers.logging import logger +from wrapt import when_imported + +from aikido_zen.helpers.get_argument import get_argument import aikido_zen.background_process.packages as pkgs import aikido_zen.vulnerabilities as vulns - -# find_one not present in list since find_one calls find function. - -OPERATIONS_WITH_FILTER = [ - ("replace_one", [0, "filter"]), - ("update_one", [0, "filter"]), - ("update_many", [0, "filter"]), - ("delete_one", [0, "filter"]), - ("delete_many", [0, "filter"]), - ("count_documents", [0, "filter"]), - ("find_one_and_delete", [0, "filter"]), - ("find_one_and_replace", [0, "filter"]), - ("find_one_and_update", [0, "filter"]), - ("find", [0, "filter"]), - ("find_raw_batches", [0, "filter"]), - ("distinct", [1, "filter"]), - ("watch", [0, "pipeline"]), - ("aggregate", [0, "pipeline"]), - ("aggregate_raw_batches", [0, "pipeline"]), -] +from . import try_wrap_function_wrapper +from ..errors import AikidoException REQUIRED_PYMONGO_VERSION = "3.10.0" -# Synchronous : -@importhook.on_import("pymongo.collection") -def on_pymongo_import(pymongo): +@when_imported("pymongo.collection") +def patch(m): """ - Hook 'n wrap on `pymongo.collection` - Our goal is to wrap the following functions in the Collection class : - https://github.com/mongodb/mongo-python-driver/blob/98658cfd1fea42680a178373333bf27f41153759/pymongo/synchronous/collection.py#L136 - Returns : Modified pymongo.collection.Collection object + patching pymongo.collection + - patches Collection.*(filter, ...) + - patches Collection.*(..., filter, ...) + - patches Collection.*(pipeline, ...) + - patches Collection.bulk_write + src: https://github.com/mongodb/mongo-python-driver/blob/98658cfd1fea42680a178373333bf27f41153759/pymongo/synchronous/collection.py#L136 """ if not pkgs.is_package_compatible("pymongo", REQUIRED_PYMONGO_VERSION): - return pymongo - modified_pymongo = importhook.copy_module(pymongo) - for op_data in OPERATIONS_WITH_FILTER: - op = op_data[0] - if not hasattr(pymongo.Collection, op): - logger.warning("Operation `%s` not found on Collection object.", op) - - prev_func = deepcopy(getattr(pymongo.Collection, op)) - - def wrapped_op_func( - self, - *args, - prev_func=prev_func, - op_data=op_data, - **kwargs, - ): - op, spot, key = op_data[0], op_data[1][0], op_data[1][1] - data = None - if kwargs.get(key, None): - # Keyword found, setting data - data = kwargs.get(key) - elif len(args) > spot and args[spot]: - data = args[spot] - if data: - vulns.run_vulnerability_scan( - kind="nosql_injection", - op=f"pymongo.collection.Collection.{op}", - args=(data,), - ) - - return prev_func(self, *args, **kwargs) - - setattr(modified_pymongo.Collection, op, wrapped_op_func) - - # Add bulk_write support : - former_bulk_write = deepcopy(pymongo.Collection.bulk_write) - - def aikido_bulk_write(self, requests, *args, **kwargs): - for request in requests: - if hasattr(request, "_filter"): - # Requested operation has a filter - vulns.run_vulnerability_scan( - kind="nosql_injection", - op="pymongo.collection.Collection.bulk_write", - args=(request._filter,), - ) - return former_bulk_write(self, requests, *args, **kwargs) - - setattr(modified_pymongo.Collection, "bulk_write", aikido_bulk_write) - return modified_pymongo + return + + # func(filter, ...) + try_wrap_function_wrapper(m, "Collection.replace_one", _func_filter_first) + try_wrap_function_wrapper(m, "Collection.update_one", _func_filter_first) + try_wrap_function_wrapper(m, "Collection.update_many", _func_filter_first) + try_wrap_function_wrapper(m, "Collection.delete_one", _func_filter_first) + try_wrap_function_wrapper(m, "Collection.delete_many", _func_filter_first) + try_wrap_function_wrapper(m, "Collection.count_documents", _func_filter_first) + try_wrap_function_wrapper(m, "Collection.find_one_and_delete", _func_filter_first) + try_wrap_function_wrapper(m, "Collection.find_one_and_replace", _func_filter_first) + try_wrap_function_wrapper(m, "Collection.find_one_and_update", _func_filter_first) + try_wrap_function_wrapper(m, "Collection.find", _func_filter_first) + try_wrap_function_wrapper(m, "Collection.find_raw_batches", _func_filter_first) + # find_one not present in list since find_one calls find function. + + # func(..., filter, ...) + try_wrap_function_wrapper(m, "Collection.distinct", _func_filter_second) + + # func(pipeline, ...) + try_wrap_function_wrapper(m, "Collection.watch", _func_pipeline) + try_wrap_function_wrapper(m, "Collection.aggregate", _func_pipeline) + try_wrap_function_wrapper(m, "Collection.aggregate_raw_batches", _func_pipeline) + + # bulk_write + try_wrap_function_wrapper(m, "Collection.bulk_write", _bulk_write) + + +def _func_filter_first(func, instance, args, kwargs): + """Collection.func(filter, ...)""" + nosql_filter = get_argument(args, kwargs, 0, "filter") + if not nosql_filter: + return func(*args, **kwargs) + + vulns.run_vulnerability_scan( + kind="nosql_injection", + op=f"pymongo.collection.Collection.{func.__name__}", + args=(nosql_filter,), + ) + return func(*args, **kwargs) + + +def _func_filter_second(func, instance, args, kwargs): + """Collection.func(..., filter, ...)""" + nosql_filter = get_argument(args, kwargs, 1, "filter") + if not nosql_filter: + return func(*args, **kwargs) + + vulns.run_vulnerability_scan( + kind="nosql_injection", + op=f"pymongo.collection.Collection.{func.__name__}", + args=(nosql_filter,), + ) + return func(*args, **kwargs) + + +def _func_pipeline(func, instance, args, kwargs): + """Collection.func(pipeline, ...)""" + nosql_pipeline = get_argument(args, kwargs, 0, "pipeline") + if not nosql_pipeline: + return func(*args, **kwargs) + + vulns.run_vulnerability_scan( + kind="nosql_injection", + op=f"pymongo.collection.Collection.{func.__name__}", + args=(nosql_pipeline,), + ) + return func(*args, **kwargs) + + +def _bulk_write(func, instance, args, kwargs): + requests = get_argument(args, kwargs, 0, "requests") + + # Filter requests that contain "_filter" + requests_with_filter = [req for req in requests if hasattr(req, "_filter")] + # Run vulnerability scans for each filtered request + for request in requests_with_filter: + try: + vulns.run_vulnerability_scan( + kind="nosql_injection", + op="pymongo.collection.Collection.bulk_write", + args=(request._filter,), + ) + except AikidoException as e: + raise e + except Exception: + pass # Log or handle the exception if needed + + return func(*args, **kwargs) From 23e5fcfdc234fd41d771ea2c4903cdd4ee66812a Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 16:42:30 +0200 Subject: [PATCH 32/60] convert mysqlclient --- aikido_zen/sinks/mysqlclient.py | 67 ++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/aikido_zen/sinks/mysqlclient.py b/aikido_zen/sinks/mysqlclient.py index ca712aca..1be85f49 100644 --- a/aikido_zen/sinks/mysqlclient.py +++ b/aikido_zen/sinks/mysqlclient.py @@ -2,43 +2,48 @@ Sink module for `mysqlclient` """ -import copy -import aikido_zen.importhook as importhook +from wrapt import when_imported + from aikido_zen.background_process.packages import is_package_compatible -from aikido_zen.helpers.logging import logger +from aikido_zen.helpers.get_argument import get_argument import aikido_zen.vulnerabilities as vulns +from aikido_zen.sinks import try_wrap_function_wrapper REQUIRED_MYSQLCLIENT_VERSION = "1.5.0" -@importhook.on_import("MySQLdb.cursors") -def on_mysqlclient_import(mysql): +@when_imported("MySQLdb.cursors") +def patch(m): """ - Hook 'n wrap on `MySQLdb.cursors` - Our goal is to wrap the query() function of the Connection class : - https://github.com/PyMySQL/mysqlclient/blob/9fd238b9e3105dcbed2b009a916828a38d1f0904/src/MySQLdb/connections.py#L257 - Returns : Modified MySQLdb.connections object + patching MySQLdb.cursors (mysqlclient) + - patches Cursor.execute(query, ...) + - patches Cursor.executemany(query, ...) """ if not is_package_compatible("mysqlclient", REQUIRED_MYSQLCLIENT_VERSION): - return mysql - modified_mysql = importhook.copy_module(mysql) - prev_execute_func = copy.deepcopy(mysql.Cursor.execute) - prev_executemany_func = copy.deepcopy(mysql.Cursor.executemany) - - def aikido_new_execute(self, query, args=None): - if isinstance(query, bytearray): - logger.debug("Query is bytearray, normally comes from executemany.") - return prev_execute_func(self, query, args) - vulns.run_vulnerability_scan( - kind="sql_injection", op="MySQLdb.Cursor.execute", args=(query, "mysql") - ) - return prev_execute_func(self, query, args) - - def aikido_new_executemany(self, query, args): - op = "MySQLdb.Cursor.executemany" - vulns.run_vulnerability_scan(kind="sql_injection", op=op, args=(query, "mysql")) - return prev_executemany_func(self, query, args) - - setattr(mysql.Cursor, "execute", aikido_new_execute) - setattr(mysql.Cursor, "executemany", aikido_new_executemany) - return modified_mysql + return + + try_wrap_function_wrapper(m, "Cursor.execute", _execute) + try_wrap_function_wrapper(m, "Cursor.executemany", _executemany) + + +def _execute(func, instance, args, kwargs): + query = get_argument(args, kwargs, 0, "query") + if isinstance(query, bytearray): + # If query is type bytearray, it will be picked up by our wrapping of executemany + return func(*args, **kwargs) + + vulns.run_vulnerability_scan( + kind="sql_injection", op="MySQLdb.Cursor.execute", args=(query, "mysql") + ) + + return func(*args, **kwargs) + + +def _executemany(func, instance, args, kwargs): + query = get_argument(args, kwargs, 0, "query") + + vulns.run_vulnerability_scan( + kind="sql_injection", op="MySQLdb.Cursor.executemany", args=(query, "mysql") + ) + + return func(*args, **kwargs) From 76894deae8b4c61d19098ef3bbf1bf571d777700 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 21:21:02 +0200 Subject: [PATCH 33/60] convert io module --- aikido_zen/sinks/io.py | 50 +++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/aikido_zen/sinks/io.py b/aikido_zen/sinks/io.py index 15966189..9fb67aab 100644 --- a/aikido_zen/sinks/io.py +++ b/aikido_zen/sinks/io.py @@ -2,34 +2,38 @@ Sink module for python's `io` """ -import copy -import aikido_zen.importhook as importhook +from wrapt import when_imported import aikido_zen.vulnerabilities as vulns +from aikido_zen.helpers.get_argument import get_argument +from aikido_zen.sinks import try_wrap_function_wrapper -KIND = "path_traversal" +def _open(func, instance, args, kwargs): + file = get_argument(args, kwargs, 0, "file") + if not file: + return func(*args, **kwargs) + + vulns.run_vulnerability_scan(kind="path_traversal", op="io.open", args=(file,)) + + return func(*args, **kwargs) -@importhook.on_import("io") -def on_io_import(io): - """ - Hook 'n wrap on `io`, wrapping io.open(...) and io.open_code(...) - Returns : Modified io object - """ - modified_io = importhook.copy_module(io) - former_open_func = copy.deepcopy(io.open) - former_open_code_func = copy.deepcopy(io.open_code) - def aikido_open_func(file, *args, **kwargs): - if file: - vulns.run_vulnerability_scan(kind=KIND, op="io.open", args=(file,)) - return former_open_func(file, *args, **kwargs) +def _open_code(func, instance, args, kwargs): + path = get_argument(args, kwargs, 0, "path") + if not path: + return func(*args, **kwargs) - def aikido_open_code_func(path): - if path: - vulns.run_vulnerability_scan(kind=KIND, op="io.open_code", args=(path,)) - return former_open_code_func(path) + vulns.run_vulnerability_scan(kind="path_traversal", op="io.open_code", args=(path,)) - setattr(modified_io, "open", aikido_open_func) - setattr(modified_io, "open_code", aikido_open_code_func) + return func(*args, **kwargs) - return modified_io + +@when_imported("io") +def patch(m): + """ + patching module io + - patches io.open(file, ...) + - patches io.open_code(path) + """ + try_wrap_function_wrapper(m, "open", _open) + try_wrap_function_wrapper(m, "open_code", _open_code) From afe9b7793c82eaecde6df9763506fe07d9f8b8e4 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 21:34:12 +0200 Subject: [PATCH 34/60] Convert shutil module --- aikido_zen/sinks/shutil.py | 62 ++++++++++++++------------------------ 1 file changed, 23 insertions(+), 39 deletions(-) diff --git a/aikido_zen/sinks/shutil.py b/aikido_zen/sinks/shutil.py index 1e04e7c2..22599a40 100644 --- a/aikido_zen/sinks/shutil.py +++ b/aikido_zen/sinks/shutil.py @@ -2,51 +2,35 @@ Sink module for python's `shutil` """ -import copy -import aikido_zen.importhook as importhook +from wrapt import when_imported + import aikido_zen.vulnerabilities as vulns +from aikido_zen.helpers.get_argument import get_argument +from aikido_zen.sinks import try_wrap_function_wrapper -# File functions func(src, dst, *, **) -SHUTIL_SRC_DST_FUNCTIONS = [ - "copymode", - "copystat", - "copytree", - "move", -] -# shutil.copyfile(src, dst, *, **) => builtins.open -# shutil.copy(src, dst, *, **) => builtins.open -# shutil.copy2(src, dst, *, **) => builtins.open +def _shutil_func(func, instance, args, kwargs): + source = get_argument(args, kwargs, 0, "src") + destination = get_argument(args, kwargs, 1, "dst") -def generate_aikido_function(aik_op, func): - """ - Returns a generated aikido function given an operation - and the previous function - """ + kind = "path_traversal" + op = f"shutil.{func.__name__}" + if source: + vulns.run_vulnerability_scan(kind, op, (source,)) + if destination: + vulns.run_vulnerability_scan(kind, op, (destination,)) - def wrapper(src, dst, *args, **kwargs): - kind = "path_traversal" - op = f"shutil.{aik_op}" - if src: - vulns.run_vulnerability_scan(kind, op, args=(src,)) - if dst: - vulns.run_vulnerability_scan(kind, op, args=(dst,)) - return func(src, dst, *args, **kwargs) + return func(*args, **kwargs) - return wrapper - -@importhook.on_import("shutil") -def on_shutil_import(shutil): +@when_imported("shutil") +def patch(m): """ - Hook 'n wrap on `shutil`, python's built-in functions - Our goal is to wrap functions found in SHUTIL_SRC_DST_FUNCTIONS - Returns : Modified shutil object + patching module shutil + - patches: copymode, copystat, copytree, move + - does not patch: copyfile, copy, copy2 -> uses builtins.open """ - modified_shutil = importhook.copy_module(shutil) - for op in SHUTIL_SRC_DST_FUNCTIONS: - # Wrap shutil. functions - aikido_new_func = generate_aikido_function(op, getattr(shutil, op)) - setattr(modified_shutil, op, aikido_new_func) - - return modified_shutil + try_wrap_function_wrapper(m, "copymode", _shutil_func) + try_wrap_function_wrapper(m, "copystat", _shutil_func) + try_wrap_function_wrapper(m, "copytree", _shutil_func) + try_wrap_function_wrapper(m, "move", _shutil_func) From 142770dcdac688d832c96ce51b25935735cdf2d9 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 21:34:18 +0200 Subject: [PATCH 35/60] Convert asyncpg module --- aikido_zen/sinks/asyncpg.py | 66 +++++++++++-------------------------- 1 file changed, 19 insertions(+), 47 deletions(-) diff --git a/aikido_zen/sinks/asyncpg.py b/aikido_zen/sinks/asyncpg.py index bfca59fc..664a276a 100644 --- a/aikido_zen/sinks/asyncpg.py +++ b/aikido_zen/sinks/asyncpg.py @@ -2,64 +2,36 @@ Sink module for `asyncpg` """ -import copy -import aikido_zen.importhook as importhook +from wrapt import when_imported from aikido_zen.background_process.packages import is_package_compatible import aikido_zen.vulnerabilities as vulns -from aikido_zen.helpers.logging import logger +from aikido_zen.helpers.get_argument import get_argument +from aikido_zen.sinks import try_wrap_function_wrapper REQUIRED_ASYNCPG_VERSION = "0.27.0" -@importhook.on_import("asyncpg.connection") -def on_asyncpg_import(asyncpg): +@when_imported("asyncpg.connection") +def patch(m): """ - Hook 'n wrap on `asyncpg.connection` - * the Cursor classes in asyncpg.cursor are only used to fetch data. (Currently not supported) - * Pool class uses Connection class (Wrapping supported for Connection class) - * _execute(...) get's called by all except execute and executemany - Our goal is to wrap the _execute(), execute(), executemany() functions in Connection class : - https://github.com/MagicStack/asyncpg/blob/85d7eed40637e7cad73a44ed2439ffeb2a8dc1c2/asyncpg/connection.py#L43 - Returns : Modified asyncpg.connection object + patching module asyncpg.connection + - patches Connection.execute, Connection.executemany, Connection._execute + - doesn't patch Cursor class -> are only used to fetch data. + - doesn't patch Pool class -> uses Connection class + src: https://github.com/MagicStack/asyncpg/blob/85d7eed40637e7cad73a44ed2439ffeb2a8dc1c2/asyncpg/connection.py#L43 """ if not is_package_compatible("asyncpg", REQUIRED_ASYNCPG_VERSION): - return asyncpg - modified_asyncpg = importhook.copy_module(asyncpg) + return - # pylint: disable=protected-access # We need to wrap this function - former__execute = copy.deepcopy(asyncpg.Connection._execute) - former_executemany = copy.deepcopy(asyncpg.Connection.executemany) - former_execute = copy.deepcopy(asyncpg.Connection.execute) + try_wrap_function_wrapper(m, "Connection.execute", _execute) + try_wrap_function_wrapper(m, "Connection.executemany", _execute) + try_wrap_function_wrapper(m, "Connection._execute", _execute) - def aikido_new__execute(_self, query, *args, **kwargs): - vulns.run_vulnerability_scan( - kind="sql_injection", - op="asyncpg.connection.Connection._execute", - args=(query, "postgres"), - ) - return former__execute(_self, query, *args, **kwargs) +def _execute(func, instance, args, kwargs): + query = get_argument(args, kwargs, 0, "query") - def aikido_new_executemany(_self, query, *args, **kwargs): - # This query is just a string, not a list, see docs. - vulns.run_vulnerability_scan( - kind="sql_injection", - op="asyncpg.connection.Connection.executemany", - args=(query, "postgres"), - ) - return former_executemany(_self, query, *args, **kwargs) + op = f"asyncpg.connection.Connection.{func.__name__}" + vulns.run_vulnerability_scan(kind="sql_injection", op=op, args=(query, "postgres")) - def aikido_new_execute(_self, query, *args, **kwargs): - vulns.run_vulnerability_scan( - kind="sql_injection", - op="asyncpg.connection.Connection.execute", - args=(query, "postgres"), - ) - return former_execute(_self, query, *args, **kwargs) - - # pylint: disable=no-member - setattr(asyncpg.Connection, "_execute", aikido_new__execute) - setattr(asyncpg.Connection, "executemany", aikido_new_executemany) - setattr(asyncpg.Connection, "execute", aikido_new_execute) - - return modified_asyncpg + return func(*args, **kwargs) From fb309e7a101a0f204c5f5d77933327e7a82d86c9 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 21:51:50 +0200 Subject: [PATCH 36/60] Convert builtins.py --- aikido_zen/sinks/builtins.py | 38 +++++++++++++++--------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/aikido_zen/sinks/builtins.py b/aikido_zen/sinks/builtins.py index 70167e45..9d3bfb25 100644 --- a/aikido_zen/sinks/builtins.py +++ b/aikido_zen/sinks/builtins.py @@ -3,34 +3,28 @@ """ from pathlib import PurePath -import aikido_zen.importhook as importhook +from wrapt import when_imported import aikido_zen.vulnerabilities as vulns +from aikido_zen.helpers.get_argument import get_argument +from aikido_zen.sinks import try_wrap_function_wrapper -def aikido_open_decorator(func): - """Decorator for open(...)""" - - def wrapper(*args, **kwargs): - # args[0] is thefunc_name filename - if len(args) > 0 and isinstance(args[0], (str, bytes, PurePath)): - vulns.run_vulnerability_scan( - kind="path_traversal", op="builtins.open", args=(args[0],) - ) +def _open(func, instance, args, kwargs): + filename = get_argument(args, kwargs, 0, "filename") + if filename is None or not isinstance(filename, (str, bytes, PurePath)): return func(*args, **kwargs) - return wrapper + vulns.run_vulnerability_scan( + kind="path_traversal", op="builtins.open", args=(filename,) + ) + + return func(*args, **kwargs) -@importhook.on_import("builtins") -def on_builtins_import(builtins): +@when_imported("builtins") +def patch(m): """ - Hook 'n wrap on `builtins`, python's built-in functions - Our goal is to wrap the open() function, which you use when opening files - Returns : Modified builtins object + patching module builtins + - patches builtins.open """ - modified_builtins = importhook.copy_module(builtins) - - # pylint: disable=no-member - setattr(builtins, "open", aikido_open_decorator(builtins.open)) - setattr(modified_builtins, "open", aikido_open_decorator(builtins.open)) - return modified_builtins + try_wrap_function_wrapper(m, "open", _open) From 91ca20dad6c0d3ded61d055007773eff6ac95968 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 22:27:46 +0200 Subject: [PATCH 37/60] define new standards for the wrapping --- aikido_zen/sinks/__init__.py | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/aikido_zen/sinks/__init__.py b/aikido_zen/sinks/__init__.py index 1ead752c..2ba6b1b7 100644 --- a/aikido_zen/sinks/__init__.py +++ b/aikido_zen/sinks/__init__.py @@ -1,10 +1,40 @@ -from wrapt import wrap_object, FunctionWrapper +from wrapt import wrap_object, FunctionWrapper, when_imported +from aikido_zen.background_process.packages import ANY_VERSION, is_package_compatible +from aikido_zen.errors import AikidoException from aikido_zen.helpers.logging import logger -def try_wrap_function_wrapper(module, name, wrapper): +def on_import(name, package="", version_requirement=ANY_VERSION): + def decorator(func): + # Reports package and checks version reqs (if necessary) + if package and not is_package_compatible(package, version_requirement): + return + + when_imported(name)(func) + + return decorator + + +def patch_function(module, name, wrapper): try: wrap_object(module, name, FunctionWrapper, (wrapper,)) except Exception as e: logger.info("Failed to wrap %s, due to: %s", module, e) + + +def before(wrapper): + def decorator(func, instance, args, kwargs): + # try-except makes sure if we make a mistake in before wrapping it gets catch-ed + try: + wrapper(func, instance, args, kwargs) + except AikidoException as e: + raise e + except Exception as e: + logger.debug( + "%s:%s wrapping-before error: %s", func.__module__, func.__name__, e + ) + + return func(*args, **kwargs) + + return decorator From dd9b4b053647126ac62d7ecfc7c23634afca061a Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 22:28:20 +0200 Subject: [PATCH 38/60] update existing modules --- aikido_zen/sinks/asyncpg.py | 8 ++-- aikido_zen/sinks/builtins.py | 4 +- aikido_zen/sinks/mysqlclient.py | 24 +++-------- aikido_zen/sinks/os_system.py | 13 +++--- aikido_zen/sinks/pymongo.py | 76 +++++++++++++-------------------- aikido_zen/sinks/pymysql.py | 23 +++------- aikido_zen/sinks/shutil.py | 17 +++----- aikido_zen/sinks/subprocess.py | 27 ++++++------ 8 files changed, 74 insertions(+), 118 deletions(-) diff --git a/aikido_zen/sinks/asyncpg.py b/aikido_zen/sinks/asyncpg.py index 664a276a..f4b47d1d 100644 --- a/aikido_zen/sinks/asyncpg.py +++ b/aikido_zen/sinks/asyncpg.py @@ -6,7 +6,7 @@ from aikido_zen.background_process.packages import is_package_compatible import aikido_zen.vulnerabilities as vulns from aikido_zen.helpers.get_argument import get_argument -from aikido_zen.sinks import try_wrap_function_wrapper +from aikido_zen.sinks import wrap_function_before REQUIRED_ASYNCPG_VERSION = "0.27.0" @@ -23,9 +23,9 @@ def patch(m): if not is_package_compatible("asyncpg", REQUIRED_ASYNCPG_VERSION): return - try_wrap_function_wrapper(m, "Connection.execute", _execute) - try_wrap_function_wrapper(m, "Connection.executemany", _execute) - try_wrap_function_wrapper(m, "Connection._execute", _execute) + wrap_function_before(m, "Connection.execute", _execute) + wrap_function_before(m, "Connection.executemany", _execute) + wrap_function_before(m, "Connection._execute", _execute) def _execute(func, instance, args, kwargs): diff --git a/aikido_zen/sinks/builtins.py b/aikido_zen/sinks/builtins.py index 9d3bfb25..034dc52f 100644 --- a/aikido_zen/sinks/builtins.py +++ b/aikido_zen/sinks/builtins.py @@ -6,7 +6,7 @@ from wrapt import when_imported import aikido_zen.vulnerabilities as vulns from aikido_zen.helpers.get_argument import get_argument -from aikido_zen.sinks import try_wrap_function_wrapper +from aikido_zen.sinks import wrap_function_before def _open(func, instance, args, kwargs): @@ -27,4 +27,4 @@ def patch(m): patching module builtins - patches builtins.open """ - try_wrap_function_wrapper(m, "open", _open) + wrap_function_before(m, "open", _open) diff --git a/aikido_zen/sinks/mysqlclient.py b/aikido_zen/sinks/mysqlclient.py index 1be85f49..5de3b91f 100644 --- a/aikido_zen/sinks/mysqlclient.py +++ b/aikido_zen/sinks/mysqlclient.py @@ -2,48 +2,38 @@ Sink module for `mysqlclient` """ -from wrapt import when_imported - -from aikido_zen.background_process.packages import is_package_compatible from aikido_zen.helpers.get_argument import get_argument import aikido_zen.vulnerabilities as vulns -from aikido_zen.sinks import try_wrap_function_wrapper - -REQUIRED_MYSQLCLIENT_VERSION = "1.5.0" +from aikido_zen.sinks import patch_function, on_import, before -@when_imported("MySQLdb.cursors") +@on_import("MySQLdb.cursors", "mysqlclient", version_requirement="1.5.0") def patch(m): """ patching MySQLdb.cursors (mysqlclient) - patches Cursor.execute(query, ...) - patches Cursor.executemany(query, ...) """ - if not is_package_compatible("mysqlclient", REQUIRED_MYSQLCLIENT_VERSION): - return - - try_wrap_function_wrapper(m, "Cursor.execute", _execute) - try_wrap_function_wrapper(m, "Cursor.executemany", _executemany) + patch_function(m, "Cursor.execute", _execute) + patch_function(m, "Cursor.executemany", _executemany) +@before def _execute(func, instance, args, kwargs): query = get_argument(args, kwargs, 0, "query") if isinstance(query, bytearray): # If query is type bytearray, it will be picked up by our wrapping of executemany - return func(*args, **kwargs) + return vulns.run_vulnerability_scan( kind="sql_injection", op="MySQLdb.Cursor.execute", args=(query, "mysql") ) - return func(*args, **kwargs) - +@before def _executemany(func, instance, args, kwargs): query = get_argument(args, kwargs, 0, "query") vulns.run_vulnerability_scan( kind="sql_injection", op="MySQLdb.Cursor.executemany", args=(query, "mysql") ) - - return func(*args, **kwargs) diff --git a/aikido_zen/sinks/os_system.py b/aikido_zen/sinks/os_system.py index 387c2f2d..52d7887b 100644 --- a/aikido_zen/sinks/os_system.py +++ b/aikido_zen/sinks/os_system.py @@ -2,26 +2,23 @@ Sink module for `os`, wrapping os.system """ -from wrapt import when_imported - import aikido_zen.vulnerabilities as vulns from aikido_zen.helpers.get_argument import get_argument -from aikido_zen.sinks import try_wrap_function_wrapper +from aikido_zen.sinks import patch_function, before, on_import +@before def _system(func, instance, args, kwargs): command = get_argument(args, kwargs, 0, "command") if not isinstance(command, str): - return func(*args, **kwargs) + return vulns.run_vulnerability_scan( kind="shell_injection", op="os.system", args=(command,) ) - return func(*args, **kwargs) - -@when_imported("os") +@on_import("os") def patch(m): """ patching os module @@ -29,4 +26,4 @@ def patch(m): - does not patch: os.popen -> uses subprocess.Popen - does not patch: os.execl, os.execle, os.execlp, ... -> only argument injection """ - try_wrap_function_wrapper(m, "system", _system) + patch_function(m, "system", _system) diff --git a/aikido_zen/sinks/pymongo.py b/aikido_zen/sinks/pymongo.py index a20b7a1d..fa1065a9 100644 --- a/aikido_zen/sinks/pymongo.py +++ b/aikido_zen/sinks/pymongo.py @@ -2,18 +2,12 @@ Sink module for `pymongo` """ -from wrapt import when_imported - from aikido_zen.helpers.get_argument import get_argument -import aikido_zen.background_process.packages as pkgs import aikido_zen.vulnerabilities as vulns -from . import try_wrap_function_wrapper -from ..errors import AikidoException - -REQUIRED_PYMONGO_VERSION = "3.10.0" +from . import patch_function, on_import, before -@when_imported("pymongo.collection") +@on_import("pymongo.collection", "pymongo", version_requirement="3.10.0") def patch(m): """ patching pymongo.collection @@ -23,93 +17,83 @@ def patch(m): - patches Collection.bulk_write src: https://github.com/mongodb/mongo-python-driver/blob/98658cfd1fea42680a178373333bf27f41153759/pymongo/synchronous/collection.py#L136 """ - if not pkgs.is_package_compatible("pymongo", REQUIRED_PYMONGO_VERSION): - return - # func(filter, ...) - try_wrap_function_wrapper(m, "Collection.replace_one", _func_filter_first) - try_wrap_function_wrapper(m, "Collection.update_one", _func_filter_first) - try_wrap_function_wrapper(m, "Collection.update_many", _func_filter_first) - try_wrap_function_wrapper(m, "Collection.delete_one", _func_filter_first) - try_wrap_function_wrapper(m, "Collection.delete_many", _func_filter_first) - try_wrap_function_wrapper(m, "Collection.count_documents", _func_filter_first) - try_wrap_function_wrapper(m, "Collection.find_one_and_delete", _func_filter_first) - try_wrap_function_wrapper(m, "Collection.find_one_and_replace", _func_filter_first) - try_wrap_function_wrapper(m, "Collection.find_one_and_update", _func_filter_first) - try_wrap_function_wrapper(m, "Collection.find", _func_filter_first) - try_wrap_function_wrapper(m, "Collection.find_raw_batches", _func_filter_first) + patch_function(m, "Collection.replace_one", _func_filter_first) + patch_function(m, "Collection.update_one", _func_filter_first) + patch_function(m, "Collection.update_many", _func_filter_first) + patch_function(m, "Collection.delete_one", _func_filter_first) + patch_function(m, "Collection.delete_many", _func_filter_first) + patch_function(m, "Collection.count_documents", _func_filter_first) + patch_function(m, "Collection.find_one_and_delete", _func_filter_first) + patch_function(m, "Collection.find_one_and_replace", _func_filter_first) + patch_function(m, "Collection.find_one_and_update", _func_filter_first) + patch_function(m, "Collection.find", _func_filter_first) + patch_function(m, "Collection.find_raw_batches", _func_filter_first) # find_one not present in list since find_one calls find function. # func(..., filter, ...) - try_wrap_function_wrapper(m, "Collection.distinct", _func_filter_second) + patch_function(m, "Collection.distinct", _func_filter_second) # func(pipeline, ...) - try_wrap_function_wrapper(m, "Collection.watch", _func_pipeline) - try_wrap_function_wrapper(m, "Collection.aggregate", _func_pipeline) - try_wrap_function_wrapper(m, "Collection.aggregate_raw_batches", _func_pipeline) + patch_function(m, "Collection.watch", _func_pipeline) + patch_function(m, "Collection.aggregate", _func_pipeline) + patch_function(m, "Collection.aggregate_raw_batches", _func_pipeline) # bulk_write - try_wrap_function_wrapper(m, "Collection.bulk_write", _bulk_write) + patch_function(m, "Collection.bulk_write", _bulk_write) +@before def _func_filter_first(func, instance, args, kwargs): """Collection.func(filter, ...)""" nosql_filter = get_argument(args, kwargs, 0, "filter") if not nosql_filter: - return func(*args, **kwargs) + return vulns.run_vulnerability_scan( kind="nosql_injection", op=f"pymongo.collection.Collection.{func.__name__}", args=(nosql_filter,), ) - return func(*args, **kwargs) +@before def _func_filter_second(func, instance, args, kwargs): """Collection.func(..., filter, ...)""" nosql_filter = get_argument(args, kwargs, 1, "filter") if not nosql_filter: - return func(*args, **kwargs) + return vulns.run_vulnerability_scan( kind="nosql_injection", op=f"pymongo.collection.Collection.{func.__name__}", args=(nosql_filter,), ) - return func(*args, **kwargs) +@before def _func_pipeline(func, instance, args, kwargs): """Collection.func(pipeline, ...)""" nosql_pipeline = get_argument(args, kwargs, 0, "pipeline") if not nosql_pipeline: - return func(*args, **kwargs) + return vulns.run_vulnerability_scan( kind="nosql_injection", op=f"pymongo.collection.Collection.{func.__name__}", args=(nosql_pipeline,), ) - return func(*args, **kwargs) +@before def _bulk_write(func, instance, args, kwargs): requests = get_argument(args, kwargs, 0, "requests") # Filter requests that contain "_filter" requests_with_filter = [req for req in requests if hasattr(req, "_filter")] - # Run vulnerability scans for each filtered request for request in requests_with_filter: - try: - vulns.run_vulnerability_scan( - kind="nosql_injection", - op="pymongo.collection.Collection.bulk_write", - args=(request._filter,), - ) - except AikidoException as e: - raise e - except Exception: - pass # Log or handle the exception if needed - - return func(*args, **kwargs) + vulns.run_vulnerability_scan( + kind="nosql_injection", + op="pymongo.collection.Collection.bulk_write", + args=(request._filter,), + ) diff --git a/aikido_zen/sinks/pymysql.py b/aikido_zen/sinks/pymysql.py index 193eb0bc..c100039b 100644 --- a/aikido_zen/sinks/pymysql.py +++ b/aikido_zen/sinks/pymysql.py @@ -2,28 +2,24 @@ Sink module for `pymysql` """ -from wrapt import when_imported -from aikido_zen.background_process.packages import is_package_compatible import aikido_zen.vulnerabilities as vulns from aikido_zen.helpers.get_argument import get_argument -from aikido_zen.sinks import try_wrap_function_wrapper - -REQUIRED_PYMYSQL_VERSION = "0.9.0" +from aikido_zen.sinks import patch_function, on_import, before +@before def _execute(func, instance, args, kwargs): query = get_argument(args, kwargs, 0, "query") if isinstance(query, bytearray): # If query is type bytearray, it will be picked up by our wrapping of executemany - return func(*args, **kwargs) + return vulns.run_vulnerability_scan( kind="sql_injection", op="pymysql.Cursor.execute", args=(query, "mysql") ) - return func(*args, **kwargs) - +@before def _executemany(func, instance, args, kwargs): query = get_argument(args, kwargs, 0, "query") @@ -31,10 +27,8 @@ def _executemany(func, instance, args, kwargs): kind="sql_injection", op="pymysql.Cursor.executemany", args=(query, "mysql") ) - return func(*args, **kwargs) - -@when_imported("pymysql.cursors") +@on_import("pymysql.cursors", "pymysql", version_requirement="0.9.0") def patch(m): """ patching `pymysql.cursors` @@ -42,8 +36,5 @@ def patch(m): - patches Cursor.executemany(query) https://github.com/PyMySQL/PyMySQL/blob/95635f587ba9076e71a223b113efb08ac34a361d/pymysql/cursors.py#L133 """ - if not is_package_compatible("pymysql", REQUIRED_PYMYSQL_VERSION): - return - - try_wrap_function_wrapper(m, "Cursor.execute", _execute) - try_wrap_function_wrapper(m, "Cursor.executemany", _executemany) + patch_function(m, "Cursor.execute", _execute) + patch_function(m, "Cursor.executemany", _executemany) diff --git a/aikido_zen/sinks/shutil.py b/aikido_zen/sinks/shutil.py index 22599a40..79f3aaa7 100644 --- a/aikido_zen/sinks/shutil.py +++ b/aikido_zen/sinks/shutil.py @@ -2,13 +2,12 @@ Sink module for python's `shutil` """ -from wrapt import when_imported - import aikido_zen.vulnerabilities as vulns from aikido_zen.helpers.get_argument import get_argument -from aikido_zen.sinks import try_wrap_function_wrapper +from aikido_zen.sinks import on_import, patch_function, before +@before def _shutil_func(func, instance, args, kwargs): source = get_argument(args, kwargs, 0, "src") destination = get_argument(args, kwargs, 1, "dst") @@ -20,17 +19,15 @@ def _shutil_func(func, instance, args, kwargs): if destination: vulns.run_vulnerability_scan(kind, op, (destination,)) - return func(*args, **kwargs) - -@when_imported("shutil") +@on_import("shutil") def patch(m): """ patching module shutil - patches: copymode, copystat, copytree, move - does not patch: copyfile, copy, copy2 -> uses builtins.open """ - try_wrap_function_wrapper(m, "copymode", _shutil_func) - try_wrap_function_wrapper(m, "copystat", _shutil_func) - try_wrap_function_wrapper(m, "copytree", _shutil_func) - try_wrap_function_wrapper(m, "move", _shutil_func) + patch_function(m, "copymode", _shutil_func) + patch_function(m, "copystat", _shutil_func) + patch_function(m, "copytree", _shutil_func) + patch_function(m, "move", _shutil_func) diff --git a/aikido_zen/sinks/subprocess.py b/aikido_zen/sinks/subprocess.py index 3da552c7..2e20fbfb 100644 --- a/aikido_zen/sinks/subprocess.py +++ b/aikido_zen/sinks/subprocess.py @@ -2,10 +2,9 @@ Sink module for `subprocess` """ -from wrapt import when_imported import aikido_zen.vulnerabilities as vulns from aikido_zen.helpers.get_argument import get_argument -from aikido_zen.sinks import try_wrap_function_wrapper +from aikido_zen.sinks import on_import, patch_function, before def try_join_iterable(iterable): @@ -15,32 +14,30 @@ def try_join_iterable(iterable): return None +@before def _subprocess_init(func, instance, args, kwargs): shell_arguments = get_argument(args, kwargs, 0, "args") shell_enabled = get_argument(args, kwargs, 8, "shell") if not shell_enabled: - # default shell property is False, we only want to scan if it's True - return func(*args, **kwargs) + return # default shell property is False, we only want to scan if it's True command = try_join_iterable(shell_arguments) if isinstance(shell_arguments, str): command = shell_arguments + if not command: + return + vulns.run_vulnerability_scan( + kind="shell_injection", + op=f"subprocess.Popen", + args=(command,), + ) - if command: - vulns.run_vulnerability_scan( - kind="shell_injection", - op=f"subprocess.Popen", - args=(command,), - ) - return func(*args, **kwargs) - - -@when_imported("subprocess") +@on_import("subprocess") def patch(m): """ patching subprocess module - patches Popen.__init__ constructor - does not patch: check_output, check_call, call, and run (call Popen class) """ - try_wrap_function_wrapper(m, "Popen.__init__", _subprocess_init) + patch_function(m, "Popen.__init__", _subprocess_init) From 9d37dc95a6f57bdf35608fabe35405132346ab3f Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 22:28:33 +0200 Subject: [PATCH 39/60] Update io module to use new system --- aikido_zen/sinks/io.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/aikido_zen/sinks/io.py b/aikido_zen/sinks/io.py index 9fb67aab..48d54308 100644 --- a/aikido_zen/sinks/io.py +++ b/aikido_zen/sinks/io.py @@ -2,38 +2,35 @@ Sink module for python's `io` """ -from wrapt import when_imported import aikido_zen.vulnerabilities as vulns from aikido_zen.helpers.get_argument import get_argument -from aikido_zen.sinks import try_wrap_function_wrapper +from aikido_zen.sinks import patch_function, before, on_import +@before def _open(func, instance, args, kwargs): file = get_argument(args, kwargs, 0, "file") if not file: - return func(*args, **kwargs) + return vulns.run_vulnerability_scan(kind="path_traversal", op="io.open", args=(file,)) - return func(*args, **kwargs) - +@before def _open_code(func, instance, args, kwargs): path = get_argument(args, kwargs, 0, "path") if not path: - return func(*args, **kwargs) + return vulns.run_vulnerability_scan(kind="path_traversal", op="io.open_code", args=(path,)) - return func(*args, **kwargs) - -@when_imported("io") +@on_import("io") def patch(m): """ patching module io - patches io.open(file, ...) - patches io.open_code(path) """ - try_wrap_function_wrapper(m, "open", _open) - try_wrap_function_wrapper(m, "open_code", _open_code) + patch_function(m, "open", _open) + patch_function(m, "open_code", _open_code) From 1dab0f2fa819377068e28c159368587e2344187a Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 22:36:17 +0200 Subject: [PATCH 40/60] Update both builtins.py and asyncpg.py to use the new patching system --- aikido_zen/sinks/asyncpg.py | 23 ++++++----------------- aikido_zen/sinks/builtins.py | 12 +++++------- 2 files changed, 11 insertions(+), 24 deletions(-) diff --git a/aikido_zen/sinks/asyncpg.py b/aikido_zen/sinks/asyncpg.py index f4b47d1d..bc42e6f4 100644 --- a/aikido_zen/sinks/asyncpg.py +++ b/aikido_zen/sinks/asyncpg.py @@ -1,17 +1,11 @@ """ Sink module for `asyncpg` """ - -from wrapt import when_imported -from aikido_zen.background_process.packages import is_package_compatible import aikido_zen.vulnerabilities as vulns from aikido_zen.helpers.get_argument import get_argument -from aikido_zen.sinks import wrap_function_before - -REQUIRED_ASYNCPG_VERSION = "0.27.0" - +from aikido_zen.sinks import patch_function, before, on_import -@when_imported("asyncpg.connection") +@on_import("asyncpg.connection", "asyncpg", version_requirement="0.27.0") def patch(m): """ patching module asyncpg.connection @@ -20,18 +14,13 @@ def patch(m): - doesn't patch Pool class -> uses Connection class src: https://github.com/MagicStack/asyncpg/blob/85d7eed40637e7cad73a44ed2439ffeb2a8dc1c2/asyncpg/connection.py#L43 """ - if not is_package_compatible("asyncpg", REQUIRED_ASYNCPG_VERSION): - return - - wrap_function_before(m, "Connection.execute", _execute) - wrap_function_before(m, "Connection.executemany", _execute) - wrap_function_before(m, "Connection._execute", _execute) - + patch_function(m, "Connection.execute", _execute) + patch_function(m, "Connection.executemany", _execute) + patch_function(m, "Connection._execute", _execute) +@before def _execute(func, instance, args, kwargs): query = get_argument(args, kwargs, 0, "query") op = f"asyncpg.connection.Connection.{func.__name__}" vulns.run_vulnerability_scan(kind="sql_injection", op=op, args=(query, "postgres")) - - return func(*args, **kwargs) diff --git a/aikido_zen/sinks/builtins.py b/aikido_zen/sinks/builtins.py index 034dc52f..ae573040 100644 --- a/aikido_zen/sinks/builtins.py +++ b/aikido_zen/sinks/builtins.py @@ -3,28 +3,26 @@ """ from pathlib import PurePath -from wrapt import when_imported import aikido_zen.vulnerabilities as vulns from aikido_zen.helpers.get_argument import get_argument -from aikido_zen.sinks import wrap_function_before +from aikido_zen.sinks import patch_function, on_import, before +@before def _open(func, instance, args, kwargs): filename = get_argument(args, kwargs, 0, "filename") if filename is None or not isinstance(filename, (str, bytes, PurePath)): - return func(*args, **kwargs) + return vulns.run_vulnerability_scan( kind="path_traversal", op="builtins.open", args=(filename,) ) - return func(*args, **kwargs) - -@when_imported("builtins") +@on_import("builtins") def patch(m): """ patching module builtins - patches builtins.open """ - wrap_function_before(m, "open", _open) + patch_function(m, "open", _open) From cffd729cf73d7912b4d7c9b5209cf3bd448f745f Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 22:58:27 +0200 Subject: [PATCH 41/60] Cleanup checks for builtins and shutil --- aikido_zen/sinks/builtins.py | 2 +- aikido_zen/sinks/shutil.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/aikido_zen/sinks/builtins.py b/aikido_zen/sinks/builtins.py index ae573040..c1dd54da 100644 --- a/aikido_zen/sinks/builtins.py +++ b/aikido_zen/sinks/builtins.py @@ -11,7 +11,7 @@ @before def _open(func, instance, args, kwargs): filename = get_argument(args, kwargs, 0, "filename") - if filename is None or not isinstance(filename, (str, bytes, PurePath)): + if not isinstance(filename, (str, bytes, PurePath)): return vulns.run_vulnerability_scan( diff --git a/aikido_zen/sinks/shutil.py b/aikido_zen/sinks/shutil.py index 79f3aaa7..666191ff 100644 --- a/aikido_zen/sinks/shutil.py +++ b/aikido_zen/sinks/shutil.py @@ -14,9 +14,9 @@ def _shutil_func(func, instance, args, kwargs): kind = "path_traversal" op = f"shutil.{func.__name__}" - if source: + if isinstance(source, str): vulns.run_vulnerability_scan(kind, op, (source,)) - if destination: + if isinstance(source, str): vulns.run_vulnerability_scan(kind, op, (destination,)) From 0196b11a0d23abb756737631fe50ca23256a86cc Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 23:00:16 +0200 Subject: [PATCH 42/60] linting for asyncpg.py --- aikido_zen/sinks/asyncpg.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/aikido_zen/sinks/asyncpg.py b/aikido_zen/sinks/asyncpg.py index bc42e6f4..3c24de65 100644 --- a/aikido_zen/sinks/asyncpg.py +++ b/aikido_zen/sinks/asyncpg.py @@ -1,10 +1,12 @@ """ Sink module for `asyncpg` """ + import aikido_zen.vulnerabilities as vulns from aikido_zen.helpers.get_argument import get_argument from aikido_zen.sinks import patch_function, before, on_import + @on_import("asyncpg.connection", "asyncpg", version_requirement="0.27.0") def patch(m): """ @@ -18,6 +20,7 @@ def patch(m): patch_function(m, "Connection.executemany", _execute) patch_function(m, "Connection._execute", _execute) + @before def _execute(func, instance, args, kwargs): query = get_argument(args, kwargs, 0, "query") From 6a9711d9dbdc6ca117b16a9564092cfb9e09cae9 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 23:03:20 +0200 Subject: [PATCH 43/60] Cleanup the patching module --- aikido_zen/sinks/__init__.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/aikido_zen/sinks/__init__.py b/aikido_zen/sinks/__init__.py index 2ba6b1b7..64be766b 100644 --- a/aikido_zen/sinks/__init__.py +++ b/aikido_zen/sinks/__init__.py @@ -1,40 +1,49 @@ from wrapt import wrap_object, FunctionWrapper, when_imported - from aikido_zen.background_process.packages import ANY_VERSION, is_package_compatible from aikido_zen.errors import AikidoException from aikido_zen.helpers.logging import logger def on_import(name, package="", version_requirement=ANY_VERSION): + """ + Decorator to register a function to be called when a package is imported. + It checks if the package is compatible with the specified version requirement. + """ + def decorator(func): - # Reports package and checks version reqs (if necessary) if package and not is_package_compatible(package, version_requirement): return - when_imported(name)(func) + when_imported(name)(func) # Register the function to be called on import return decorator def patch_function(module, name, wrapper): + """ + Patches a function in the specified module with a wrapper function. + """ try: wrap_object(module, name, FunctionWrapper, (wrapper,)) except Exception as e: - logger.info("Failed to wrap %s, due to: %s", module, e) + logger.info("Failed to wrap %s:%s, due to: %s", module, name, e) def before(wrapper): + """ + Surrounds a patch with try-except and calls the original function at the end + """ + def decorator(func, instance, args, kwargs): - # try-except makes sure if we make a mistake in before wrapping it gets catch-ed try: - wrapper(func, instance, args, kwargs) + wrapper(func, instance, args, kwargs) # Call the patch except AikidoException as e: - raise e + raise e # Re-raise AikidoException except Exception as e: logger.debug( "%s:%s wrapping-before error: %s", func.__module__, func.__name__, e ) - return func(*args, **kwargs) + return func(*args, **kwargs) # Call the original function return decorator From 57faa805d5e8bd57e8f35368ecdc8514173e7594 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 23:22:04 +0200 Subject: [PATCH 44/60] Convert os.py --- aikido_zen/sinks/os.py | 110 +++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 66 deletions(-) diff --git a/aikido_zen/sinks/os.py b/aikido_zen/sinks/os.py index 9cf4f880..02939d0a 100644 --- a/aikido_zen/sinks/os.py +++ b/aikido_zen/sinks/os.py @@ -2,78 +2,56 @@ Sink module for python's `os` """ -import copy from pathlib import PurePath -import aikido_zen.importhook as importhook import aikido_zen.vulnerabilities as vulns +from aikido_zen.errors import AikidoException +from aikido_zen.importhook import on_import +from aikido_zen.sinks import before, patch_function -# os.func(...) functions, can have a filename and destination. -OS_FILE_FUNCTIONS = [ - "access", - "chmod", - "chown", - "mkdir", - "listdir", - "readlink", - "unlink", - "rename", - "rmdir", - "remove", - "symlink", - "link", - "walk", - "open", -] -# os.path.realpath, os.path.abspath aren't wrapped, since they use os.path.join -OS_PATH_FUNCTIONS = ["getsize", "join", "expanduser", "expandvars"] +@before +def _os_patch(func, instance, args, kwargs): + possible_paths = args + tuple(kwargs.values()) + for path in possible_paths: + if not isinstance(path, (str, bytes, PurePath)): + continue + # change op if it's an os.path function + op = f"os.{func.__name__}" + if func.__name__ in ("getsize", "join", "expanduser", "expandvars"): + op = f"os.path.{func.__name__}" -# os.makedirs() is not wrapped since it uses os.mkdir() which we wrap -# os.path.exists() and functions alike are not wrapped for performance reasons. -# We also don't wrap the stat library : https://docs.python.org/3/library/stat.html + vulns.run_vulnerability_scan(kind="path_traversal", op=op, args=(path,)) -def generate_aikido_function(op, former_func): +@on_import("os") +def patch(m): """ - Returns a generated aikido function given an operation - and the previous function + patching module os + - patches os.* functions that take in paths + - patches os.path.* functions that take in paths + - doesn't patch os.makedirs -> uses os.mkdir + - doesn't patch os.path.realpath or os.path.abspath -> uses os.path.join + - doesn't patch os.path.exists and others -> to big of a performance impact + - doesn't patch stat library https://docs.python.org/3/library/stat.html """ - - def aikido_new_func(*args, op=op, former_func=former_func, **kwargs): - for arg in args: - if isinstance(arg, (str, bytes, PurePath)): - vulns.run_vulnerability_scan( - kind="path_traversal", op=f"os.{op}", args=(arg,) - ) - return former_func(*args, **kwargs) - - return aikido_new_func - - -@importhook.on_import("os") -def on_os_import(os): - """ - Hook 'n wrap on `os` module, wrapping os.func(...) and os.path.func(...) - Returns : Modified os object - """ - modified_os = importhook.copy_module(os) - for op in OS_FILE_FUNCTIONS: - # Wrap os. functions - if not hasattr(os, op): - continue # Don't wrap methods that are specific to the OS (e.g. chown) - former_func = copy.deepcopy(getattr(os, op)) - aikido_new_func = generate_aikido_function(op, former_func) - setattr(os, op, aikido_new_func) - setattr(modified_os, op, aikido_new_func) - - for op in OS_PATH_FUNCTIONS: - # Wrap os.path functions - if not hasattr(os.path, op): - continue # Don't wrap methods that are specific to the OS - former_func = copy.deepcopy(getattr(os.path, op)) - aikido_new_func = generate_aikido_function(f"path.{op}", former_func) - setattr(os.path, op, aikido_new_func) - # pylint: disable=no-member - setattr(modified_os.path, op, aikido_new_func) - - return modified_os + # os.*(...) patches + patch_function(m, "access", _os_patch) + patch_function(m, "chmod", _os_patch) + patch_function(m, "chown", _os_patch) + patch_function(m, "mkdir", _os_patch) + patch_function(m, "listdir", _os_patch) + patch_function(m, "readlink", _os_patch) + patch_function(m, "unlink", _os_patch) + patch_function(m, "rename", _os_patch) + patch_function(m, "rmdir", _os_patch) + patch_function(m, "remove", _os_patch) + patch_function(m, "symlink", _os_patch) + patch_function(m, "link", _os_patch) + patch_function(m, "walk", _os_patch) + patch_function(m, "open", _os_patch) + + # os.path.*(...) patches + patch_function(m, "path.getsize", _os_patch) + patch_function(m, "path.join", _os_patch) + patch_function(m, "path.expanduser", _os_patch) + patch_function(m, "path.expandvars", _os_patch) From e8c50d3e1c943d177662d6c82b28715eb587da1a Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 23:35:06 +0200 Subject: [PATCH 45/60] Update http_client.py sink, adding the @after --- aikido_zen/sinks/__init__.py | 21 ++++++++++++ aikido_zen/sinks/http_client.py | 59 ++++++++++++--------------------- 2 files changed, 43 insertions(+), 37 deletions(-) diff --git a/aikido_zen/sinks/__init__.py b/aikido_zen/sinks/__init__.py index 64be766b..da48d57d 100644 --- a/aikido_zen/sinks/__init__.py +++ b/aikido_zen/sinks/__init__.py @@ -47,3 +47,24 @@ def decorator(func, instance, args, kwargs): return func(*args, **kwargs) # Call the original function return decorator + + +def after(wrapper): + """ + Surrounds a patch with try-except, calls the original function and gives the return value to the patch + """ + + def decorator(func, instance, args, kwargs): + return_value = func(*args, **kwargs) # Call the original function + try: + wrapper(func, instance, args, kwargs, return_value) # Call the patch + except AikidoException as e: + raise e # Re-raise AikidoException + except Exception as e: + logger.debug( + "%s:%s wrapping-after error: %s", func.__module__, func.__name__, e + ) + finally: + return return_value + + return decorator diff --git a/aikido_zen/sinks/http_client.py b/aikido_zen/sinks/http_client.py index f4120396..18115506 100644 --- a/aikido_zen/sinks/http_client.py +++ b/aikido_zen/sinks/http_client.py @@ -2,49 +2,34 @@ Sink module for `http` """ -import copy -import aikido_zen.importhook as importhook -from aikido_zen.helpers.logging import logger -from aikido_zen.vulnerabilities import run_vulnerability_scan +from aikido_zen.helpers.get_argument import get_argument +from aikido_zen.importhook import on_import +from aikido_zen.sinks import before, after, patch_function from aikido_zen.vulnerabilities.ssrf.handle_http_response import ( handle_http_response, ) from aikido_zen.helpers.try_parse_url import try_parse_url -from aikido_zen.errors import AikidoException -@importhook.on_import("http.client") -def on_http_import(http): - """ - Hook 'n wrap on `http.client.HTTPConnection.putrequest` - Our goal is to wrap the putrequest() function of the HTTPConnection class : - https://github.com/python/cpython/blob/372df1950817dfcf8b9bac099448934bf8657cf5/Lib/http/client.py#L1136 - Returns : Modified http.client object - """ - modified_http = importhook.copy_module(http) - former_putrequest = copy.deepcopy(http.HTTPConnection.putrequest) - former_getresponse = copy.deepcopy(http.HTTPConnection.getresponse) +@before +def _putrequest(func, instance, args, kwargs): + path = get_argument(args, kwargs, 1, "path") + setattr(instance, "_aikido_var_path", path) + - def aik_new_putrequest(_self, method, path, *args, **kwargs): - # Aikido putrequest, gets called before the request goes through - # Set path for aik_new_getresponse : - _self.aikido_attr_path = path - return former_putrequest(_self, method, path, *args, **kwargs) +@after +def _getresponse(func, instance, args, kwargs, return_value): + path = getattr(instance, "_aikido_var_path") + source_url = try_parse_url(f"http://{instance.host}:{instance.port}{path}") + handle_http_response(http_response=return_value, source=source_url) - def aik_new_getresponse(_self): - # Aikido getresponse, gets called after the request is complete - # And fetches the response - response = former_getresponse(_self) - try: - assembled_url = f"http://{_self.host}:{_self.port}{_self.aikido_attr_path}" - source_url = try_parse_url(assembled_url) - handle_http_response(http_response=response, source=source_url) - except Exception as e: - logger.debug("Exception occurred in custom getresponse function : %s", e) - return response - # pylint: disable=no-member - setattr(http.HTTPConnection, "putrequest", aik_new_putrequest) - # pylint: disable=no-member - setattr(http.HTTPConnection, "getresponse", aik_new_getresponse) - return modified_http +@on_import("http.client") +def patch(m): + """ + patching module http.client + - patches HTTPConnection.putrequest -> stores path + - patches HTTPConnection.getresponse -> handles response object + """ + patch_function(m, "HTTPConnection.putrequest", _putrequest) + patch_function(m, "HTTPConnection.getresponse", _getresponse) From 87892fd8bbc7b3c39c3fb8df3ed5408065dc6d18 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 23:44:09 +0200 Subject: [PATCH 46/60] Update psycopg sink --- aikido_zen/sinks/psycopg.py | 60 ++++++++++++++----------------------- 1 file changed, 22 insertions(+), 38 deletions(-) diff --git a/aikido_zen/sinks/psycopg.py b/aikido_zen/sinks/psycopg.py index 18672c86..2ea4dd66 100644 --- a/aikido_zen/sinks/psycopg.py +++ b/aikido_zen/sinks/psycopg.py @@ -2,50 +2,34 @@ Sink module for `psycopg` """ -import copy -import aikido_zen.importhook as importhook -from aikido_zen.background_process.packages import is_package_compatible import aikido_zen.vulnerabilities as vulns +from aikido_zen.helpers.get_argument import get_argument +from aikido_zen.sinks import patch_function, on_import, before -REQUIRED_PSYCOPG_VERSION = "3.1.0" - -@importhook.on_import("psycopg.cursor") -def on_psycopg_import(psycopg): +@on_import("psycopg.cursor", "psycopg", version_requirement="3.1.0") +def patch(m): """ - Hook 'n wrap on `psycopg.connect` function, we modify the cursor_factory - of the result of this connect function. + patching module psycopg.cursor + - patches Cursor.copy + - patches Cursor.execute + - patches Cursor.executemany """ - if not is_package_compatible("psycopg", REQUIRED_PSYCOPG_VERSION): - return psycopg - modified_psycopg = importhook.copy_module(psycopg) - former_copy_funtcion = copy.deepcopy(psycopg.Cursor.copy) - former_execute_function = copy.deepcopy(psycopg.Cursor.execute) - former_executemany_function = copy.deepcopy(psycopg.Cursor.executemany) - - def aikido_copy(self, statement, params=None, *args, **kwargs): - sql = statement - vulns.run_vulnerability_scan( - kind="sql_injection", op="psycopg.Cursor.copy", args=(sql, "postgres") - ) - return former_copy_funtcion(self, statement, params, *args, **kwargs) + patch_function(m, "Cursor.copy", _copy) + patch_function(m, "Cursor.execute", _execute) + patch_function(m, "Cursor.executemany", _execute) - def aikido_execute(self, query, params=None, *args, **kwargs): - sql = query - vulns.run_vulnerability_scan( - kind="sql_injection", op="psycopg.Cursor.execute", args=(sql, "postgres") - ) - return former_execute_function(self, query, params, *args, **kwargs) - def aikido_executemany(self, query, params_seq): - args = (query, "postgres") - op = "psycopg.Cursor.executemany" - vulns.run_vulnerability_scan(kind="sql_injection", op=op, args=args) - return former_executemany_function(self, query, params_seq) +@before +def _copy(func, instance, args, kwargs): + statement = get_argument(args, kwargs, 0, "statement") + vulns.run_vulnerability_scan( + kind="sql_injection", op="psycopg.Cursor.copy", args=(statement, "postgres") + ) - setattr(psycopg.Cursor, "copy", aikido_copy) # pylint: disable=no-member - setattr(psycopg.Cursor, "execute", aikido_execute) # pylint: disable=no-member - # pylint: disable=no-member - setattr(psycopg.Cursor, "executemany", aikido_executemany) - return modified_psycopg +@before +def _execute(func, instance, args, kwargs): + query = get_argument(args, kwargs, 0, "query") + op = f"psycopg.Cursor.{func.__name__}" + vulns.run_vulnerability_scan(kind="sql_injection", op=op, args=(query, "postgres")) From fa9f54f7c0553e691469067910461758f17f7e5c Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 23:51:30 +0200 Subject: [PATCH 47/60] convert socket.py to new format --- aikido_zen/sinks/socket.py | 50 ++++++++++---------------------------- 1 file changed, 13 insertions(+), 37 deletions(-) diff --git a/aikido_zen/sinks/socket.py b/aikido_zen/sinks/socket.py index 5dfcb748..fc613db1 100644 --- a/aikido_zen/sinks/socket.py +++ b/aikido_zen/sinks/socket.py @@ -2,47 +2,23 @@ Sink module for `socket` """ -import copy -import aikido_zen.importhook as importhook -from aikido_zen.helpers.logging import logger +from aikido_zen.helpers.get_argument import get_argument +from aikido_zen.sinks import on_import, patch_function, after from aikido_zen.vulnerabilities import run_vulnerability_scan -SOCKET_OPERATIONS = [ - "gethostbyname", - "gethostbyaddr", - "getaddrinfo", - "create_connection", -] +@after +def _getaddrinfo(func, instance, args, kwargs, return_value): + host = get_argument(args, kwargs, 0, "host") + port = get_argument(args, kwargs, 1, "port") + arguments = (return_value, host, port) # return_value = dns response + run_vulnerability_scan(kind="ssrf", op="socket.getaddrinfo", args=arguments) -def generate_aikido_function(former_func, op): - """ - Generates a new aikido function given a former function and op - """ - - def aik_new_func(*args, **kwargs): - res = former_func(*args, **kwargs) - if op == "getaddrinfo": - run_vulnerability_scan( - kind="ssrf", op="socket.getaddrinfo", args=(res, args[0], args[1]) - ) - return res - return aik_new_func - - -@importhook.on_import("socket") -def on_socket_import(socket): +@on_import("socket") +def patch(m): """ - Hook 'n wrap on `socket` - Our goal is to wrap the getaddrinfo socket function - https://github.com/python/cpython/blob/8f19be47b6a50059924e1d7b64277ad3cef4dac7/Lib/socket.py#L10 - Returns : Modified socket object + patching module socket + - patches getaddrinfo(host, port, ...) """ - modified_socket = importhook.copy_module(socket) - for op in SOCKET_OPERATIONS: - former_func = copy.deepcopy(getattr(socket, op)) - setattr(modified_socket, op, generate_aikido_function(former_func, op)) - setattr(socket, op, generate_aikido_function(former_func, op)) - - return modified_socket + patch_function(m, "getaddrinfo", _getaddrinfo) From cb37a0c21b6717c4773910383a8c9e7035072a8a Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Mon, 14 Apr 2025 23:56:20 +0200 Subject: [PATCH 48/60] Fix shutil and shutil test cases --- aikido_zen/sinks/shutil.py | 4 ++-- aikido_zen/sinks/tests/shutil_test.py | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/aikido_zen/sinks/shutil.py b/aikido_zen/sinks/shutil.py index 666191ff..6e4198b3 100644 --- a/aikido_zen/sinks/shutil.py +++ b/aikido_zen/sinks/shutil.py @@ -15,9 +15,9 @@ def _shutil_func(func, instance, args, kwargs): kind = "path_traversal" op = f"shutil.{func.__name__}" if isinstance(source, str): - vulns.run_vulnerability_scan(kind, op, (source,)) + vulns.run_vulnerability_scan(kind, op, args=(source,)) if isinstance(source, str): - vulns.run_vulnerability_scan(kind, op, (destination,)) + vulns.run_vulnerability_scan(kind, op, args=(destination,)) @on_import("shutil") diff --git a/aikido_zen/sinks/tests/shutil_test.py b/aikido_zen/sinks/tests/shutil_test.py index adfaf1f6..a9e3efc4 100644 --- a/aikido_zen/sinks/tests/shutil_test.py +++ b/aikido_zen/sinks/tests/shutil_test.py @@ -28,7 +28,7 @@ def test_shutil_copyfile(): assert call_2.kwargs["args"] == args2 -def test_shutil_copyfile(): +def test_shutil_copyfile_2(): with patch( "aikido_zen.vulnerabilities.run_vulnerability_scan" ) as mock_run_vulnerability_scan: @@ -135,7 +135,6 @@ def test_shutil_copy(): op = "builtins.open" args1 = ("Makefile",) args2 = ("test2",) - assert len(mock_run_vulnerability_scan.call_args_list) == 3 call_1 = mock_run_vulnerability_scan.call_args_list[0] call_2 = mock_run_vulnerability_scan.call_args_list[1] @@ -155,7 +154,6 @@ def test_shutil_copy2(): op = "builtins.open" args1 = ("Makefile",) args2 = ("test2",) - assert len(mock_run_vulnerability_scan.call_args_list) == 3 call_1 = mock_run_vulnerability_scan.call_args_list[0] call_2 = mock_run_vulnerability_scan.call_args_list[1] From 06e7abdd41b94e17d94c8bfacfe5b4445259452d Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Tue, 15 Apr 2025 00:54:37 +0200 Subject: [PATCH 49/60] Convert psycopg2 module --- aikido_zen/sinks/psycopg2.py | 94 +++++++++++-------------- aikido_zen/sinks/tests/psycopg2_test.py | 84 ++++++++++++++++++++-- 2 files changed, 121 insertions(+), 57 deletions(-) diff --git a/aikido_zen/sinks/psycopg2.py b/aikido_zen/sinks/psycopg2.py index afd5a0fe..7f0da4c6 100644 --- a/aikido_zen/sinks/psycopg2.py +++ b/aikido_zen/sinks/psycopg2.py @@ -2,68 +2,56 @@ Sink module for `psycopg2` """ -import copy -import aikido_zen.importhook as importhook +from aikido_zen import logger from aikido_zen.background_process.packages import is_package_compatible import aikido_zen.vulnerabilities as vulns +from aikido_zen.helpers.get_argument import get_argument +from aikido_zen.sinks import on_import, before, patch_function -PSYCOPG2_REQUIRED_VERSION = "2.9.2" +@on_import("psycopg2") +def patch(m): + """ + patching module psycopg2 + - patches psycopg2.connect + Warning: cannot set 'execute' attribute of immutable type 'psycopg2.extensions.cursor' + """ + compatible = is_package_compatible( + required_version="2.9.2", packages=["psycopg2", "psycopg2-binary"] + ) + if not compatible: + # Users can install either psycopg2 or psycopg2-binary, we need to check if at least + # one is installed and if they meet version requirements + return -def wrap_cursor_factory(cursor_factory): - former_cursor_factory = copy.deepcopy(cursor_factory) - import psycopg2.extensions as ext + patch_function(m, "connect", _connect) - class AikidoWrappedCursor(ext.cursor): - def execute(self, *args, **kwargs): - """Aikido's wrapped execute function""" - vulns.run_vulnerability_scan( - kind="sql_injection", - op="psycopg2.Connection.Cursor.execute", - args=(args[0], "postgres"), # args[0] : sql - ) - if former_cursor_factory and hasattr(former_cursor_factory, "execute"): - return former_cursor_factory.execute(self, *args, **kwargs) - return ext.cursor.execute(self, *args, **kwargs) - def executemany(self, *args, **kwargs): - """Aikido's wrapped executemany function""" - sql = args[0] # The data is double, but sql only once. - vulns.run_vulnerability_scan( - kind="sql_injection", - op="psycopg2.Connection.Cursor.executemany", - args=(sql, "postgres"), - ) - if former_cursor_factory and hasattr(former_cursor_factory, "executemany"): - return former_cursor_factory.executemany(self, *args, **kwargs) - return ext.cursor.executemany(self, *args, **kwargs) +def _connect(func, instance, args, kwargs): + cursor_factory = get_argument(args, kwargs, 2, "cursor_factory") + if "cursor_factory" in kwargs: + del kwargs["cursor_factory"] + try: + if cursor_factory is None: + import psycopg2.extensions - return AikidoWrappedCursor + class AikidoDefaultCursor(psycopg2.extensions.cursor): + pass + cursor_factory = AikidoDefaultCursor -@importhook.on_import("psycopg2") -def on_psycopg2_import(psycopg2): - """ - Hook 'n wrap on `psycopg2.connect` function, we modify the cursor_factory - of the result of this connect function. - """ - # Users can install either psycopg2 or psycopg2-binary, we need to check if at least - # one is installed and if they meet version requirements : - if not is_package_compatible( - required_version=PSYCOPG2_REQUIRED_VERSION, - packages=["psycopg2", "psycopg2-binary"], - ): - # Both psycopg2 and psycopg2-binary are not supported, don't wrapping - return psycopg2 - modified_psycopg2 = importhook.copy_module(psycopg2) - former_connect_function = copy.deepcopy(psycopg2.connect) + # patch execute or executemany of an already existing cursor or of a new one + patch_function(cursor_factory, "execute", _execute) + patch_function(cursor_factory, "executemany", _execute) + + except Exception as e: + logger.info("patch of psycopg2 failed: %s", e.msg) + + return func(*args, cursor_factory=cursor_factory, **kwargs) - def aikido_connect(*args, **kwargs): - former_conn = former_connect_function(*args, **kwargs) - former_conn.cursor_factory = wrap_cursor_factory(former_conn.cursor_factory) - return former_conn - # pylint: disable=no-member - setattr(psycopg2, "connect", aikido_connect) - setattr(modified_psycopg2, "connect", aikido_connect) - return modified_psycopg2 +@before +def _execute(func, instance, args, kwargs): + query = get_argument(args, kwargs, 0, "query") + op = f"psycopg2.Connection.Cursor.{func.__name__}" + vulns.run_vulnerability_scan(kind="sql_injection", op=op, args=(query, "postgres")) diff --git a/aikido_zen/sinks/tests/psycopg2_test.py b/aikido_zen/sinks/tests/psycopg2_test.py index 483475f7..1c0b6b47 100644 --- a/aikido_zen/sinks/tests/psycopg2_test.py +++ b/aikido_zen/sinks/tests/psycopg2_test.py @@ -10,9 +10,26 @@ @pytest.fixture def database_conn(): import psycopg2 + from psycopg2.extras import DictCursor return psycopg2.connect( - host="127.0.0.1", user="user", password="password", database="db" + cursor_factory=DictCursor, + host="127.0.0.1", + user="user", + password="password", + database="db", + ) + + +@pytest.fixture +def database_conn_empty_cursor(): + import psycopg2 + + return psycopg2.connect( + host="127.0.0.1", + user="user", + password="password", + database="db", ) @@ -35,6 +52,25 @@ def test_cursor_execute(database_conn): mock_run_vulnerability_scan.assert_called_once() +def test_cursor_execute2(database_conn_empty_cursor): + reset_comms() + with patch( + "aikido_zen.vulnerabilities.run_vulnerability_scan" + ) as mock_run_vulnerability_scan: + cursor = database_conn_empty_cursor.cursor() + query = "SELECT * FROM dogs" + cursor.execute(query) + + called_with_args = mock_run_vulnerability_scan.call_args[1]["args"] + assert called_with_args[0] == query + assert called_with_args[1] == "postgres" + mock_run_vulnerability_scan.assert_called_once() + + cursor.fetchall() + database_conn_empty_cursor.close() + mock_run_vulnerability_scan.assert_called_once() + + def test_cursor_execute_parameterized(database_conn): reset_comms() with patch( @@ -47,10 +83,26 @@ def test_cursor_execute_parameterized(database_conn): called_with_args = mock_run_vulnerability_scan.call_args[1]["args"] assert called_with_args[0] == query assert called_with_args[1] == "postgres" - mock_run_vulnerability_scan.assert_called_once() - database_conn.commit() database_conn.close() + + +def test_cursor_execute_parameterized2(database_conn_empty_cursor): + reset_comms() + with patch( + "aikido_zen.vulnerabilities.run_vulnerability_scan" + ) as mock_run_vulnerability_scan: + cursor = database_conn_empty_cursor.cursor() + query = "INSERT INTO dogs (dog_name, isadmin) VALUES (%s, %s)" + cursor.execute(query, ("doggo", True)) + + called_with_args = mock_run_vulnerability_scan.call_args[1]["args"] + assert called_with_args[0] == query + assert called_with_args[1] == "postgres" + mock_run_vulnerability_scan.assert_called_once() + + database_conn_empty_cursor.commit() + database_conn_empty_cursor.close() mock_run_vulnerability_scan.assert_called_once() @@ -72,9 +124,33 @@ def test_cursor_executemany(database_conn): == "INSERT INTO dogs (dog_name, isadmin) VALUES (%s, %s)" ) assert called_with_args[1] == "postgres" - mock_run_vulnerability_scan.assert_called_once() database_conn.commit() cursor.close() database_conn.close() + + +def test_cursor_executemany2(database_conn_empty_cursor): + reset_comms() + with patch( + "aikido_zen.vulnerabilities.run_vulnerability_scan" + ) as mock_run_vulnerability_scan: + cursor = database_conn_empty_cursor.cursor() + data = [ + ("Doggy", False), + ("Doggy 2", True), + ("Dogski", True), + ] + cursor.executemany("INSERT INTO dogs (dog_name, isadmin) VALUES (%s, %s)", data) + called_with_args = mock_run_vulnerability_scan.call_args[1]["args"] + assert ( + called_with_args[0] + == "INSERT INTO dogs (dog_name, isadmin) VALUES (%s, %s)" + ) + assert called_with_args[1] == "postgres" + mock_run_vulnerability_scan.assert_called_once() + + database_conn_empty_cursor.commit() + cursor.close() + database_conn_empty_cursor.close() mock_run_vulnerability_scan.assert_called_once() From 6af31a4562380d7214e428cf2620cc8c010b5954 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Tue, 15 Apr 2025 01:01:47 +0200 Subject: [PATCH 50/60] update sample app lockfiles --- sample-apps/django-mysql-gunicorn/poetry.lock | 3 +- sample-apps/django-mysql/poetry.lock | 92 ++++++++++++++++++- .../django-postgres-gunicorn/poetry.lock | 3 +- .../fastapi-postgres-uvicorn/poetry.lock | 92 ++++++++++++++++++- sample-apps/flask-mongo/poetry.lock | 3 +- sample-apps/flask-mssql/poetry.lock | 92 ++++++++++++++++++- sample-apps/flask-mysql-uwsgi/poetry.lock | 92 ++++++++++++++++++- sample-apps/flask-mysql/poetry.lock | 92 ++++++++++++++++++- sample-apps/flask-postgres-xml/poetry.lock | 92 ++++++++++++++++++- sample-apps/flask-postgres/poetry.lock | 92 ++++++++++++++++++- sample-apps/quart-mongo/poetry.lock | 92 ++++++++++++++++++- .../quart-postgres-uvicorn/poetry.lock | 92 ++++++++++++++++++- .../starlette-postgres-uvicorn/poetry.lock | 92 ++++++++++++++++++- 13 files changed, 916 insertions(+), 13 deletions(-) diff --git a/sample-apps/django-mysql-gunicorn/poetry.lock b/sample-apps/django-mysql-gunicorn/poetry.lock index c24fd2b3..7ba87813 100644 --- a/sample-apps/django-mysql-gunicorn/poetry.lock +++ b/sample-apps/django-mysql-gunicorn/poetry.lock @@ -2,7 +2,7 @@ [[package]] name = "aikido-zen" -version = "1.1.1" +version = "1.0.0" description = "Aikido Zen for Python" optional = false python-versions = "^3.8" @@ -15,6 +15,7 @@ packaging = "^24.1" python-dotenv = "^1.0.1" regex = "^2024.5.15" requests = "^2.32.3" +wrapt = "^1.17" [package.source] type = "directory" diff --git a/sample-apps/django-mysql/poetry.lock b/sample-apps/django-mysql/poetry.lock index 0f50f429..9b462041 100644 --- a/sample-apps/django-mysql/poetry.lock +++ b/sample-apps/django-mysql/poetry.lock @@ -2,7 +2,7 @@ [[package]] name = "aikido-zen" -version = "1.1.1" +version = "1.0.0" description = "Aikido Zen for Python" optional = false python-versions = "^3.8" @@ -15,6 +15,7 @@ packaging = "^24.1" python-dotenv = "^1.0.1" regex = "^2024.5.15" requests = "^2.32.3" +wrapt = "^1.17" [package.source] type = "directory" @@ -575,6 +576,95 @@ h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] +[[package]] +name = "wrapt" +version = "1.17.2" +description = "Module for decorators, wrappers and monkey patching." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984"}, + {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22"}, + {file = "wrapt-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62"}, + {file = "wrapt-1.17.2-cp310-cp310-win32.whl", hash = "sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563"}, + {file = "wrapt-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72"}, + {file = "wrapt-1.17.2-cp311-cp311-win32.whl", hash = "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317"}, + {file = "wrapt-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9"}, + {file = "wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9"}, + {file = "wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504"}, + {file = "wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a"}, + {file = "wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f"}, + {file = "wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555"}, + {file = "wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c803c401ea1c1c18de70a06a6f79fcc9c5acfc79133e9869e730ad7f8ad8ef9"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f917c1180fdb8623c2b75a99192f4025e412597c50b2ac870f156de8fb101119"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ecc840861360ba9d176d413a5489b9a0aff6d6303d7e733e2c4623cfa26904a6"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb87745b2e6dc56361bfde481d5a378dc314b252a98d7dd19a651a3fa58f24a9"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58455b79ec2661c3600e65c0a716955adc2410f7383755d537584b0de41b1d8a"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4e42a40a5e164cbfdb7b386c966a588b1047558a990981ace551ed7e12ca9c2"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:91bd7d1773e64019f9288b7a5101f3ae50d3d8e6b1de7edee9c2ccc1d32f0c0a"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:bb90fb8bda722a1b9d48ac1e6c38f923ea757b3baf8ebd0c82e09c5c1a0e7a04"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:08e7ce672e35efa54c5024936e559469436f8b8096253404faeb54d2a878416f"}, + {file = "wrapt-1.17.2-cp38-cp38-win32.whl", hash = "sha256:410a92fefd2e0e10d26210e1dfb4a876ddaf8439ef60d6434f21ef8d87efc5b7"}, + {file = "wrapt-1.17.2-cp38-cp38-win_amd64.whl", hash = "sha256:95c658736ec15602da0ed73f312d410117723914a5c91a14ee4cdd72f1d790b3"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99039fa9e6306880572915728d7f6c24a86ec57b0a83f6b2491e1d8ab0235b9a"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2696993ee1eebd20b8e4ee4356483c4cb696066ddc24bd70bcbb80fa56ff9061"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:612dff5db80beef9e649c6d803a8d50c409082f1fedc9dbcdfde2983b2025b82"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62c2caa1585c82b3f7a7ab56afef7b3602021d6da34fbc1cf234ff139fed3cd9"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c958bcfd59bacc2d0249dcfe575e71da54f9dcf4a8bdf89c4cb9a68a1170d73f"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc78a84e2dfbc27afe4b2bd7c80c8db9bca75cc5b85df52bfe634596a1da846b"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba0f0eb61ef00ea10e00eb53a9129501f52385c44853dbd6c4ad3f403603083f"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1e1fe0e6ab7775fd842bc39e86f6dcfc4507ab0ffe206093e76d61cde37225c8"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c86563182421896d73858e08e1db93afdd2b947a70064b813d515d66549e15f9"}, + {file = "wrapt-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f393cda562f79828f38a819f4788641ac7c4085f30f1ce1a68672baa686482bb"}, + {file = "wrapt-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:36ccae62f64235cf8ddb682073a60519426fdd4725524ae38874adf72b5f2aeb"}, + {file = "wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8"}, + {file = "wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3"}, +] + [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0" diff --git a/sample-apps/django-postgres-gunicorn/poetry.lock b/sample-apps/django-postgres-gunicorn/poetry.lock index 9bf1b0fd..3b52b974 100644 --- a/sample-apps/django-postgres-gunicorn/poetry.lock +++ b/sample-apps/django-postgres-gunicorn/poetry.lock @@ -2,7 +2,7 @@ [[package]] name = "aikido-zen" -version = "1.1.1" +version = "1.0.0" description = "Aikido Zen for Python" optional = false python-versions = "^3.8" @@ -15,6 +15,7 @@ packaging = "^24.1" python-dotenv = "^1.0.1" regex = "^2024.5.15" requests = "^2.32.3" +wrapt = "^1.17" [package.source] type = "directory" diff --git a/sample-apps/fastapi-postgres-uvicorn/poetry.lock b/sample-apps/fastapi-postgres-uvicorn/poetry.lock index 836da824..3e69ce6c 100644 --- a/sample-apps/fastapi-postgres-uvicorn/poetry.lock +++ b/sample-apps/fastapi-postgres-uvicorn/poetry.lock @@ -2,7 +2,7 @@ [[package]] name = "aikido-zen" -version = "1.1.1" +version = "1.0.0" description = "Aikido Zen for Python" optional = false python-versions = "^3.8" @@ -15,6 +15,7 @@ packaging = "^24.1" python-dotenv = "^1.0.1" regex = "^2024.5.15" requests = "^2.32.3" +wrapt = "^1.17" [package.source] type = "directory" @@ -954,6 +955,95 @@ typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} [package.extras] standard = ["colorama (>=0.4)", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] +[[package]] +name = "wrapt" +version = "1.17.2" +description = "Module for decorators, wrappers and monkey patching." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984"}, + {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22"}, + {file = "wrapt-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62"}, + {file = "wrapt-1.17.2-cp310-cp310-win32.whl", hash = "sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563"}, + {file = "wrapt-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72"}, + {file = "wrapt-1.17.2-cp311-cp311-win32.whl", hash = "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317"}, + {file = "wrapt-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9"}, + {file = "wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9"}, + {file = "wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504"}, + {file = "wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a"}, + {file = "wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f"}, + {file = "wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555"}, + {file = "wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c803c401ea1c1c18de70a06a6f79fcc9c5acfc79133e9869e730ad7f8ad8ef9"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f917c1180fdb8623c2b75a99192f4025e412597c50b2ac870f156de8fb101119"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ecc840861360ba9d176d413a5489b9a0aff6d6303d7e733e2c4623cfa26904a6"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb87745b2e6dc56361bfde481d5a378dc314b252a98d7dd19a651a3fa58f24a9"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58455b79ec2661c3600e65c0a716955adc2410f7383755d537584b0de41b1d8a"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4e42a40a5e164cbfdb7b386c966a588b1047558a990981ace551ed7e12ca9c2"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:91bd7d1773e64019f9288b7a5101f3ae50d3d8e6b1de7edee9c2ccc1d32f0c0a"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:bb90fb8bda722a1b9d48ac1e6c38f923ea757b3baf8ebd0c82e09c5c1a0e7a04"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:08e7ce672e35efa54c5024936e559469436f8b8096253404faeb54d2a878416f"}, + {file = "wrapt-1.17.2-cp38-cp38-win32.whl", hash = "sha256:410a92fefd2e0e10d26210e1dfb4a876ddaf8439ef60d6434f21ef8d87efc5b7"}, + {file = "wrapt-1.17.2-cp38-cp38-win_amd64.whl", hash = "sha256:95c658736ec15602da0ed73f312d410117723914a5c91a14ee4cdd72f1d790b3"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99039fa9e6306880572915728d7f6c24a86ec57b0a83f6b2491e1d8ab0235b9a"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2696993ee1eebd20b8e4ee4356483c4cb696066ddc24bd70bcbb80fa56ff9061"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:612dff5db80beef9e649c6d803a8d50c409082f1fedc9dbcdfde2983b2025b82"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62c2caa1585c82b3f7a7ab56afef7b3602021d6da34fbc1cf234ff139fed3cd9"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c958bcfd59bacc2d0249dcfe575e71da54f9dcf4a8bdf89c4cb9a68a1170d73f"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc78a84e2dfbc27afe4b2bd7c80c8db9bca75cc5b85df52bfe634596a1da846b"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba0f0eb61ef00ea10e00eb53a9129501f52385c44853dbd6c4ad3f403603083f"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1e1fe0e6ab7775fd842bc39e86f6dcfc4507ab0ffe206093e76d61cde37225c8"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c86563182421896d73858e08e1db93afdd2b947a70064b813d515d66549e15f9"}, + {file = "wrapt-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f393cda562f79828f38a819f4788641ac7c4085f30f1ce1a68672baa686482bb"}, + {file = "wrapt-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:36ccae62f64235cf8ddb682073a60519426fdd4725524ae38874adf72b5f2aeb"}, + {file = "wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8"}, + {file = "wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3"}, +] + [metadata] lock-version = "2.1" python-versions = ">3.9.1,<4.0" diff --git a/sample-apps/flask-mongo/poetry.lock b/sample-apps/flask-mongo/poetry.lock index 8f4ed85e..16e95a24 100644 --- a/sample-apps/flask-mongo/poetry.lock +++ b/sample-apps/flask-mongo/poetry.lock @@ -2,7 +2,7 @@ [[package]] name = "aikido-zen" -version = "1.1.1" +version = "1.0.0" description = "Aikido Zen for Python" optional = false python-versions = "^3.8" @@ -15,6 +15,7 @@ packaging = "^24.1" python-dotenv = "^1.0.1" regex = "^2024.5.15" requests = "^2.32.3" +wrapt = "^1.17" [package.source] type = "directory" diff --git a/sample-apps/flask-mssql/poetry.lock b/sample-apps/flask-mssql/poetry.lock index 7b19a0ce..939c2e22 100644 --- a/sample-apps/flask-mssql/poetry.lock +++ b/sample-apps/flask-mssql/poetry.lock @@ -2,7 +2,7 @@ [[package]] name = "aikido-zen" -version = "1.1.1" +version = "1.0.0" description = "Aikido Zen for Python" optional = false python-versions = "^3.8" @@ -15,6 +15,7 @@ packaging = "^24.1" python-dotenv = "^1.0.1" regex = "^2024.5.15" requests = "^2.32.3" +wrapt = "^1.17" [package.source] type = "directory" @@ -740,6 +741,95 @@ MarkupSafe = ">=2.1.1" [package.extras] watchdog = ["watchdog (>=2.3)"] +[[package]] +name = "wrapt" +version = "1.17.2" +description = "Module for decorators, wrappers and monkey patching." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984"}, + {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22"}, + {file = "wrapt-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62"}, + {file = "wrapt-1.17.2-cp310-cp310-win32.whl", hash = "sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563"}, + {file = "wrapt-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72"}, + {file = "wrapt-1.17.2-cp311-cp311-win32.whl", hash = "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317"}, + {file = "wrapt-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9"}, + {file = "wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9"}, + {file = "wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504"}, + {file = "wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a"}, + {file = "wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f"}, + {file = "wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555"}, + {file = "wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c803c401ea1c1c18de70a06a6f79fcc9c5acfc79133e9869e730ad7f8ad8ef9"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f917c1180fdb8623c2b75a99192f4025e412597c50b2ac870f156de8fb101119"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ecc840861360ba9d176d413a5489b9a0aff6d6303d7e733e2c4623cfa26904a6"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb87745b2e6dc56361bfde481d5a378dc314b252a98d7dd19a651a3fa58f24a9"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58455b79ec2661c3600e65c0a716955adc2410f7383755d537584b0de41b1d8a"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4e42a40a5e164cbfdb7b386c966a588b1047558a990981ace551ed7e12ca9c2"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:91bd7d1773e64019f9288b7a5101f3ae50d3d8e6b1de7edee9c2ccc1d32f0c0a"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:bb90fb8bda722a1b9d48ac1e6c38f923ea757b3baf8ebd0c82e09c5c1a0e7a04"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:08e7ce672e35efa54c5024936e559469436f8b8096253404faeb54d2a878416f"}, + {file = "wrapt-1.17.2-cp38-cp38-win32.whl", hash = "sha256:410a92fefd2e0e10d26210e1dfb4a876ddaf8439ef60d6434f21ef8d87efc5b7"}, + {file = "wrapt-1.17.2-cp38-cp38-win_amd64.whl", hash = "sha256:95c658736ec15602da0ed73f312d410117723914a5c91a14ee4cdd72f1d790b3"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99039fa9e6306880572915728d7f6c24a86ec57b0a83f6b2491e1d8ab0235b9a"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2696993ee1eebd20b8e4ee4356483c4cb696066ddc24bd70bcbb80fa56ff9061"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:612dff5db80beef9e649c6d803a8d50c409082f1fedc9dbcdfde2983b2025b82"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62c2caa1585c82b3f7a7ab56afef7b3602021d6da34fbc1cf234ff139fed3cd9"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c958bcfd59bacc2d0249dcfe575e71da54f9dcf4a8bdf89c4cb9a68a1170d73f"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc78a84e2dfbc27afe4b2bd7c80c8db9bca75cc5b85df52bfe634596a1da846b"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba0f0eb61ef00ea10e00eb53a9129501f52385c44853dbd6c4ad3f403603083f"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1e1fe0e6ab7775fd842bc39e86f6dcfc4507ab0ffe206093e76d61cde37225c8"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c86563182421896d73858e08e1db93afdd2b947a70064b813d515d66549e15f9"}, + {file = "wrapt-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f393cda562f79828f38a819f4788641ac7c4085f30f1ce1a68672baa686482bb"}, + {file = "wrapt-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:36ccae62f64235cf8ddb682073a60519426fdd4725524ae38874adf72b5f2aeb"}, + {file = "wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8"}, + {file = "wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3"}, +] + [[package]] name = "zipp" version = "3.21.0" diff --git a/sample-apps/flask-mysql-uwsgi/poetry.lock b/sample-apps/flask-mysql-uwsgi/poetry.lock index 98b42bf2..4b933168 100644 --- a/sample-apps/flask-mysql-uwsgi/poetry.lock +++ b/sample-apps/flask-mysql-uwsgi/poetry.lock @@ -2,7 +2,7 @@ [[package]] name = "aikido-zen" -version = "1.1.1" +version = "1.0.0" description = "Aikido Zen for Python" optional = false python-versions = "^3.8" @@ -15,6 +15,7 @@ packaging = "^24.1" python-dotenv = "^1.0.1" regex = "^2024.5.15" requests = "^2.32.3" +wrapt = "^1.17" [package.source] type = "directory" @@ -715,6 +716,95 @@ MarkupSafe = ">=2.1.1" [package.extras] watchdog = ["watchdog (>=2.3)"] +[[package]] +name = "wrapt" +version = "1.17.2" +description = "Module for decorators, wrappers and monkey patching." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984"}, + {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22"}, + {file = "wrapt-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62"}, + {file = "wrapt-1.17.2-cp310-cp310-win32.whl", hash = "sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563"}, + {file = "wrapt-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72"}, + {file = "wrapt-1.17.2-cp311-cp311-win32.whl", hash = "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317"}, + {file = "wrapt-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9"}, + {file = "wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9"}, + {file = "wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504"}, + {file = "wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a"}, + {file = "wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f"}, + {file = "wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555"}, + {file = "wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c803c401ea1c1c18de70a06a6f79fcc9c5acfc79133e9869e730ad7f8ad8ef9"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f917c1180fdb8623c2b75a99192f4025e412597c50b2ac870f156de8fb101119"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ecc840861360ba9d176d413a5489b9a0aff6d6303d7e733e2c4623cfa26904a6"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb87745b2e6dc56361bfde481d5a378dc314b252a98d7dd19a651a3fa58f24a9"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58455b79ec2661c3600e65c0a716955adc2410f7383755d537584b0de41b1d8a"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4e42a40a5e164cbfdb7b386c966a588b1047558a990981ace551ed7e12ca9c2"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:91bd7d1773e64019f9288b7a5101f3ae50d3d8e6b1de7edee9c2ccc1d32f0c0a"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:bb90fb8bda722a1b9d48ac1e6c38f923ea757b3baf8ebd0c82e09c5c1a0e7a04"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:08e7ce672e35efa54c5024936e559469436f8b8096253404faeb54d2a878416f"}, + {file = "wrapt-1.17.2-cp38-cp38-win32.whl", hash = "sha256:410a92fefd2e0e10d26210e1dfb4a876ddaf8439ef60d6434f21ef8d87efc5b7"}, + {file = "wrapt-1.17.2-cp38-cp38-win_amd64.whl", hash = "sha256:95c658736ec15602da0ed73f312d410117723914a5c91a14ee4cdd72f1d790b3"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99039fa9e6306880572915728d7f6c24a86ec57b0a83f6b2491e1d8ab0235b9a"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2696993ee1eebd20b8e4ee4356483c4cb696066ddc24bd70bcbb80fa56ff9061"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:612dff5db80beef9e649c6d803a8d50c409082f1fedc9dbcdfde2983b2025b82"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62c2caa1585c82b3f7a7ab56afef7b3602021d6da34fbc1cf234ff139fed3cd9"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c958bcfd59bacc2d0249dcfe575e71da54f9dcf4a8bdf89c4cb9a68a1170d73f"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc78a84e2dfbc27afe4b2bd7c80c8db9bca75cc5b85df52bfe634596a1da846b"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba0f0eb61ef00ea10e00eb53a9129501f52385c44853dbd6c4ad3f403603083f"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1e1fe0e6ab7775fd842bc39e86f6dcfc4507ab0ffe206093e76d61cde37225c8"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c86563182421896d73858e08e1db93afdd2b947a70064b813d515d66549e15f9"}, + {file = "wrapt-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f393cda562f79828f38a819f4788641ac7c4085f30f1ce1a68672baa686482bb"}, + {file = "wrapt-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:36ccae62f64235cf8ddb682073a60519426fdd4725524ae38874adf72b5f2aeb"}, + {file = "wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8"}, + {file = "wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3"}, +] + [[package]] name = "zipp" version = "3.21.0" diff --git a/sample-apps/flask-mysql/poetry.lock b/sample-apps/flask-mysql/poetry.lock index 56963fa8..1de267b5 100644 --- a/sample-apps/flask-mysql/poetry.lock +++ b/sample-apps/flask-mysql/poetry.lock @@ -2,7 +2,7 @@ [[package]] name = "aikido-zen" -version = "1.1.1" +version = "1.0.0" description = "Aikido Zen for Python" optional = false python-versions = "^3.8" @@ -15,6 +15,7 @@ packaging = "^24.1" python-dotenv = "^1.0.1" regex = "^2024.5.15" requests = "^2.32.3" +wrapt = "^1.17" [package.source] type = "directory" @@ -760,6 +761,95 @@ MarkupSafe = ">=2.1.1" [package.extras] watchdog = ["watchdog (>=2.3)"] +[[package]] +name = "wrapt" +version = "1.17.2" +description = "Module for decorators, wrappers and monkey patching." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984"}, + {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22"}, + {file = "wrapt-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62"}, + {file = "wrapt-1.17.2-cp310-cp310-win32.whl", hash = "sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563"}, + {file = "wrapt-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72"}, + {file = "wrapt-1.17.2-cp311-cp311-win32.whl", hash = "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317"}, + {file = "wrapt-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9"}, + {file = "wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9"}, + {file = "wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504"}, + {file = "wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a"}, + {file = "wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f"}, + {file = "wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555"}, + {file = "wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c803c401ea1c1c18de70a06a6f79fcc9c5acfc79133e9869e730ad7f8ad8ef9"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f917c1180fdb8623c2b75a99192f4025e412597c50b2ac870f156de8fb101119"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ecc840861360ba9d176d413a5489b9a0aff6d6303d7e733e2c4623cfa26904a6"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb87745b2e6dc56361bfde481d5a378dc314b252a98d7dd19a651a3fa58f24a9"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58455b79ec2661c3600e65c0a716955adc2410f7383755d537584b0de41b1d8a"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4e42a40a5e164cbfdb7b386c966a588b1047558a990981ace551ed7e12ca9c2"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:91bd7d1773e64019f9288b7a5101f3ae50d3d8e6b1de7edee9c2ccc1d32f0c0a"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:bb90fb8bda722a1b9d48ac1e6c38f923ea757b3baf8ebd0c82e09c5c1a0e7a04"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:08e7ce672e35efa54c5024936e559469436f8b8096253404faeb54d2a878416f"}, + {file = "wrapt-1.17.2-cp38-cp38-win32.whl", hash = "sha256:410a92fefd2e0e10d26210e1dfb4a876ddaf8439ef60d6434f21ef8d87efc5b7"}, + {file = "wrapt-1.17.2-cp38-cp38-win_amd64.whl", hash = "sha256:95c658736ec15602da0ed73f312d410117723914a5c91a14ee4cdd72f1d790b3"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99039fa9e6306880572915728d7f6c24a86ec57b0a83f6b2491e1d8ab0235b9a"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2696993ee1eebd20b8e4ee4356483c4cb696066ddc24bd70bcbb80fa56ff9061"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:612dff5db80beef9e649c6d803a8d50c409082f1fedc9dbcdfde2983b2025b82"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62c2caa1585c82b3f7a7ab56afef7b3602021d6da34fbc1cf234ff139fed3cd9"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c958bcfd59bacc2d0249dcfe575e71da54f9dcf4a8bdf89c4cb9a68a1170d73f"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc78a84e2dfbc27afe4b2bd7c80c8db9bca75cc5b85df52bfe634596a1da846b"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba0f0eb61ef00ea10e00eb53a9129501f52385c44853dbd6c4ad3f403603083f"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1e1fe0e6ab7775fd842bc39e86f6dcfc4507ab0ffe206093e76d61cde37225c8"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c86563182421896d73858e08e1db93afdd2b947a70064b813d515d66549e15f9"}, + {file = "wrapt-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f393cda562f79828f38a819f4788641ac7c4085f30f1ce1a68672baa686482bb"}, + {file = "wrapt-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:36ccae62f64235cf8ddb682073a60519426fdd4725524ae38874adf72b5f2aeb"}, + {file = "wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8"}, + {file = "wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3"}, +] + [[package]] name = "zipp" version = "3.21.0" diff --git a/sample-apps/flask-postgres-xml/poetry.lock b/sample-apps/flask-postgres-xml/poetry.lock index 1e3dcf5a..c5dbc21f 100644 --- a/sample-apps/flask-postgres-xml/poetry.lock +++ b/sample-apps/flask-postgres-xml/poetry.lock @@ -2,7 +2,7 @@ [[package]] name = "aikido-zen" -version = "1.1.1" +version = "1.0.0" description = "Aikido Zen for Python" optional = false python-versions = "^3.8" @@ -15,6 +15,7 @@ packaging = "^24.1" python-dotenv = "^1.0.1" regex = "^2024.5.15" requests = "^2.32.3" +wrapt = "^1.17" [package.source] type = "directory" @@ -905,6 +906,95 @@ MarkupSafe = ">=2.1.1" [package.extras] watchdog = ["watchdog (>=2.3)"] +[[package]] +name = "wrapt" +version = "1.17.2" +description = "Module for decorators, wrappers and monkey patching." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984"}, + {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22"}, + {file = "wrapt-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62"}, + {file = "wrapt-1.17.2-cp310-cp310-win32.whl", hash = "sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563"}, + {file = "wrapt-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72"}, + {file = "wrapt-1.17.2-cp311-cp311-win32.whl", hash = "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317"}, + {file = "wrapt-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9"}, + {file = "wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9"}, + {file = "wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504"}, + {file = "wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a"}, + {file = "wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f"}, + {file = "wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555"}, + {file = "wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c803c401ea1c1c18de70a06a6f79fcc9c5acfc79133e9869e730ad7f8ad8ef9"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f917c1180fdb8623c2b75a99192f4025e412597c50b2ac870f156de8fb101119"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ecc840861360ba9d176d413a5489b9a0aff6d6303d7e733e2c4623cfa26904a6"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb87745b2e6dc56361bfde481d5a378dc314b252a98d7dd19a651a3fa58f24a9"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58455b79ec2661c3600e65c0a716955adc2410f7383755d537584b0de41b1d8a"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4e42a40a5e164cbfdb7b386c966a588b1047558a990981ace551ed7e12ca9c2"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:91bd7d1773e64019f9288b7a5101f3ae50d3d8e6b1de7edee9c2ccc1d32f0c0a"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:bb90fb8bda722a1b9d48ac1e6c38f923ea757b3baf8ebd0c82e09c5c1a0e7a04"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:08e7ce672e35efa54c5024936e559469436f8b8096253404faeb54d2a878416f"}, + {file = "wrapt-1.17.2-cp38-cp38-win32.whl", hash = "sha256:410a92fefd2e0e10d26210e1dfb4a876ddaf8439ef60d6434f21ef8d87efc5b7"}, + {file = "wrapt-1.17.2-cp38-cp38-win_amd64.whl", hash = "sha256:95c658736ec15602da0ed73f312d410117723914a5c91a14ee4cdd72f1d790b3"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99039fa9e6306880572915728d7f6c24a86ec57b0a83f6b2491e1d8ab0235b9a"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2696993ee1eebd20b8e4ee4356483c4cb696066ddc24bd70bcbb80fa56ff9061"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:612dff5db80beef9e649c6d803a8d50c409082f1fedc9dbcdfde2983b2025b82"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62c2caa1585c82b3f7a7ab56afef7b3602021d6da34fbc1cf234ff139fed3cd9"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c958bcfd59bacc2d0249dcfe575e71da54f9dcf4a8bdf89c4cb9a68a1170d73f"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc78a84e2dfbc27afe4b2bd7c80c8db9bca75cc5b85df52bfe634596a1da846b"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba0f0eb61ef00ea10e00eb53a9129501f52385c44853dbd6c4ad3f403603083f"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1e1fe0e6ab7775fd842bc39e86f6dcfc4507ab0ffe206093e76d61cde37225c8"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c86563182421896d73858e08e1db93afdd2b947a70064b813d515d66549e15f9"}, + {file = "wrapt-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f393cda562f79828f38a819f4788641ac7c4085f30f1ce1a68672baa686482bb"}, + {file = "wrapt-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:36ccae62f64235cf8ddb682073a60519426fdd4725524ae38874adf72b5f2aeb"}, + {file = "wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8"}, + {file = "wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3"}, +] + [[package]] name = "zipp" version = "3.21.0" diff --git a/sample-apps/flask-postgres/poetry.lock b/sample-apps/flask-postgres/poetry.lock index 73d25f24..b56cb0a4 100644 --- a/sample-apps/flask-postgres/poetry.lock +++ b/sample-apps/flask-postgres/poetry.lock @@ -2,7 +2,7 @@ [[package]] name = "aikido-zen" -version = "1.1.1" +version = "1.0.0" description = "Aikido Zen for Python" optional = false python-versions = "^3.8" @@ -15,6 +15,7 @@ packaging = "^24.1" python-dotenv = "^1.0.1" regex = "^2024.5.15" requests = "^2.32.3" +wrapt = "^1.17" [package.source] type = "directory" @@ -750,6 +751,95 @@ MarkupSafe = ">=2.1.1" [package.extras] watchdog = ["watchdog (>=2.3)"] +[[package]] +name = "wrapt" +version = "1.17.2" +description = "Module for decorators, wrappers and monkey patching." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984"}, + {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22"}, + {file = "wrapt-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62"}, + {file = "wrapt-1.17.2-cp310-cp310-win32.whl", hash = "sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563"}, + {file = "wrapt-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72"}, + {file = "wrapt-1.17.2-cp311-cp311-win32.whl", hash = "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317"}, + {file = "wrapt-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9"}, + {file = "wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9"}, + {file = "wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504"}, + {file = "wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a"}, + {file = "wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f"}, + {file = "wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555"}, + {file = "wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c803c401ea1c1c18de70a06a6f79fcc9c5acfc79133e9869e730ad7f8ad8ef9"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f917c1180fdb8623c2b75a99192f4025e412597c50b2ac870f156de8fb101119"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ecc840861360ba9d176d413a5489b9a0aff6d6303d7e733e2c4623cfa26904a6"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb87745b2e6dc56361bfde481d5a378dc314b252a98d7dd19a651a3fa58f24a9"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58455b79ec2661c3600e65c0a716955adc2410f7383755d537584b0de41b1d8a"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4e42a40a5e164cbfdb7b386c966a588b1047558a990981ace551ed7e12ca9c2"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:91bd7d1773e64019f9288b7a5101f3ae50d3d8e6b1de7edee9c2ccc1d32f0c0a"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:bb90fb8bda722a1b9d48ac1e6c38f923ea757b3baf8ebd0c82e09c5c1a0e7a04"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:08e7ce672e35efa54c5024936e559469436f8b8096253404faeb54d2a878416f"}, + {file = "wrapt-1.17.2-cp38-cp38-win32.whl", hash = "sha256:410a92fefd2e0e10d26210e1dfb4a876ddaf8439ef60d6434f21ef8d87efc5b7"}, + {file = "wrapt-1.17.2-cp38-cp38-win_amd64.whl", hash = "sha256:95c658736ec15602da0ed73f312d410117723914a5c91a14ee4cdd72f1d790b3"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99039fa9e6306880572915728d7f6c24a86ec57b0a83f6b2491e1d8ab0235b9a"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2696993ee1eebd20b8e4ee4356483c4cb696066ddc24bd70bcbb80fa56ff9061"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:612dff5db80beef9e649c6d803a8d50c409082f1fedc9dbcdfde2983b2025b82"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62c2caa1585c82b3f7a7ab56afef7b3602021d6da34fbc1cf234ff139fed3cd9"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c958bcfd59bacc2d0249dcfe575e71da54f9dcf4a8bdf89c4cb9a68a1170d73f"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc78a84e2dfbc27afe4b2bd7c80c8db9bca75cc5b85df52bfe634596a1da846b"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba0f0eb61ef00ea10e00eb53a9129501f52385c44853dbd6c4ad3f403603083f"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1e1fe0e6ab7775fd842bc39e86f6dcfc4507ab0ffe206093e76d61cde37225c8"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c86563182421896d73858e08e1db93afdd2b947a70064b813d515d66549e15f9"}, + {file = "wrapt-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f393cda562f79828f38a819f4788641ac7c4085f30f1ce1a68672baa686482bb"}, + {file = "wrapt-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:36ccae62f64235cf8ddb682073a60519426fdd4725524ae38874adf72b5f2aeb"}, + {file = "wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8"}, + {file = "wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3"}, +] + [[package]] name = "zipp" version = "3.21.0" diff --git a/sample-apps/quart-mongo/poetry.lock b/sample-apps/quart-mongo/poetry.lock index a06fa4cc..3ca1c0a2 100644 --- a/sample-apps/quart-mongo/poetry.lock +++ b/sample-apps/quart-mongo/poetry.lock @@ -2,7 +2,7 @@ [[package]] name = "aikido-zen" -version = "1.1.1" +version = "1.0.0" description = "Aikido Zen for Python" optional = false python-versions = "^3.8" @@ -15,6 +15,7 @@ packaging = "^24.1" python-dotenv = "^1.0.1" regex = "^2024.5.15" requests = "^2.32.3" +wrapt = "^1.17" [package.source] type = "directory" @@ -993,6 +994,95 @@ MarkupSafe = ">=2.1.1" [package.extras] watchdog = ["watchdog (>=2.3)"] +[[package]] +name = "wrapt" +version = "1.17.2" +description = "Module for decorators, wrappers and monkey patching." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984"}, + {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22"}, + {file = "wrapt-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62"}, + {file = "wrapt-1.17.2-cp310-cp310-win32.whl", hash = "sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563"}, + {file = "wrapt-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72"}, + {file = "wrapt-1.17.2-cp311-cp311-win32.whl", hash = "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317"}, + {file = "wrapt-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9"}, + {file = "wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9"}, + {file = "wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504"}, + {file = "wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a"}, + {file = "wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f"}, + {file = "wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555"}, + {file = "wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c803c401ea1c1c18de70a06a6f79fcc9c5acfc79133e9869e730ad7f8ad8ef9"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f917c1180fdb8623c2b75a99192f4025e412597c50b2ac870f156de8fb101119"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ecc840861360ba9d176d413a5489b9a0aff6d6303d7e733e2c4623cfa26904a6"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb87745b2e6dc56361bfde481d5a378dc314b252a98d7dd19a651a3fa58f24a9"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58455b79ec2661c3600e65c0a716955adc2410f7383755d537584b0de41b1d8a"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4e42a40a5e164cbfdb7b386c966a588b1047558a990981ace551ed7e12ca9c2"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:91bd7d1773e64019f9288b7a5101f3ae50d3d8e6b1de7edee9c2ccc1d32f0c0a"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:bb90fb8bda722a1b9d48ac1e6c38f923ea757b3baf8ebd0c82e09c5c1a0e7a04"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:08e7ce672e35efa54c5024936e559469436f8b8096253404faeb54d2a878416f"}, + {file = "wrapt-1.17.2-cp38-cp38-win32.whl", hash = "sha256:410a92fefd2e0e10d26210e1dfb4a876ddaf8439ef60d6434f21ef8d87efc5b7"}, + {file = "wrapt-1.17.2-cp38-cp38-win_amd64.whl", hash = "sha256:95c658736ec15602da0ed73f312d410117723914a5c91a14ee4cdd72f1d790b3"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99039fa9e6306880572915728d7f6c24a86ec57b0a83f6b2491e1d8ab0235b9a"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2696993ee1eebd20b8e4ee4356483c4cb696066ddc24bd70bcbb80fa56ff9061"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:612dff5db80beef9e649c6d803a8d50c409082f1fedc9dbcdfde2983b2025b82"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62c2caa1585c82b3f7a7ab56afef7b3602021d6da34fbc1cf234ff139fed3cd9"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c958bcfd59bacc2d0249dcfe575e71da54f9dcf4a8bdf89c4cb9a68a1170d73f"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc78a84e2dfbc27afe4b2bd7c80c8db9bca75cc5b85df52bfe634596a1da846b"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba0f0eb61ef00ea10e00eb53a9129501f52385c44853dbd6c4ad3f403603083f"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1e1fe0e6ab7775fd842bc39e86f6dcfc4507ab0ffe206093e76d61cde37225c8"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c86563182421896d73858e08e1db93afdd2b947a70064b813d515d66549e15f9"}, + {file = "wrapt-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f393cda562f79828f38a819f4788641ac7c4085f30f1ce1a68672baa686482bb"}, + {file = "wrapt-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:36ccae62f64235cf8ddb682073a60519426fdd4725524ae38874adf72b5f2aeb"}, + {file = "wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8"}, + {file = "wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3"}, +] + [[package]] name = "wsproto" version = "1.2.0" diff --git a/sample-apps/quart-postgres-uvicorn/poetry.lock b/sample-apps/quart-postgres-uvicorn/poetry.lock index 6781095d..2bb4fefe 100644 --- a/sample-apps/quart-postgres-uvicorn/poetry.lock +++ b/sample-apps/quart-postgres-uvicorn/poetry.lock @@ -2,7 +2,7 @@ [[package]] name = "aikido-zen" -version = "1.1.1" +version = "1.0.0" description = "Aikido Zen for Python" optional = false python-versions = "^3.8" @@ -15,6 +15,7 @@ packaging = "^24.1" python-dotenv = "^1.0.1" regex = "^2024.5.15" requests = "^2.32.3" +wrapt = "^1.17" [package.source] type = "directory" @@ -965,6 +966,95 @@ MarkupSafe = ">=2.1.1" [package.extras] watchdog = ["watchdog (>=2.3)"] +[[package]] +name = "wrapt" +version = "1.17.2" +description = "Module for decorators, wrappers and monkey patching." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984"}, + {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22"}, + {file = "wrapt-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62"}, + {file = "wrapt-1.17.2-cp310-cp310-win32.whl", hash = "sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563"}, + {file = "wrapt-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72"}, + {file = "wrapt-1.17.2-cp311-cp311-win32.whl", hash = "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317"}, + {file = "wrapt-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9"}, + {file = "wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9"}, + {file = "wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504"}, + {file = "wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a"}, + {file = "wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f"}, + {file = "wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555"}, + {file = "wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c803c401ea1c1c18de70a06a6f79fcc9c5acfc79133e9869e730ad7f8ad8ef9"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f917c1180fdb8623c2b75a99192f4025e412597c50b2ac870f156de8fb101119"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ecc840861360ba9d176d413a5489b9a0aff6d6303d7e733e2c4623cfa26904a6"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb87745b2e6dc56361bfde481d5a378dc314b252a98d7dd19a651a3fa58f24a9"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58455b79ec2661c3600e65c0a716955adc2410f7383755d537584b0de41b1d8a"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4e42a40a5e164cbfdb7b386c966a588b1047558a990981ace551ed7e12ca9c2"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:91bd7d1773e64019f9288b7a5101f3ae50d3d8e6b1de7edee9c2ccc1d32f0c0a"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:bb90fb8bda722a1b9d48ac1e6c38f923ea757b3baf8ebd0c82e09c5c1a0e7a04"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:08e7ce672e35efa54c5024936e559469436f8b8096253404faeb54d2a878416f"}, + {file = "wrapt-1.17.2-cp38-cp38-win32.whl", hash = "sha256:410a92fefd2e0e10d26210e1dfb4a876ddaf8439ef60d6434f21ef8d87efc5b7"}, + {file = "wrapt-1.17.2-cp38-cp38-win_amd64.whl", hash = "sha256:95c658736ec15602da0ed73f312d410117723914a5c91a14ee4cdd72f1d790b3"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99039fa9e6306880572915728d7f6c24a86ec57b0a83f6b2491e1d8ab0235b9a"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2696993ee1eebd20b8e4ee4356483c4cb696066ddc24bd70bcbb80fa56ff9061"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:612dff5db80beef9e649c6d803a8d50c409082f1fedc9dbcdfde2983b2025b82"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62c2caa1585c82b3f7a7ab56afef7b3602021d6da34fbc1cf234ff139fed3cd9"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c958bcfd59bacc2d0249dcfe575e71da54f9dcf4a8bdf89c4cb9a68a1170d73f"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc78a84e2dfbc27afe4b2bd7c80c8db9bca75cc5b85df52bfe634596a1da846b"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba0f0eb61ef00ea10e00eb53a9129501f52385c44853dbd6c4ad3f403603083f"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1e1fe0e6ab7775fd842bc39e86f6dcfc4507ab0ffe206093e76d61cde37225c8"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c86563182421896d73858e08e1db93afdd2b947a70064b813d515d66549e15f9"}, + {file = "wrapt-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f393cda562f79828f38a819f4788641ac7c4085f30f1ce1a68672baa686482bb"}, + {file = "wrapt-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:36ccae62f64235cf8ddb682073a60519426fdd4725524ae38874adf72b5f2aeb"}, + {file = "wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8"}, + {file = "wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3"}, +] + [[package]] name = "wsproto" version = "1.2.0" diff --git a/sample-apps/starlette-postgres-uvicorn/poetry.lock b/sample-apps/starlette-postgres-uvicorn/poetry.lock index 7a01f488..479a6e7b 100644 --- a/sample-apps/starlette-postgres-uvicorn/poetry.lock +++ b/sample-apps/starlette-postgres-uvicorn/poetry.lock @@ -2,7 +2,7 @@ [[package]] name = "aikido-zen" -version = "1.1.1" +version = "1.0.0" description = "Aikido Zen for Python" optional = false python-versions = "^3.8" @@ -15,6 +15,7 @@ packaging = "^24.1" python-dotenv = "^1.0.1" regex = "^2024.5.15" requests = "^2.32.3" +wrapt = "^1.17" [package.source] type = "directory" @@ -787,6 +788,95 @@ typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} [package.extras] standard = ["colorama (>=0.4)", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] +[[package]] +name = "wrapt" +version = "1.17.2" +description = "Module for decorators, wrappers and monkey patching." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984"}, + {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22"}, + {file = "wrapt-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72"}, + {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c"}, + {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62"}, + {file = "wrapt-1.17.2-cp310-cp310-win32.whl", hash = "sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563"}, + {file = "wrapt-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda"}, + {file = "wrapt-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000"}, + {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662"}, + {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72"}, + {file = "wrapt-1.17.2-cp311-cp311-win32.whl", hash = "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317"}, + {file = "wrapt-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392"}, + {file = "wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b"}, + {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae"}, + {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9"}, + {file = "wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9"}, + {file = "wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998"}, + {file = "wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6"}, + {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b"}, + {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504"}, + {file = "wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a"}, + {file = "wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b"}, + {file = "wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb"}, + {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6"}, + {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f"}, + {file = "wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555"}, + {file = "wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c803c401ea1c1c18de70a06a6f79fcc9c5acfc79133e9869e730ad7f8ad8ef9"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f917c1180fdb8623c2b75a99192f4025e412597c50b2ac870f156de8fb101119"}, + {file = "wrapt-1.17.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ecc840861360ba9d176d413a5489b9a0aff6d6303d7e733e2c4623cfa26904a6"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb87745b2e6dc56361bfde481d5a378dc314b252a98d7dd19a651a3fa58f24a9"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58455b79ec2661c3600e65c0a716955adc2410f7383755d537584b0de41b1d8a"}, + {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4e42a40a5e164cbfdb7b386c966a588b1047558a990981ace551ed7e12ca9c2"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:91bd7d1773e64019f9288b7a5101f3ae50d3d8e6b1de7edee9c2ccc1d32f0c0a"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:bb90fb8bda722a1b9d48ac1e6c38f923ea757b3baf8ebd0c82e09c5c1a0e7a04"}, + {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:08e7ce672e35efa54c5024936e559469436f8b8096253404faeb54d2a878416f"}, + {file = "wrapt-1.17.2-cp38-cp38-win32.whl", hash = "sha256:410a92fefd2e0e10d26210e1dfb4a876ddaf8439ef60d6434f21ef8d87efc5b7"}, + {file = "wrapt-1.17.2-cp38-cp38-win_amd64.whl", hash = "sha256:95c658736ec15602da0ed73f312d410117723914a5c91a14ee4cdd72f1d790b3"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99039fa9e6306880572915728d7f6c24a86ec57b0a83f6b2491e1d8ab0235b9a"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2696993ee1eebd20b8e4ee4356483c4cb696066ddc24bd70bcbb80fa56ff9061"}, + {file = "wrapt-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:612dff5db80beef9e649c6d803a8d50c409082f1fedc9dbcdfde2983b2025b82"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62c2caa1585c82b3f7a7ab56afef7b3602021d6da34fbc1cf234ff139fed3cd9"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c958bcfd59bacc2d0249dcfe575e71da54f9dcf4a8bdf89c4cb9a68a1170d73f"}, + {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc78a84e2dfbc27afe4b2bd7c80c8db9bca75cc5b85df52bfe634596a1da846b"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba0f0eb61ef00ea10e00eb53a9129501f52385c44853dbd6c4ad3f403603083f"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1e1fe0e6ab7775fd842bc39e86f6dcfc4507ab0ffe206093e76d61cde37225c8"}, + {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c86563182421896d73858e08e1db93afdd2b947a70064b813d515d66549e15f9"}, + {file = "wrapt-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f393cda562f79828f38a819f4788641ac7c4085f30f1ce1a68672baa686482bb"}, + {file = "wrapt-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:36ccae62f64235cf8ddb682073a60519426fdd4725524ae38874adf72b5f2aeb"}, + {file = "wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8"}, + {file = "wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3"}, +] + [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0" From 78348610bcf3d9021876feb45acf98bc6628ff29 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Tue, 15 Apr 2025 13:33:51 +0200 Subject: [PATCH 51/60] Update actions/setup-python v2 -> v5 --- .github/workflows/benchmark.yml | 6 +++--- .github/workflows/end2end.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/smoke-test-ffi.yml | 2 +- .github/workflows/unit-test.yml | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 74a001b5..20e22e05 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -14,7 +14,7 @@ jobs: working-directory: ./sample-apps/databases run: docker compose up --build -d - name: Set up Python 3.9 - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: 3.9 @@ -46,7 +46,7 @@ jobs: working-directory: ./sample-apps/databases run: docker compose up --build -d - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install dependencies & build @@ -76,7 +76,7 @@ jobs: working-directory: ./sample-apps/databases run: docker compose up --build -d - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install dependencies & build diff --git a/.github/workflows/end2end.yml b/.github/workflows/end2end.yml index 05d16c68..2c10c24c 100644 --- a/.github/workflows/end2end.yml +++ b/.github/workflows/end2end.yml @@ -53,7 +53,7 @@ jobs: docker run --name mock_core -d -p 5000:5000 mock_core - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a51a28ce..810a19c2 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -9,7 +9,7 @@ jobs: uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: '3.x' diff --git a/.github/workflows/smoke-test-ffi.yml b/.github/workflows/smoke-test-ffi.yml index eb9184a4..86819651 100644 --- a/.github/workflows/smoke-test-ffi.yml +++ b/.github/workflows/smoke-test-ffi.yml @@ -20,7 +20,7 @@ jobs: uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: 3.12 diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 03bed046..6eee5077 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -22,7 +22,7 @@ jobs: run: | sudo echo "127.0.0.1 local.aikido.io" | sudo tee -a /etc/hosts - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} From 70305bff0738e1135002b8706fddd94ca9f38e00 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Tue, 15 Apr 2025 13:55:04 +0200 Subject: [PATCH 52/60] Fix @after by removing finally: which was swallowing the error --- aikido_zen/sinks/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aikido_zen/sinks/__init__.py b/aikido_zen/sinks/__init__.py index da48d57d..460f0d99 100644 --- a/aikido_zen/sinks/__init__.py +++ b/aikido_zen/sinks/__init__.py @@ -64,7 +64,7 @@ def decorator(func, instance, args, kwargs): logger.debug( "%s:%s wrapping-after error: %s", func.__module__, func.__name__, e ) - finally: - return return_value + + return return_value return decorator From 35c4c8215496b530f9cfc48d4c90d47e5de1ec31 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Tue, 15 Apr 2025 14:16:32 +0200 Subject: [PATCH 53/60] Fix broken subprocess test cases --- aikido_zen/sinks/tests/subprocess_test.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/aikido_zen/sinks/tests/subprocess_test.py b/aikido_zen/sinks/tests/subprocess_test.py index df0485d8..8a8bb473 100644 --- a/aikido_zen/sinks/tests/subprocess_test.py +++ b/aikido_zen/sinks/tests/subprocess_test.py @@ -175,27 +175,27 @@ def test_subprocess_check_output(): subprocess.check_output(["ls", "-la"], shell=True) args = ("ls -la",) - mock_run_vulnerability_scan.assert_called_with(kind=kind, op=op, args=args) + mock_run_vulnerability_scan.assert_any_call(kind=kind, op=op, args=args) with pytest.raises(subprocess.CalledProcessError): subprocess.check_output(["cfsknflks"], shell=True) args = ("cfsknflks",) - mock_run_vulnerability_scan.assert_called_with(kind=kind, op=op, args=args) + mock_run_vulnerability_scan.assert_any_call(kind=kind, op=op, args=args) with pytest.raises(subprocess.CalledProcessError): subprocess.check_output(("tuple", "command"), shell=True) args = ("tuple command",) - mock_run_vulnerability_scan.assert_called_with(kind=kind, op=op, args=args) + mock_run_vulnerability_scan.assert_any_call(kind=kind, op=op, args=args) with pytest.raises(subprocess.CalledProcessError): subprocess.check_output({"key": "value"}, shell=True) args = ("key",) - mock_run_vulnerability_scan.assert_called_with(kind=kind, op=op, args=args) + mock_run_vulnerability_scan.assert_any_call(kind=kind, op=op, args=args) with pytest.raises(subprocess.CalledProcessError): subprocess.check_output({"ke": "value", "key2": "value2"}, shell=True) args = ("ke key2",) - mock_run_vulnerability_scan.assert_called_with(kind=kind, op=op, args=args) + mock_run_vulnerability_scan.assert_any_call(kind=kind, op=op, args=args) def test_subprocess_check_output_2(): From 3618197640f6c0f697ff6ca9b74be65e605fcb2c Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Tue, 15 Apr 2025 14:19:20 +0200 Subject: [PATCH 54/60] Remove ms checks for starlette benchmark in favour of percentages --- benchmarks/starlette_benchmark.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/benchmarks/starlette_benchmark.py b/benchmarks/starlette_benchmark.py index c6144712..920112e5 100644 --- a/benchmarks/starlette_benchmark.py +++ b/benchmarks/starlette_benchmark.py @@ -22,7 +22,7 @@ def extract_requests_and_latency_tuple(output): print(output.stderr.strip()) sys.exit(1) -def run_benchmark(route1, route2, descriptor, percentage_limit, ms_limit): +def run_benchmark(route1, route2, descriptor, percentage_limit): output_nofw = subprocess.run( generate_wrk_command_for_url(route2), @@ -51,8 +51,6 @@ def run_benchmark(route1, route2, descriptor, percentage_limit, ms_limit): delta_in_ms = round(result_fw[1] - result_nofw[1], 2) print(f"-> Delta in ms: {delta_in_ms}ms after running load test on {descriptor}") - if delta_in_ms > ms_limit: - sys.exit(1) delay_percentage = round( (result_nofw[0] - result_fw[0]) / result_nofw[0] * 100 ) @@ -67,9 +65,9 @@ def run_benchmark(route1, route2, descriptor, percentage_limit, ms_limit): "http://localhost:8102/delayed_route", "http://localhost:8103/delayed_route", "a non empty route which makes a simulated request to a database", - percentage_limit=15, ms_limit=20 + percentage_limit=15 ) run_benchmark( "http://localhost:8102/just", "http://localhost:8103/just", "an empty route", - percentage_limit=30, ms_limit=25 + percentage_limit=30 ) From 31705c1b7f08d84cbdb334a287698ec3623a2ec2 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Tue, 15 Apr 2025 14:25:36 +0200 Subject: [PATCH 55/60] Exclude psycopg2 testing for python 3.13 --- aikido_zen/sinks/tests/psycopg2_test.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/aikido_zen/sinks/tests/psycopg2_test.py b/aikido_zen/sinks/tests/psycopg2_test.py index 1c0b6b47..7bf62cca 100644 --- a/aikido_zen/sinks/tests/psycopg2_test.py +++ b/aikido_zen/sinks/tests/psycopg2_test.py @@ -1,3 +1,5 @@ +import sys + import pytest from unittest.mock import patch import aikido_zen.sinks.psycopg2 @@ -6,6 +8,9 @@ kind = "sql_injection" op = "pymysql.connections.query" +# psycopg2 not working on python 3.13 for now +skip_python_3_13 = sys.version_info[:2] == (3, 13) + @pytest.fixture def database_conn(): @@ -33,6 +38,7 @@ def database_conn_empty_cursor(): ) +@pytest.mark.skipif(skip_python_3_13, reason="Skipping test on Python 3.13") def test_cursor_execute(database_conn): reset_comms() with patch( @@ -52,6 +58,7 @@ def test_cursor_execute(database_conn): mock_run_vulnerability_scan.assert_called_once() +@pytest.mark.skipif(skip_python_3_13, reason="Skipping test on Python 3.13") def test_cursor_execute2(database_conn_empty_cursor): reset_comms() with patch( @@ -71,6 +78,7 @@ def test_cursor_execute2(database_conn_empty_cursor): mock_run_vulnerability_scan.assert_called_once() +@pytest.mark.skipif(skip_python_3_13, reason="Skipping test on Python 3.13") def test_cursor_execute_parameterized(database_conn): reset_comms() with patch( @@ -87,6 +95,7 @@ def test_cursor_execute_parameterized(database_conn): database_conn.close() +@pytest.mark.skipif(skip_python_3_13, reason="Skipping test on Python 3.13") def test_cursor_execute_parameterized2(database_conn_empty_cursor): reset_comms() with patch( @@ -106,6 +115,7 @@ def test_cursor_execute_parameterized2(database_conn_empty_cursor): mock_run_vulnerability_scan.assert_called_once() +@pytest.mark.skipif(skip_python_3_13, reason="Skipping test on Python 3.13") def test_cursor_executemany(database_conn): reset_comms() with patch( @@ -130,6 +140,7 @@ def test_cursor_executemany(database_conn): database_conn.close() +@pytest.mark.skipif(skip_python_3_13, reason="Skipping test on Python 3.13") def test_cursor_executemany2(database_conn_empty_cursor): reset_comms() with patch( From 3aa49ccad3f57ce2835effa58eeac4675bc3e5da Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Tue, 15 Apr 2025 14:34:01 +0200 Subject: [PATCH 56/60] Make sure psycopg2.py implementation is the same as prev one --- aikido_zen/sinks/psycopg2.py | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/aikido_zen/sinks/psycopg2.py b/aikido_zen/sinks/psycopg2.py index 7f0da4c6..25358692 100644 --- a/aikido_zen/sinks/psycopg2.py +++ b/aikido_zen/sinks/psycopg2.py @@ -6,7 +6,7 @@ from aikido_zen.background_process.packages import is_package_compatible import aikido_zen.vulnerabilities as vulns from aikido_zen.helpers.get_argument import get_argument -from aikido_zen.sinks import on_import, before, patch_function +from aikido_zen.sinks import on_import, before, patch_function, after @on_import("psycopg2") @@ -27,27 +27,22 @@ def patch(m): patch_function(m, "connect", _connect) -def _connect(func, instance, args, kwargs): - cursor_factory = get_argument(args, kwargs, 2, "cursor_factory") - if "cursor_factory" in kwargs: - del kwargs["cursor_factory"] - try: - if cursor_factory is None: - import psycopg2.extensions - - class AikidoDefaultCursor(psycopg2.extensions.cursor): - pass - - cursor_factory = AikidoDefaultCursor +@after +def _connect(func, instance, args, kwargs, rv): + """ + the return value (rv) is the new connection object, we'll change the cursor_factory attribute here. + """ + # Create new default cursor factory if not exists + if rv.cursor_factory is None: + import psycopg2.extensions - # patch execute or executemany of an already existing cursor or of a new one - patch_function(cursor_factory, "execute", _execute) - patch_function(cursor_factory, "executemany", _execute) + class AikidoDefaultCursor(psycopg2.extensions.cursor): + pass - except Exception as e: - logger.info("patch of psycopg2 failed: %s", e.msg) + rv.cursor_factory = AikidoDefaultCursor - return func(*args, cursor_factory=cursor_factory, **kwargs) + patch_function(rv.cursor_factory, "execute", _execute) + patch_function(rv.cursor_factory, "executemany", _execute) @before From 807b9817789d70d23598ffa1d0ec8a3af8b2a0dd Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Tue, 15 Apr 2025 16:43:54 +0200 Subject: [PATCH 57/60] Add extra tests for psycopg2 and fix issue for immutables --- aikido_zen/sinks/psycopg2.py | 25 ++++++---- aikido_zen/sinks/tests/psycopg2_test.py | 62 +++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 10 deletions(-) diff --git a/aikido_zen/sinks/psycopg2.py b/aikido_zen/sinks/psycopg2.py index 25358692..85bb3148 100644 --- a/aikido_zen/sinks/psycopg2.py +++ b/aikido_zen/sinks/psycopg2.py @@ -2,7 +2,6 @@ Sink module for `psycopg2` """ -from aikido_zen import logger from aikido_zen.background_process.packages import is_package_compatible import aikido_zen.vulnerabilities as vulns from aikido_zen.helpers.get_argument import get_argument @@ -28,25 +27,31 @@ def patch(m): @after -def _connect(func, instance, args, kwargs, rv): +def _connect(func, instance, _args, _kwargs, rv): """ the return value (rv) is the new connection object, we'll change the cursor_factory attribute here. """ - # Create new default cursor factory if not exists if rv.cursor_factory is None: + # set default if not set import psycopg2.extensions - class AikidoDefaultCursor(psycopg2.extensions.cursor): - pass + rv.cursor_factory = psycopg2.extensions.cursor - rv.cursor_factory = AikidoDefaultCursor - - patch_function(rv.cursor_factory, "execute", _execute) - patch_function(rv.cursor_factory, "executemany", _execute) + rv.cursor_factory = type( + "AikidoPsycopg2Cursor", + (rv.cursor_factory,), + { + # Allows us to modify these otherwise immutable functions + "execute": rv.cursor_factory.execute, + "executemany": rv.cursor_factory.executemany, + }, + ) + patch_function(rv.cursor_factory, "execute", psycopg2_patch) + patch_function(rv.cursor_factory, "executemany", psycopg2_patch) @before -def _execute(func, instance, args, kwargs): +def psycopg2_patch(func, instance, args, kwargs): query = get_argument(args, kwargs, 0, "query") op = f"psycopg2.Connection.Cursor.{func.__name__}" vulns.run_vulnerability_scan(kind="sql_injection", op=op, args=(query, "postgres")) diff --git a/aikido_zen/sinks/tests/psycopg2_test.py b/aikido_zen/sinks/tests/psycopg2_test.py index 7bf62cca..f5384487 100644 --- a/aikido_zen/sinks/tests/psycopg2_test.py +++ b/aikido_zen/sinks/tests/psycopg2_test.py @@ -26,6 +26,20 @@ def database_conn(): ) +@pytest.fixture +def database_conn_immutable_cursor(): + import psycopg2 + from psycopg2.extensions import cursor + + return psycopg2.connect( + cursor_factory=cursor, + host="127.0.0.1", + user="user", + password="password", + database="db", + ) + + @pytest.fixture def database_conn_empty_cursor(): import psycopg2 @@ -45,6 +59,7 @@ def test_cursor_execute(database_conn): "aikido_zen.vulnerabilities.run_vulnerability_scan" ) as mock_run_vulnerability_scan: cursor = database_conn.cursor() + print(cursor) query = "SELECT * FROM dogs" cursor.execute(query) @@ -78,6 +93,26 @@ def test_cursor_execute2(database_conn_empty_cursor): mock_run_vulnerability_scan.assert_called_once() +@pytest.mark.skipif(skip_python_3_13, reason="Skipping test on Python 3.13") +def test_cursor_execute3(database_conn_immutable_cursor): + reset_comms() + with patch( + "aikido_zen.vulnerabilities.run_vulnerability_scan" + ) as mock_run_vulnerability_scan: + cursor = database_conn_immutable_cursor.cursor() + query = "SELECT * FROM dogs" + cursor.execute(query) + + called_with_args = mock_run_vulnerability_scan.call_args[1]["args"] + assert called_with_args[0] == query + assert called_with_args[1] == "postgres" + mock_run_vulnerability_scan.assert_called_once() + + cursor.fetchall() + database_conn_immutable_cursor.close() + mock_run_vulnerability_scan.assert_called_once() + + @pytest.mark.skipif(skip_python_3_13, reason="Skipping test on Python 3.13") def test_cursor_execute_parameterized(database_conn): reset_comms() @@ -165,3 +200,30 @@ def test_cursor_executemany2(database_conn_empty_cursor): cursor.close() database_conn_empty_cursor.close() mock_run_vulnerability_scan.assert_called_once() + + +@pytest.mark.skipif(skip_python_3_13, reason="Skipping test on Python 3.13") +def test_cursor_executemany3(database_conn_immutable_cursor): + reset_comms() + with patch( + "aikido_zen.vulnerabilities.run_vulnerability_scan" + ) as mock_run_vulnerability_scan: + cursor = database_conn_immutable_cursor.cursor() + data = [ + ("Doggy", False), + ("Doggy 2", True), + ("Dogski", True), + ] + cursor.executemany("INSERT INTO dogs (dog_name, isadmin) VALUES (%s, %s)", data) + called_with_args = mock_run_vulnerability_scan.call_args[1]["args"] + assert ( + called_with_args[0] + == "INSERT INTO dogs (dog_name, isadmin) VALUES (%s, %s)" + ) + assert called_with_args[1] == "postgres" + mock_run_vulnerability_scan.assert_called_once() + + database_conn_immutable_cursor.commit() + cursor.close() + database_conn_immutable_cursor.close() + mock_run_vulnerability_scan.assert_called_once() From b8eec8f7fbea61af89d0589af69ed461ba710771 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Tue, 15 Apr 2025 16:49:16 +0200 Subject: [PATCH 58/60] use assert_any_call for python 3.13 --- aikido_zen/sinks/tests/os_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aikido_zen/sinks/tests/os_test.py b/aikido_zen/sinks/tests/os_test.py index c3bd9648..4f3d35e4 100644 --- a/aikido_zen/sinks/tests/os_test.py +++ b/aikido_zen/sinks/tests/os_test.py @@ -15,7 +15,7 @@ def test_ospath_commands(): os.path.realpath("test/test2") op = "os.path.join" args = ("test/test2",) - mock_run_vulnerability_scan.assert_called_with(kind=kind, op=op, args=args) + mock_run_vulnerability_scan.assert_any_call(kind=kind, op=op, args=args) with pytest.raises(FileNotFoundError): os.path.getsize("aqkqjefbkqlleq_qkvfjksaicuaviel") @@ -27,7 +27,7 @@ def test_ospath_commands(): os.path.realpath(b"te2st/test2") op = "os.path.join" args = (b"te2st/test2",) - mock_run_vulnerability_scan.assert_called_with(kind=kind, op=op, args=args) + mock_run_vulnerability_scan.assert_any_call(kind=kind, op=op, args=args) path1 = Path("./", "../", "test/../test2") with pytest.raises(FileNotFoundError): From 0aabc2cb868d2d87ee0195bb3f4f929647a461c1 Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Wed, 16 Apr 2025 10:23:53 +0200 Subject: [PATCH 59/60] Patch os.path.realpath for python 3.13 --- aikido_zen/sinks/os.py | 3 ++- aikido_zen/sinks/tests/os_test.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/aikido_zen/sinks/os.py b/aikido_zen/sinks/os.py index 02939d0a..d557978f 100644 --- a/aikido_zen/sinks/os.py +++ b/aikido_zen/sinks/os.py @@ -17,7 +17,7 @@ def _os_patch(func, instance, args, kwargs): continue # change op if it's an os.path function op = f"os.{func.__name__}" - if func.__name__ in ("getsize", "join", "expanduser", "expandvars"): + if func.__name__ in ("getsize", "join", "expanduser", "expandvars", "realpath"): op = f"os.path.{func.__name__}" vulns.run_vulnerability_scan(kind="path_traversal", op=op, args=(path,)) @@ -55,3 +55,4 @@ def patch(m): patch_function(m, "path.join", _os_patch) patch_function(m, "path.expanduser", _os_patch) patch_function(m, "path.expandvars", _os_patch) + patch_function(m, "path.realpath", _os_patch) # Python 3.13 diff --git a/aikido_zen/sinks/tests/os_test.py b/aikido_zen/sinks/tests/os_test.py index 4f3d35e4..ab77b1a0 100644 --- a/aikido_zen/sinks/tests/os_test.py +++ b/aikido_zen/sinks/tests/os_test.py @@ -13,7 +13,7 @@ def test_ospath_commands(): import os os.path.realpath("test/test2") - op = "os.path.join" + op = "os.path.realpath" args = ("test/test2",) mock_run_vulnerability_scan.assert_any_call(kind=kind, op=op, args=args) From b29cc3eafefd45ce46987acb05b75ff83b425c0e Mon Sep 17 00:00:00 2001 From: BitterPanda63 Date: Wed, 16 Apr 2025 10:23:53 +0200 Subject: [PATCH 60/60] Patch os.path.realpath for python 3.13 --- aikido_zen/sinks/os.py | 3 ++- aikido_zen/sinks/tests/os_test.py | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/aikido_zen/sinks/os.py b/aikido_zen/sinks/os.py index 02939d0a..d557978f 100644 --- a/aikido_zen/sinks/os.py +++ b/aikido_zen/sinks/os.py @@ -17,7 +17,7 @@ def _os_patch(func, instance, args, kwargs): continue # change op if it's an os.path function op = f"os.{func.__name__}" - if func.__name__ in ("getsize", "join", "expanduser", "expandvars"): + if func.__name__ in ("getsize", "join", "expanduser", "expandvars", "realpath"): op = f"os.path.{func.__name__}" vulns.run_vulnerability_scan(kind="path_traversal", op=op, args=(path,)) @@ -55,3 +55,4 @@ def patch(m): patch_function(m, "path.join", _os_patch) patch_function(m, "path.expanduser", _os_patch) patch_function(m, "path.expandvars", _os_patch) + patch_function(m, "path.realpath", _os_patch) # Python 3.13 diff --git a/aikido_zen/sinks/tests/os_test.py b/aikido_zen/sinks/tests/os_test.py index 4f3d35e4..fc55f66f 100644 --- a/aikido_zen/sinks/tests/os_test.py +++ b/aikido_zen/sinks/tests/os_test.py @@ -13,7 +13,7 @@ def test_ospath_commands(): import os os.path.realpath("test/test2") - op = "os.path.join" + op = "os.path.realpath" args = ("test/test2",) mock_run_vulnerability_scan.assert_any_call(kind=kind, op=op, args=args) @@ -25,7 +25,7 @@ def test_ospath_commands(): mock_run_vulnerability_scan.assert_any_call(kind=kind, op=op, args=args) os.path.realpath(b"te2st/test2") - op = "os.path.join" + op = "os.path.realpath" args = (b"te2st/test2",) mock_run_vulnerability_scan.assert_any_call(kind=kind, op=op, args=args)