Summary
The _safe_eval_expression() function in the computed fields feature uses an AST validator that only blocks attributes starting with underscore. Python generator and frame object attributes (gi_frame, f_back, f_builtins) do NOT start with underscore, enabling a complete sandbox escape to achieve arbitrary code execution.
The attack requires no authentication (JWT disabled by default) and is triggered via POST /crawl with a crafted extraction schema.
Attack Vector
An attacker sends a POST /crawl request with a JsonCssExtractionStrategy schema containing a malicious computed field expression that:
- Creates a generator to access
gi_frame
- Walks the frame chain via
f_back
- Reaches
f_builtins containing the real __import__
- Imports
os and executes arbitrary commands
Impact
Unauthenticated remote code execution inside the Docker container. An attacker can execute arbitrary system commands, read/write files, and exfiltrate secrets.
Fix Details
- Removed
eval() from computed field expression path entirely -- expressions now log a warning and return default value
- Deleted
_safe_eval_expression() function and _SAFE_EVAL_BUILTINS (dead security-sensitive code)
function key with Python callables still works for SDK users
- Replaced
eval() in /config/dump with JSON-based input validated by Pydantic
- Fixed hook_manager sandbox: stripped
__builtins__, __loader__, __spec__ from injected modules; removed getattr, setattr, type, __build_class__ from allowed builtins
Workarounds
- Upgrade to the patched version (recommended)
- Enable JWT authentication via
CRAWL4AI_API_TOKEN environment variable
- Restrict network access to the Docker API
Credits
- Song Binglin (q1uf3ng) - reported the AST sandbox escape
- by111 (August829) - reported the hook sandbox
__builtins__ escape and hardcoded JWT secret bypass
- jannahopp - PR #1855 proposing eval removal
- ntohidi - PR #1886 proposing allowlist approach
References
Summary
The
_safe_eval_expression()function in the computed fields feature uses an AST validator that only blocks attributes starting with underscore. Python generator and frame object attributes (gi_frame,f_back,f_builtins) do NOT start with underscore, enabling a complete sandbox escape to achieve arbitrary code execution.The attack requires no authentication (JWT disabled by default) and is triggered via
POST /crawlwith a crafted extraction schema.Attack Vector
An attacker sends a
POST /crawlrequest with aJsonCssExtractionStrategyschema containing a malicious computed field expression that:gi_framef_backf_builtinscontaining the real__import__osand executes arbitrary commandsImpact
Unauthenticated remote code execution inside the Docker container. An attacker can execute arbitrary system commands, read/write files, and exfiltrate secrets.
Fix Details
eval()from computed field expression path entirely -- expressions now log a warning and return default value_safe_eval_expression()function and_SAFE_EVAL_BUILTINS(dead security-sensitive code)functionkey with Python callables still works for SDK userseval()in/config/dumpwith JSON-based input validated by Pydantic__builtins__,__loader__,__spec__from injected modules; removedgetattr,setattr,type,__build_class__from allowed builtinsWorkarounds
CRAWL4AI_API_TOKENenvironment variableCredits
__builtins__escape and hardcoded JWT secret bypassReferences