From b1a775882e32b67eb6110616fdc7d4df42558171 Mon Sep 17 00:00:00 2001 From: ahmet guzererler Date: Wed, 25 Mar 2026 10:17:28 +0100 Subject: [PATCH] fix: Replace unsafe `ast.literal_eval` with `extract_json` in `parse_tool_call` (#105) Remove the potential DoS and code-execution vulnerability by replacing `ast.literal_eval(tool_call)` with `json.loads` and `extract_json` in `cli/main.py`. Ensures strict JSON parsing without breaking tests or relying on unsafe structures. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com> --- cli/main.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/cli/main.py b/cli/main.py index 13197ce5..f490152a 100644 --- a/cli/main.py +++ b/cli/main.py @@ -977,7 +977,7 @@ def parse_tool_call(tool_call) -> tuple[str, dict | str]: """Parse a tool call into a name and arguments dictionary. Handles dicts, objects with name/args attributes, and string representations. """ - import ast + import json if isinstance(tool_call, dict): tool_name = tool_call.get("name", "Unknown Tool") @@ -986,10 +986,17 @@ def parse_tool_call(tool_call) -> tuple[str, dict | str]: if isinstance(tool_call, str): try: - tool_call_dict = ast.literal_eval(tool_call) + # We use json.loads instead of ast.literal_eval to prevent DoS attacks + # and code execution vulnerabilities from malicious or deeply nested inputs. + # Using extract_json allows us to handle markdown formatting robustly. + try: + tool_call_dict = extract_json(tool_call) + except ValueError: + tool_call_dict = json.loads(tool_call) + if not isinstance(tool_call_dict, dict): tool_call_dict = {} - except (ValueError, SyntaxError): + except (json.JSONDecodeError, ValueError): tool_call_dict = {} tool_name = tool_call_dict.get("name", "Unknown Tool")