BUG-HUNT: [security] plugins/loader.py load_from_entry_points executes arbitrary modules before allowlist validation #7476

Closed
opened 2026-04-10 20:44:58 +00:00 by HAL9000 · 4 comments
Owner

Bug Report: Security — Plugin Entry Points Execute Arbitrary Code Before Allowlist Check

Severity Assessment

  • Impact: Complete security bypass — malicious third-party packages can execute arbitrary code via entry point registration
  • Likelihood: Medium — requires a malicious package to be installed, but is a known supply-chain attack vector
  • Priority: Critical

Location

  • File: src/cleveragents/infrastructure/plugins/loader.py
  • Function: PluginLoader.load_from_entry_points
  • Lines: 168–172
  • Category: security

Description

ep.load() is called unconditionally for every discovered entry point, importing the module and executing all module-level code, before any prefix validation. The return value is then discarded. This completely defeats the allowlist security described in the docstring. A malicious third-party package can register an entry point pointing to any module and it will be fully imported and executed.

Evidence

for ep in eps:
    try:
        ep.load()                                          # ← arbitrary module imported & executed HERE
        module_path = ep.value.rsplit(":", 1)[0] if ":" in ep.value else ""
        class_name  = ep.value.rsplit(":", 1)[1] if ":" in ep.value else ep.value

        descriptor = PluginDescriptor(
            name=ep.name,
            module_path=module_path,
            class_name=class_name,
            state=PluginState.DISCOVERED,                  # ← only "discovered", never validated
        )

The _validate_module_prefix guard is computed but never called in this code path. When activate_plugin later calls load_class, Python's module cache means the malicious code already ran.

Expected Behavior

The allowlist (_allowed_prefixes) should be checked BEFORE any module is imported/executed.

Actual Behavior

All modules referenced by entry points are imported (and their module-level code executed) before any validation occurs. The allowlist check is effectively bypassed.

Suggested Fix

for ep in eps:
    try:
        # Parse the value string FIRST, validate prefix, THEN load
        if ":" not in ep.value:
            self._logger.warning("plugin.entry_point_invalid_value", name=ep.name, value=ep.value)
            continue
        module_path, class_name = ep.value.rsplit(":", 1)
        self._validate_module_prefix(module_path)   # raises PluginLoadError if not allowed
        ep.load()                                   # only now is it safe to import
        descriptor = PluginDescriptor(...)

Category

security

TDD Note

After this bug issue is verified, a corresponding Type/Testing issue will be created for TDD. The test will use tags: @tdd_issue, @tdd_issue_, and @tdd_expected_fail to prove the bug exists before fixing it.


Automated by CleverAgents Bot
Supervisor: Bug Detection Pool | Agent: bug-hunt-pool-supervisor

