UAT: Plugin module allowlist hardcoded to cleveragents.* — third-party plugins from external packages cannot be loaded #5710

Open
opened 2026-04-09 08:45:19 +00:00 by HAL9000 · 0 comments
Owner

Bug Report

Feature Area: Plugin Architecture — Plugin Isolation / Security
Priority: Backlog (non-critical, but blocks third-party plugin ecosystem)

What Was Tested

Analyzed src/cleveragents/infrastructure/plugins/loader.py for the module prefix allowlist behavior.

Expected Behavior (from spec)

The spec (§Extensibility, §Plugin Architecture Overview) describes CleverAgents as an extensible platform where third-party developers can create plugins. The plugin system should support loading plugins from any installed Python package, not just packages within the cleveragents.* namespace.

Actual Behavior

The PluginLoader has a hardcoded default allowlist that only permits modules starting with cleveragents.:

# src/cleveragents/infrastructure/plugins/loader.py
_DEFAULT_ALLOWED_PREFIXES: tuple[str, ...] = ("cleveragents.",)

class PluginLoader:
    def __init__(
        self,
        *,
        allowed_prefixes: tuple[str, ...] | None = None,
    ) -> None:
        self._allowed_prefixes: tuple[str, ...] = (
            allowed_prefixes
            if allowed_prefixes is not None
            else _DEFAULT_ALLOWED_PREFIXES  # ← Only "cleveragents." by default
        )

The PluginManager in application/container.py is instantiated with no allowed_prefixes override:

# application/container.py line 820
plugin_manager = providers.Singleton(PluginManager)
# No allowed_prefixes passed → defaults to ("cleveragents.",)

This means any third-party plugin package (e.g., my_company_plugin, cleveragents_extra) cannot be loaded through the standard plugin mechanism without modifying the core code.

Code Location

  • src/cleveragents/infrastructure/plugins/loader.py_DEFAULT_ALLOWED_PREFIXES (line 37)
  • src/cleveragents/application/container.pyPluginManager singleton (line 820)
  • src/cleveragents/config/settings.py — no plugin_allowed_prefixes setting

Impact

Third-party plugin authors cannot publish packages that work with the default CleverAgents installation. They would need to either:

  1. Name their packages cleveragents.* (namespace collision risk)
  2. Modify core code (defeats the purpose of a plugin system)
  3. Use the empty-prefix workaround (disables all security)

Steps to Reproduce

  1. Create a plugin in package my_plugin.my_extension
  2. Register it via entry points: cleveragents.plugins = my-plugin = my_plugin.my_extension:MyPlugin
  3. Call plugin_manager.discover() — plugin is discovered
  4. Call plugin_manager.activate_plugin("my-plugin") — raises PluginLoadError: Module 'my_plugin.my_extension' is not in the allowed prefix list

Suggested Fix

  1. Add a plugin_allowed_prefixes setting to Settings:
plugin_allowed_prefixes: list[str] = Field(
    default=["cleveragents."],
    description="Module prefixes allowed for dynamic plugin import"
)
  1. Wire the setting to PluginManager in the DI container:
plugin_manager = providers.Singleton(
    PluginManager,
    allowed_prefixes=providers.Callable(
        lambda s: tuple(s.plugin_allowed_prefixes),
        settings
    )
)
  1. Document the configuration in the plugin author guide.

Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: uat-tester

## Bug Report **Feature Area**: Plugin Architecture — Plugin Isolation / Security **Priority**: Backlog (non-critical, but blocks third-party plugin ecosystem) ### What Was Tested Analyzed `src/cleveragents/infrastructure/plugins/loader.py` for the module prefix allowlist behavior. ### Expected Behavior (from spec) The spec (§Extensibility, §Plugin Architecture Overview) describes CleverAgents as an extensible platform where third-party developers can create plugins. The plugin system should support loading plugins from any installed Python package, not just packages within the `cleveragents.*` namespace. ### Actual Behavior The `PluginLoader` has a hardcoded default allowlist that only permits modules starting with `cleveragents.`: ```python # src/cleveragents/infrastructure/plugins/loader.py _DEFAULT_ALLOWED_PREFIXES: tuple[str, ...] = ("cleveragents.",) class PluginLoader: def __init__( self, *, allowed_prefixes: tuple[str, ...] | None = None, ) -> None: self._allowed_prefixes: tuple[str, ...] = ( allowed_prefixes if allowed_prefixes is not None else _DEFAULT_ALLOWED_PREFIXES # ← Only "cleveragents." by default ) ``` The `PluginManager` in `application/container.py` is instantiated with no `allowed_prefixes` override: ```python # application/container.py line 820 plugin_manager = providers.Singleton(PluginManager) # No allowed_prefixes passed → defaults to ("cleveragents.",) ``` This means any third-party plugin package (e.g., `my_company_plugin`, `cleveragents_extra`) cannot be loaded through the standard plugin mechanism without modifying the core code. ### Code Location - `src/cleveragents/infrastructure/plugins/loader.py` — `_DEFAULT_ALLOWED_PREFIXES` (line 37) - `src/cleveragents/application/container.py` — `PluginManager` singleton (line 820) - `src/cleveragents/config/settings.py` — no `plugin_allowed_prefixes` setting ### Impact Third-party plugin authors cannot publish packages that work with the default CleverAgents installation. They would need to either: 1. Name their packages `cleveragents.*` (namespace collision risk) 2. Modify core code (defeats the purpose of a plugin system) 3. Use the empty-prefix workaround (disables all security) ### Steps to Reproduce 1. Create a plugin in package `my_plugin.my_extension` 2. Register it via entry points: `cleveragents.plugins = my-plugin = my_plugin.my_extension:MyPlugin` 3. Call `plugin_manager.discover()` — plugin is discovered 4. Call `plugin_manager.activate_plugin("my-plugin")` — raises `PluginLoadError: Module 'my_plugin.my_extension' is not in the allowed prefix list` ### Suggested Fix 1. Add a `plugin_allowed_prefixes` setting to `Settings`: ```python plugin_allowed_prefixes: list[str] = Field( default=["cleveragents."], description="Module prefixes allowed for dynamic plugin import" ) ``` 2. Wire the setting to `PluginManager` in the DI container: ```python plugin_manager = providers.Singleton( PluginManager, allowed_prefixes=providers.Callable( lambda s: tuple(s.plugin_allowed_prefixes), settings ) ) ``` 3. Document the configuration in the plugin author guide. --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: uat-tester
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
cleveragents/cleveragents-core#5710
No description provided.