Skip to content

fix(security): prevent Python import blacklist bypass in Code node#2701

Open
manusjs wants to merge 1 commit into
coze-dev:mainfrom
manusjs:fix/python-code-node-import-bypass
Open

fix(security): prevent Python import blacklist bypass in Code node#2701
manusjs wants to merge 1 commit into
coze-dev:mainfrom
manusjs:fix/python-code-node-import-bypass

Conversation

@manusjs

@manusjs manusjs commented Jun 4, 2026

Copy link
Copy Markdown

Summary

Fixes GHSA-pfc8-gmgc-5pwq — Code Execution via Python Import Blacklist Bypass in Code Node.

The validatePythonImports() function only parses import and from X import statements via regex. This is trivially bypassed using:

  • __import__('os')
  • eval() / exec() with encoded payloads
  • open() builtin (no import needed)
  • globals()['__builtins__'].__import__('os')
  • ().__class__.__bases__[0].__subclasses__() gadget chains

Changes

1. Runtime builtins restriction (primary fix)

File: backend/infra/coderunner/impl/direct/runner.go

The Python execution template now injects a security preamble that:

  • Patches __import__ with a runtime hook enforcing the module blacklist (catches all dynamic import techniques)
  • Replaces open(), eval(), exec(), compile(), breakpoint() with functions that raise PermissionError
  • Deletes the reference to the original import function

2. Expanded module blacklist

File: backend/domain/workflow/internal/nodes/code/code.go

Added to pythonBuiltinBlacklist: os, subprocess, sys, shutil, ctypes, importlib, signal, ssl, ftplib, smtplib, http, xmlrpc, socketserver, select, selectors

These were previously missing — import os passed validation without any error.

3. Static bypass pattern detection (defense-in-depth)

Added regex detection for common bypass patterns (__import__(, importlib.import_module(, globals()[, __subclasses__(), __builtins__[) to reject code early with a clear error message.

Recommendation

This patch hardens the direct runner significantly, but the proper long-term fix is to require the sandbox runner (CodeRunnerType_Sandbox) for all deployments. Python's introspection capabilities make static analysis fundamentally insufficient as a sole security boundary. The sandbox runner already provides OS-level isolation.

Testing

Verified that all bypass techniques from the advisory (__import__, open(), eval+base64, globals()) are now blocked both at the static validation layer and at runtime.

The validatePythonImports() function only parses 'import' and 'from X import'
statements via regex, which is trivially bypassed using __import__(), eval(),
exec(), open(), globals()['__builtins__'], and other dynamic code loading
techniques.

This patch adds three layers of defense:

1. Runtime builtins restriction (primary fix): The Python execution template
   now injects a security preamble that patches __import__ with a hook
   enforcing the module blacklist at runtime, and replaces dangerous builtins
   (open, eval, exec, compile) with functions that raise PermissionError.

2. Expanded module blacklist: Added os, subprocess, sys, shutil, ctypes,
   importlib, signal, ssl, ftplib, smtplib, http, xmlrpc, socketserver,
   select, and selectors to pythonBuiltinBlacklist. These were previously
   missing, allowing 'import os' to pass validation without error.

3. Static bypass pattern detection (defense-in-depth): Added regex checks
   for __import__(), importlib.import_module(), globals()[], __subclasses__(),
   and __builtins__[] patterns to reject code early before execution.

Note: The proper long-term remediation is to require the sandbox runner
(CodeRunnerType_Sandbox) for all deployments, as Python's introspection
capabilities make static analysis fundamentally insufficient as a sole
security boundary.

Fixes: GHSA-pfc8-gmgc-5pwq
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants