fix(sdk): guard built-in providers in is_tool_wrapper_provider

- Short-circuit on is_builtin_provider before loading entry points
- Prevent same-name plug-ins from flipping a built-in onto the tool-wrapper path
- Avoid executing plug-in code via ep.load() for built-in names
- Add regression test asserting ep.load is never called
This commit is contained in:
StylusFrost
2026-06-01 19:43:36 +02:00
parent 468234577c
commit 5070ce39c2
2 changed files with 19 additions and 0 deletions
+5
View File
@@ -13,6 +13,7 @@ and `prowler.providers.common.provider` without forming an import cycle.
import importlib.metadata
from prowler.lib.check.external_tool_providers import EXTERNAL_TOOL_PROVIDERS
from prowler.providers.common.builtin import is_builtin_provider
# Module-level cache for entry-point classes consulted by this helper.
# Independent of `Provider._ep_providers` to keep this module leaf — the cost
@@ -53,5 +54,9 @@ def is_tool_wrapper_provider(provider: str) -> bool:
"""
if provider in EXTERNAL_TOOL_PROVIDERS:
return True
# Built-in wins: short-circuit before ep.load() so a same-name plug-in
# cannot flip a built-in onto the tool-wrapper path or run its code.
if is_builtin_provider(provider):
return False
cls = _load_ep_class(provider)
return bool(cls and getattr(cls, "is_external_tool_provider", False))
+14
View File
@@ -70,6 +70,20 @@ class TestIsToolWrapperProvider:
assert is_tool_wrapper_provider("does-not-exist") is False
@patch("prowler.lib.check.tool_wrapper.importlib.metadata.entry_points")
def test_builtin_name_shortcircuits_before_loading_same_name_plugin(self, mock_eps):
"""A plug-in registered under a built-in's name cannot flip the
built-in onto the tool-wrapper path, and its module is never loaded."""
from prowler.lib.check.tool_wrapper import is_tool_wrapper_provider
malicious = _make_entry_point("aws", MagicMock(is_external_tool_provider=True))
mock_eps.return_value = [malicious]
# `aws` is a built-in, so classification short-circuits to False...
assert is_tool_wrapper_provider("aws") is False
# ...and the shadowing plug-in's code is never executed via ep.load().
malicious.load.assert_not_called()
class TestLoadEpClass:
"""_load_ep_class: cache, broken plug-ins, no-match."""