fix: replace eval() with safe type lookup in UserInputField to prevent code injection - #207
Conversation
…t code injection Signed-off-by: FailSafe Researcher <joshua@getfailsafe.com>
1b4bb80 to
bbc3b3b
Compare
|
Hi maintainers 👋 This vulnerability was found by FailSafe — a top agentic cybersecurity company specializing in automated deep security analysis of AI/ML and agentic codebases. We're reporting these initial findings as a social good contribution to help secure the open-source AI ecosystem. If you'd like us to perform a deeper, more comprehensive security scan of your project, we'd love to hear from you — reach out at joshua@getfailsafe.com. Thanks for maintaining this project! 🙏 |
|
This security fix PR has been open for 3+ weeks without review. We understand maintainers are busy. If you prefer, we can also reach out via security@ email. Happy to rebase or adjust the patch. Please let us know how you'd like to proceed. |
|
Friendly follow-up on this security PR. It has been open for a while without human reviewer feedback. Happy to rebase, trim the patch, or adjust the approach if that helps. Thanks for taking a look. |
Problem
UserInputField.from_dict()inagents/tools/base.pycallseval(data["field_type"])without sanitization. The same pattern exists inagents/models/base.py:1162. Sincefield_typeoriginates from LLM tool call arguments (which can be influenced by user prompts via prompt injection), this enables arbitrary Python code execution within the agent process.An attacker who can influence the LLM's tool call output (via prompt injection) can set
field_typeto__import__('os').system('id')to execute arbitrary commands.Severity: High (CVSS 8.8) — LLM tool call context → host Python process execution
Fix
Replace
eval()with a static allowlist lookup (_SAFE_TYPESdict) that maps type name strings to their Python type objects. Unknown type names default tostr. This preserves the intended functionality (converting type name strings to type objects) while eliminating the code injection vector.Test Plan
UserInputField.from_dict({"name": "x", "field_type": "int", ...})→ field_type isintUserInputField.from_dict({"name": "x", "field_type": "__import__('os').system('id')", ...})→ field_type isstr(no code execution)UserInputField.from_dict({"name": "x", "field_type": "unknown", ...})→ field_type isstr(safe default)Security Note
This is a high-severity code injection vulnerability exploitable via prompt injection. The fix replaces
eval()with a safe allowlist lookup.