Grades are a hygiene check, not a security guarantee.

MCP, MCP server

Ai Agents Orchestrator

Ai Agents Orchestrator, an MCP server listed in the PlugVet directory.

Compatibility: Not stated.

Grade C

One Medium finding. Read the findings before installing.

Graded by PlugVetRubric v2

Not a guarantee. A hygiene check of the source at the commit shown, not a security audit.

Rescanned at commit fd1f2a75aca8, unchanged since the check below.

INSTALL_REMOTE_SCRIPT

Why this grade

  • INSTALL_REMOTE_SCRIPT Medium

    Fetches a script from the network and runs it (a pipe to a shell, or an install hook with a URL).

    scripts/setup-env.sh, line 12 echo " curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash"

Any High, or two or more Medium findings, give D. One Medium gives C. Low findings or a security Note give B. Each code names a finding behind the letter.

If you think this grade is wrong, email [email protected] with the entry link and your evidence. We aim to acknowledge within two working days and decide within seven. If we confirm an error, we aim to correct it within 24 hours of confirming it. These are aims, not guarantees.

Grades are a hygiene check of the source at the commit shown, on the date checked, not a security audit or a guarantee. The free directory grades are automated. Before release, a PlugVet engineer reviews every paid report and any grade we hold back, including all F grades, against the source code and the evidence we quote.

What was checked

Plain notes from the hygiene checks.

  • Permissions

    Note

    requests shell access. The manifest names this permission.

    PERMISSION_SHELL_DECLARED

    AI-Collaboration-Skills/ai_collaboration/git_state.py, line 50

    completed = subprocess.run(

    agentic_team/shell.py, line 284

    handler = self.commands.get(command)

    agentic_team/shell.py, line 430

    os.system("clear" if os.name != "nt" else "cls")

    Show more

    agentic_team/adapters/base.py, line 244

    process = subprocess.Popen( # pylint: disable=consider-using-with

    agentic_team/adapters/cli_communicator.py, line 93

    process = subprocess.Popen( # pylint: disable=consider-using-with

    agentic_team/adapters/cli_communicator.py, line 132

    process = subprocess.Popen( # pylint: disable=consider-using-with

    agentic_team/adapters/cli_communicator.py, line 180

    process = subprocess.Popen( # pylint: disable=consider-using-with

    agentic_team/adapters/cli_communicator.py, line 285

    process = subprocess.Popen( # pylint: disable=consider-using-with

  • Install and update

    Serious

    install fetches a script from the network. The docs document an installer that pipes a download into a shell.

    INSTALL_REMOTE_SCRIPT INSTALL_DOCUMENTED_INSTALLER

    DEPLOYMENT.md, line 439

    curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash

    DEPLOYMENT.md, line 451

    curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

    scripts/setup-env.sh, line 12

    echo " curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash"

    Show more

    docs/offline-mode.md, line 144

    curl -fsSL https://ollama.com/install.sh | sh

    requirements.txt, line 2

    click>=8.1.0

  • Network

    Concern

    can reach a host that is not written as a fixed address.

    NETWORK_NO_FIXED_HOST

    agentic_team/offline.py, line 44

    response = httpx.head(

    agentic_team/adapters/llama_cpp_adapter.py, line 124

    resp = httpx.get(url, timeout=2, follow_redirects=False)

    agentic_team/adapters/llama_cpp_adapter.py, line 138

    resp = httpx.get(f"{self.endpoint}/v1/models", timeout=10)

    Show more

    agentic_team/adapters/ollama_adapter.py, line 130

    response = httpx.get(f"{self.endpoint}/api/tags", timeout=2)

    agentic_team/adapters/ollama_adapter.py, line 142

    resp = httpx.get(f"{self.endpoint}/api/tags", timeout=10)

    agentic_team/adapters/ollama_adapter.py, line 154

    response = httpx.post(

    agentic_team/adapters/ollama_adapter.py, line 168

    response = httpx.delete( # pylint: disable=unexpected-keyword-arg

    agentic_team/ui/app.py, line 237

    response = httpx.get(f"{endpoint}/api/tags", timeout=3)

    deployment/scripts/blue-green-switch.sh, line 82

    if kubectl exec -n "$NAMESPACE" "$pod" -- curl -sf "http://localhost:${APP_PORT}/health" > /dev/null; then

    deployment/scripts/blue-green-switch.sh, line 90

    if kubectl exec -n "$NAMESPACE" "$pod" -- curl -sf "http://localhost:${APP_PORT}/ready" > /dev/null; then

    mcp_server/tools/devops_tools.py, line 84

    CMD curl -f http://localhost:{port}/health || exit 1

    .circleci/config.yml, line 429

    python -c "import urllib.request; r=urllib.request.urlopen('http://localhost:$PORT/health'); print(r.read().decode())" \

    .claude/agents/devops-infrastructure.md, line 69

    CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:5001/health')" || exit 1

    .claude/skills/devops/docker-containerization.md, line 51

    CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"

    docker-compose.yml, line 52

    test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:5001/health', timeout=5)"]

    docker-compose.yml, line 90

    test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:5002/health', timeout=5)"]

  • Secrets

    Concern

    reads a credential or environment file.

    SECRETS_ENV_READ SECRETS_PATH_DOTENV

    agentic_team/context/ops/project_scanner.py, line 140

    ".env",

    agentic_team/context/ops/project_scanner.py, line 270

    ".env.example",

    agentic_team/ui/app.py, line 29

    app.config["SECRET_KEY"] = os.environ.get("FLASK_SECRET_KEY_AGENTIC", os.urandom(32).hex())

    Show more

    graphify/analyzers/config_analyzer.py, line 4

    Dockerfiles, and .env files.

    graphify/analyzers/config_analyzer.py, line 48

    if lower.startswith(".env"):

    graphify/analyzers/config_analyzer.py, line 277

    # .env files

    graphify/core/config.py, line 39

    ".env",

    graphify/core/schema.py, line 146

    ".env": Language.SHELL,

    graphify/core/schema.py, line 147

    ".env.example": Language.SHELL,

    orchestrator/ui/app.py, line 78

    app.config["SECRET_KEY"] = os.environ.get("FLASK_SECRET_KEY", os.urandom(32).hex())

  • Agent instructions

    Pass

    No instruction to ignore earlier instructions or to hide a step.

  • Obfuscation

    Note

    a file was over the read cap and was not fully read. the file cap was reached before every file was read.

    OBFUSCATION_FILE_OVER_READ_CAP OBFUSCATION_FILE_CAP_REACHED

    coverage.xml, line 1

    <?xml version="1.0" ?>

    orchestrator/ui/frontend/src/style.css, line 1

    @tailwind base;

  • Licence

    Pass

    A licence file is present (LICENSE).

  • Maintainer activity

    Pass

    The latest commit is within the last 365 days.

Note

Hygiene check of commit fd1f2a75aca8. requests shell access. The manifest names this permission. install fetches a script from the network. The docs document an installer that pipes a download into a shell. can reach a host that is not written as a fixed address. reads a credential or environment file. a file was over the read cap and was not fully read. the file cap was reached before every file was read.

Date and source

Date checked:

View source

github.com

Commit graded: fd1f2a75aca87907cd5e510a65516d120dfd7a3c

This link goes to the original host. PlugVet does not host or check what you download from there, and installing it is your own decision and risk.

Read how this letter is chosen