## Bug Report: Security — Plugin Entry Points Execute Arbitrary Code Before Allowlist Check ### Severity Assessment - **Impact**: Complete security bypass — malicious third-party packages can execute arbitrary code via entry point registration - **Likelihood**: Medium — requires a malicious package to be installed, but is a known supply-chain attack vector - **Priority**: Critical ### Location - **File**: `src/cleveragents/infrastructure/plugins/loader.py` - **Function**: `PluginLoader.load_from_entry_points` - **Lines**: 168–172 - **Category**: security ### Description `ep.load()` is called unconditionally for every discovered entry point, importing the module and executing all module-level code, **before any prefix validation**. The return value is then discarded. This completely defeats the allowlist security described in the docstring. A malicious third-party package can register an entry point pointing to any module and it will be fully imported and executed. ### Evidence ```python for ep in eps: try: ep.load() # ← arbitrary module imported & executed HERE module_path = ep.value.rsplit(":", 1)[0] if ":" in ep.value else "" class_name = ep.value.rsplit(":", 1)[1] if ":" in ep.value else ep.value descriptor = PluginDescriptor( name=ep.name, module_path=module_path, class_name=class_name, state=PluginState.DISCOVERED, # ← only "discovered", never validated ) ``` The `_validate_module_prefix` guard is computed but **never called** in this code path. When `activate_plugin` later calls `load_class`, Python's module cache means the malicious code already ran. ### Expected Behavior The allowlist (`_allowed_prefixes`) should be checked BEFORE any module is imported/executed. ### Actual Behavior All modules referenced by entry points are imported (and their module-level code executed) before any validation occurs. The allowlist check is effectively bypassed. ### Suggested Fix ```python for ep in eps: try: # Parse the value string FIRST, validate prefix, THEN load if ":" not in ep.value: self._logger.warning("plugin.entry_point_invalid_value", name=ep.name, value=ep.value) continue module_path, class_name = ep.value.rsplit(":", 1) self._validate_module_prefix(module_path) # raises PluginLoadError if not allowed ep.load() # only now is it safe to import descriptor = PluginDescriptor(...) ``` ### Category security ### TDD Note After this bug issue is verified, a corresponding Type/Testing issue will be created for TDD. The test will use tags: @tdd_issue, @tdd_issue_<this-issue-number>, and @tdd_expected_fail to prove the bug exists before fixing it. --- **Automated by CleverAgents Bot** Supervisor: Bug Detection Pool | Agent: bug-hunt-pool-supervisor
HAL9000 added this to the v3.5.0 milestone 2026-04-10 21:38:36 +00:00
Author
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: Critical — Security vulnerability that could allow unauthorized access, path traversal, or arbitrary code execution. Security bugs are always Critical priority.
  • Milestone: v3.5.0 (M6: Autonomy Hardening) — Security hardening and sandbox enforcement are core to this milestone
  • Story Points: 3 (M) — Bug fix with clear reproduction path and suggested fix
  • MoSCoW: Must Have — Security vulnerabilities must be fixed before any release
  • Type: Bug

Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner-pool-supervisor

Issue triaged by project owner: - **State**: Verified - **Priority**: Critical — Security vulnerability that could allow unauthorized access, path traversal, or arbitrary code execution. Security bugs are always Critical priority. - **Milestone**: v3.5.0 (M6: Autonomy Hardening) — Security hardening and sandbox enforcement are core to this milestone - **Story Points**: 3 (M) — Bug fix with clear reproduction path and suggested fix - **MoSCoW**: Must Have — Security vulnerabilities must be fixed before any release - **Type**: Bug --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
Author
Owner

[CLAIM] Issue claimed by implementation-worker

Claim Details:

  • Agent: implementation-worker
  • Session ID: impl-7476
  • Claim ID: 1775963851
  • Timestamp: 2026-04-12T03:17:31Z

Work is now in progress. Please refrain from starting parallel implementation on this issue.


Automated by CleverAgents Bot
Supervisor: Implementation | Agent: implementation-worker

[CLAIM] Issue claimed by implementation-worker **Claim Details:** - Agent: implementation-worker - Session ID: impl-7476 - Claim ID: 1775963851 - Timestamp: 2026-04-12T03:17:31Z Work is now in progress. Please refrain from starting parallel implementation on this issue. --- **Automated by CleverAgents Bot** Supervisor: Implementation | Agent: implementation-worker
Author
Owner

PR #7785 created on branch . Monitoring CI and feedback until merge.


Automated by CleverAgents Bot
Supervisor: Implementation | Agent: implementation-worker

PR #7785 created on branch . Monitoring CI and feedback until merge. --- **Automated by CleverAgents Bot** Supervisor: Implementation | Agent: implementation-worker
Author
Owner

Correction: PR #7785 created on branch fix/issue-7476-plugins-loader-security. Monitoring CI and feedback until merge.


Automated by CleverAgents Bot
Supervisor: Implementation | Agent: implementation-worker

Correction: PR #7785 created on branch fix/issue-7476-plugins-loader-security. Monitoring CI and feedback until merge. --- **Automated by CleverAgents Bot** Supervisor: Implementation | Agent: implementation-worker
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.

Depends on
Reference
cleveragents/cleveragents-core#7476
No description provided.