CVE-2026-47391 - PraisonAI A2A eval tool RCE
PraisonAI versions before 4.6.40 shipped a first-party A2A server example
that combined three unsafe defaults: no configured A2A auth token, a public
0.0.0.0 bind, and a calculate(expression) helper implemented with Python
eval(). An unauthenticated client that can reach /a2a can submit a
JSON-RPC message/send request that is passed to the server-side agent. In
the vulnerable example and equivalent deployments, the model can invoke the
registered calculate tool and execute Python in the server process.
This is not a claim that every A2A server is RCE. The risky pattern is public or LAN-reachable unauthenticated A2A combined with tools that execute code, spawn processes, mutate files, fetch privileged network resources, or expose agent task state.
Affected versions
- Vulnerable package:
PraisonAI <=4.6.39 - Fixed package:
PraisonAI 4.6.40+ - Affected coordinate:
PraisonAIon PyPI - Affected surface: copied or deployed PraisonAI A2A examples, local A2A
wrappers, agent demos, MCP/A2A bridges, and agent servers that expose
unauthenticated
/a2atraffic to untrusted clients - Affected code pattern: an A2A route with no auth token or equivalent
access control can reach an LLM-backed agent that has an unsafe local tool
such as
eval,exec,subprocess, shell execution, file writes, or network-capable callbacks.
Indicator-of-exposure
- The repository depends on, vendors, forks, or deploys
PraisonAI <=4.6.39. - A copied PraisonAI A2A example, tutorial, notebook, Docker image, demo app,
or internal agent service binds to
0.0.0.0or a non-loopback interface. A2A(...),auth_token=None, missingauth_token,/a2a,message/send, or task APIs are reachable without authentication.- Registered tools include
eval,exec,compile,subprocess,os.system,shell=True, file-write helpers, browser automation, local crawl, or administrative API clients. - Tests verify happy-path A2A messages but do not assert unauthenticated denial, loopback-only defaults, or dangerous-tool blocking.
Quick checks:
rg -n "PraisonAI|praisonai|A2A\\(|/a2a|message/send|auth_token|0\\.0\\.0\\.0|eval\\(|exec\\(|subprocess|os\\.system|shell=True|write_file|tasks/(list|get|cancel)" .
python -m pip show PraisonAI praisonai
python -m pip freeze | rg -i '^(PraisonAI|praisonai)=='
Windows:
rg -n "PraisonAI|praisonai|A2A\\(|/a2a|message/send|auth_token|0\\.0\\.0\\.0|eval\\(|exec\\(|subprocess|os\\.system|shell=True|write_file|tasks/(list|get|cancel)" .
python -m pip show PraisonAI praisonai
python -m pip freeze | rg -i '^(PraisonAI|praisonai)=='
Do not reproduce this against production A2A services, live model-provider
keys, customer prompts, or public listening sockets. Prefer local unit tests
with fake models and local TestClient fixtures.
Remediation strategy
- Upgrade every controlled PraisonAI package, lockfile, image, deployment,
SBOM, and generated dependency report to
4.6.40+. - Remove
eval()and other code-capable helpers from copied examples, notebooks, demos, and production A2A services. If arithmetic is required, use a strict parser or an allow-listed operation table. - Require authentication for
/a2aand task APIs before a request can reachagent.chat()or registered tools. - Bind examples and local demos to
127.0.0.1by default. Add a fail-closed startup guard for0.0.0.0without authentication. - Treat tool capability as part of authorization. Tools that can execute code, write files, call local networks, manage agents, or read secrets require an explicit approval boundary and negative tests.
- Review exposed A2A task histories and agent logs for prompts, task data, tool output, provider keys, and credentials if an affected service was reachable by untrusted users.
When to use it
Use this recipe when a repository deploys PraisonAI A2A servers, copied
examples, notebooks, demos, MCP/A2A bridges, or wrappers that expose /a2a,
task APIs, LLM-backed tools, or public preview endpoints. It is most important
when A2A traffic can reach code, file, network, browser, or admin tools.
Use it to upgrade PraisonAI, require A2A authentication, bind examples safely, and remove dangerous demo tools. Do not use it to run exploit payloads against production or public listening sockets.
Inputs
- Python manifests, lockfiles, constraints, Dockerfiles, Compose files, Helm charts, Kubernetes manifests, notebooks, examples, A2A wrappers, MCP/A2A bridges, deployment docs, SBOMs, generated reports, and forks.
- A2A surfaces:
A2A(,/a2a,message/send, task list/get/cancel APIs, auth token config, bind host, uvicorn startup, public demos, and preview environments. - Registered tool inventory:
eval,exec,compile, subprocess, shell, file-write helpers, local crawl, browser automation, network clients, admin clients, MCP tool calls, and task-state access. - Sensitive runtime context: A2A tokens, provider keys, prompts, task history, tool output, customer data, local files, environment variables, and agent configuration.
- Validation evidence: A2A auth tests, public-bind fail-closed tests, dangerous-tool scans, example/notebook scans, deployment rendering, image builds, SBOM refresh, and non-secret smoke tests.
The prompt
You are remediating CVE-2026-47391 / GHSA-vg22-4gmj-prxw, the PraisonAI A2A
example chain where unauthenticated JSON-RPC traffic can reach an LLM-driven
`eval()` tool. Produce exactly one output:
- A reviewer-ready PR/change request that upgrades PraisonAI, removes unsafe
A2A example tools, requires A2A authentication, adds local regression tests,
refreshes generated artifacts, and documents operator review actions, or
- TRIAGE.md if this repository does not control an affected PraisonAI runtime,
copied example, wrapper, image, deployment, or dependency.
## Rules
- Scope only CVE-2026-47391 / GHSA-vg22-4gmj-prxw and directly related A2A
authentication, public bind, dangerous-tool, and task-state boundaries.
- Treat A2A bearer tokens, cookies, model-provider keys, prompts, task history,
tool outputs, local files, environment variables, customer data, and agent
configuration as sensitive.
- Do not run real exploit payloads against production, bind a repro server to
a public interface, print live API keys, or use customer prompts.
- Do not fix the finding by deleting authentication, disabling audit logs,
weakening tool approval, or removing tests.
- Do not auto-merge.
## Steps
1. Inventory every PraisonAI reference controlled by this repository:
requirements, pyproject files, lockfiles, constraints, Dockerfiles, Compose
files, Helm charts, Kubernetes manifests, notebooks, examples, A2A wrappers,
MCP/A2A bridges, deployment docs, SBOMs, generated dependency reports, and
local forks.
2. Determine every resolved PraisonAI version. A target is vulnerable if it
resolves to `4.6.39` or earlier.
3. Search for A2A entry points and copied examples: `A2A(`, `/a2a`,
`message/send`, `auth_token`, `tasks/list`, `tasks/get`, `tasks/cancel`,
`uvicorn.run`, and `host="0.0.0.0"`.
4. Search registered tools and callbacks for code or state mutation:
`eval`, `exec`, `compile`, `subprocess`, `os.system`, `shell=True`,
file-write helpers, local crawl, browser automation, network clients,
admin clients, and MCP tool execution.
5. If the repository only calls an externally owned PraisonAI or A2A service,
stop with `TRIAGE.md` listing checked files, the external owner, and the
required fixed version and A2A auth contract.
6. Upgrade all controlled PraisonAI pins to `4.6.40+`. Regenerate lockfiles,
constraints, image metadata, SBOMs, dependency reports, and generated docs.
7. Remove unsafe demo tools from copied examples and production services:
- replace `eval()` arithmetic with a strict parser or fixed operation map;
- remove shell/process/file-write tools from unauthenticated examples;
- classify code, file, network, and admin tools as dangerous capabilities.
8. Enforce A2A authentication:
- require a runtime-provided token or stronger auth mechanism before
`/a2a` reaches `agent.chat()`;
- protect task list, get, and cancel APIs;
- reject public bind without auth unless a documented local-only test flag
is used.
9. Add safe local regression tests:
- unauthenticated `/a2a` returns 401 or equivalent denial;
- public bind without auth fails closed;
- copied examples contain no `eval`, `exec`, shell, or file-write tools;
- dangerous tools require explicit authorization or approval;
- task APIs do not expose prompts or structured data anonymously;
- logs and test output omit tokens, provider keys, prompts, and tenant data.
10. Add a PR body section named `CVE-2026-47391 operator actions` that states:
- PraisonAI versions before and after;
- every A2A endpoint, example, notebook, or wrapper reviewed;
- whether `/a2a` or task APIs were reachable without auth;
- whether any registered tool could execute code, write files, call local
networks, or mutate agent state;
- whether exposed task history, prompts, tool outputs, or provider keys
require log review or credential rotation;
- which validation commands passed.
11. Run relevant validation: dependency install, lockfile checks, A2A route
tests, dangerous-tool tests, example/notebook scans, lint/typecheck,
deployment rendering, container build, SBOM refresh, dependency/security
scans, and local non-secret smoke checks available in this repository.
12. Use PR title:
`fix(sec): remediate CVE-2026-47391 in PraisonAI A2A`
## Stop conditions
- No affected PraisonAI runtime, copied A2A example, package pin, image, or
deployment is controlled by this repository.
- A fixed PraisonAI version cannot be consumed without a broader agent-runtime
migration.
- Product policy intentionally allows unauthenticated public A2A with
code-capable tools; document the required security-owner decision in
`TRIAGE.md`.
- Verification would require production A2A probes, live model-provider keys,
public exploit payloads, customer prompts, or credential disclosure.
- Validation fails for unrelated pre-existing reasons; document those failures
instead of broadening scope.
Verification - what the reviewer looks for
- No controlled lockfile, image, SBOM, or deployment resolves PraisonAI below
4.6.40. - A2A endpoints and task APIs require authentication before reaching the agent or task state.
- Examples and copied service code do not combine public bind, no auth, and code-capable tools.
- Tests prove unauthenticated
/a2aand task APIs fail closed without printing tokens, provider keys, prompts, or tenant data. - Operator notes cover log review and credential rotation if an affected A2A surface was exposed.
Watch for
- Upgrading the package while notebooks, copied examples, Docker images, or generated dependency reports still use vulnerable PraisonAI code.
- Fixing only the
eval()helper while leaving unauthenticated public A2A and task-state APIs exposed. - Binding to
0.0.0.0in examples, dev containers, preview environments, or internal demos without a fail-closed auth guard. - Treating tool names as safe instead of classifying capabilities such as code execution, file writes, network access, and admin mutations.
- Running real LLM canaries with provider keys in CI logs.
Output contract
Return one of:
- A reviewer-ready PR/change request that upgrades every controlled PraisonAI
runtime to
4.6.40+, removes unsafe A2A demo tools, requires authentication before agent/tool/task access, fails closed on public bind without auth, adds local regression tests, refreshes artifacts, and documents operator review. TRIAGE.mdwhen no affected runtime, copied A2A example, wrapper, image, deployment, package pin, or dependency is controlled by the repository.
The output must list versions, A2A endpoints reviewed, auth posture, bind posture, dangerous tools removed or gated, task APIs protected, validation commands, and logs/secrets needing review. It must not use live provider keys, customer prompts, production A2A probes, public exploit payloads, or weakened tool approval.
Related recipes
- CVE-2026-47397 - PraisonAI arbitrary file write
- a separate PraisonAI tool-boundary issue where web context can drive unsafe file writes.
References
- GitHub Advisory: https://github.com/advisories/GHSA-vg22-4gmj-prxw
- Vendor advisory: https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-vg22-4gmj-prxw
- NVD CVE: https://nvd.nist.gov/vuln/detail/CVE-2026-47391
- PraisonAI project: https://github.com/MervinPraison/PraisonAI