Skip to content

Unable to Update + Static Code Review Warning From A0Β #264

@wgnrai

Description

@wgnrai

Error

Plugin Installer

Installation failed: Cmd('git') failed due to: exit code(128) cmdline: git pull -v -- origin main stderr: 'fatal: Need to specify how to reconcile divergent branches.'


πŸ›‘οΈ Security Scan Report: Commands

1. Summary

The Commands plugin is well-structured with clean, readable code that matches its declared purpose. Two warnings warrant attention: runpy.run_path executes arbitrary user-created Python scripts without sandboxing, and those scripts receive AgentContext data including chat history. Caution.

2. Plugin Info

  • Name: commands
  • Purpose: YAML-configured slash commands with text templates or Python hooks
  • Version: 0.5.0

3. Results

Check Status Details
Structure & Purpose Match 🟒 Pass All files (API handlers, JS stores, HTML modals, skill templates, tests) directly support slash command CRUD and execution
Static Code Review 🟑 Warning runpy.run_path executes arbitrary Python from user-created script commands without sandboxing
Agent Manipulation Detection 🟒 Pass No prompt injection, hidden instructions, base64 payloads, zero-width characters, or social engineering text found
Remote Communication 🟒 Pass No external network calls; all communication is local via /plugins/commands/... API endpoints
Secrets & Sensitive Data Access 🟑 Warning Script commands receive full AgentContext payload including chat history and agent reference
Obfuscation & Hidden Code 🟒 Pass All code is readable, well-documented, with no minification, encoding, or dynamic import tricks

4. Details

Static Code Review β€” 🟑 Warning

File: helpers/commands.py β†’ lines 968–1003

async def _run_script_command(
    *,
    command: dict[str, Any],
    invocation: dict[str, Any],
    project_name: str,
    context_id: str,
) -> dict[str, Any]:
    script_path = _to_abs_path(command.get("content_path", ""))
    if not script_path:
        raise ValueError("Script command is missing script_path")
    if not os.path.exists(script_path):
        raise ValueError("Script file not found for this command")

    module_globals = runpy.run_path(script_path)
    hook = module_globals.get("run")
    if not callable(hook):
        raise ValueError('Script command must expose a callable "run(payload)" function')

Risk: runpy.run_path loads and executes an arbitrary .py file in the same Python process as the Agent Zero framework. Any user who can create or modify a script-type command can run arbitrary Python code with full framework access. This is an intentional design choice for the plugin's "script hook" feature, but there is no sandboxing, permission check, or code review gate. A malicious script command could import os, subprocess, or any other module and execute system-level operations. The risk is scoped to users who already have the ability to create commands within the Agent Zero UI.


Secrets & Sensitive Data Access β€” 🟑 Warning

File: helpers/commands.py β†’ lines 986–998

    context = _get_context(context_id)
    history = _extract_chat_history(context) if command.get("include_history") else []
    payload = {
        "command": _public_command_payload(command),
        "invocation": invocation,
        "arguments": invocation.get("arguments", {}),
        "context": {
            "context_id": context_id,
            "project_name": project_name,
            "agent": getattr(context, "agent0", None) if context else None,
            "chat_history": history,
        },
    }

Risk: When include_history is set to true on a script command, the full chat history from the active AgentContext is passed to the user-created Python script's run(payload) function. The payload also includes a reference to the agent0 object. A malicious script command could exfiltrate chat history (which may contain sensitive user data, API keys, or credentials shared during conversation) or interact with the agent object in unintended ways. This is an intentional feature β€” the plugin documents that script commands can request history β€” but users should be aware that any script-type command they install has access to this data.


File: helpers/commands.py β†’ lines 1027–1043

def _extract_chat_history(context: AgentContext | None) -> list[Any]:
    if not context:
        return []

    for attribute in ("chat_history", "history", "messages"):
        value = getattr(context, attribute, None)
        if isinstance(value, list):
            return value

    getter = getattr(context, "get_data", None)
    if callable(getter):
        for key in ("chat_history", "messages", "history"):
            value = getter(key)
            if isinstance(value, list):
                return value

    return []

Risk: This function iterates multiple attribute names and data keys to extract chat history from the AgentContext. It falls back from direct attribute access to get_data() calls, maximizing the chance of retrieving conversation data. While justified by the plugin's stated purpose of providing chat context to script commands, it broadly accesses internal framework state that could contain sensitive conversation content.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions