Skip to content

Commit 3d17dd9

Browse files
committed
fix: Address Copilot review comments
- Replace unsafe eval() with safe AST-based evaluation in examples - Use ast.literal_eval() in documentation example - Fix misleading comment about coroutine parameter (all functions are async) Security improvements: - Example now uses AST parsing with whitelisted operators - Documentation uses ast.literal_eval() for safe evaluation - Both approaches prevent arbitrary code execution
1 parent dbbf383 commit 3d17dd9

File tree

4 files changed

+37
-5
lines changed

4 files changed

+37
-5
lines changed

Any

Whitespace-only changes.

agent-memory-client/agent_memory_client/integrations/langchain.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ def get_memory_tools(
204204
func=config["func"],
205205
name=config["name"],
206206
description=config["description"],
207-
coroutine=config["func"], # Same function works for both sync and async
207+
coroutine=config["func"], # All our functions are async
208208
)
209209
langchain_tools.append(langchain_tool)
210210

docs/langchain-integration.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,14 @@ memory_tools = get_memory_tools(
222222
# Define custom tools
223223
@tool
224224
async def calculate(expression: str) -> str:
225-
"""Evaluate a mathematical expression."""
226-
return str(eval(expression))
225+
"""Evaluate a simple mathematical expression safely."""
226+
import ast
227+
# Use ast.literal_eval for safe evaluation of simple expressions
228+
try:
229+
result = ast.literal_eval(expression)
230+
return str(result)
231+
except (ValueError, SyntaxError):
232+
return "Error: Invalid expression"
227233

228234
@tool
229235
async def get_weather(city: str) -> str:

examples/langchain_integration_example.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,35 @@ async def custom_agent_example():
186186

187187
@tool
188188
async def calculate(expression: str) -> str:
189-
"""Evaluate a mathematical expression."""
189+
"""Evaluate a simple mathematical expression (numbers and basic operators only)."""
190+
import ast
191+
import operator
192+
193+
# Safe evaluation using AST - only allows basic math operations
194+
allowed_operators = {
195+
ast.Add: operator.add,
196+
ast.Sub: operator.sub,
197+
ast.Mult: operator.mul,
198+
ast.Div: operator.truediv,
199+
ast.Pow: operator.pow,
200+
}
201+
190202
try:
191-
result = eval(expression) # Note: Use safely in production!
203+
204+
def eval_node(node: ast.AST) -> float:
205+
if isinstance(node, ast.Constant):
206+
return float(node.value)
207+
if isinstance(node, ast.BinOp):
208+
op = allowed_operators.get(type(node.op))
209+
if op is None:
210+
raise ValueError(f"Unsupported operator: {type(node.op)}")
211+
return op(eval_node(node.left), eval_node(node.right))
212+
if isinstance(node, ast.UnaryOp) and isinstance(node.op, ast.USub):
213+
return -eval_node(node.operand)
214+
raise ValueError(f"Unsupported expression: {type(node)}")
215+
216+
tree = ast.parse(expression, mode="eval")
217+
result = eval_node(tree.body)
192218
return f"Result: {result}"
193219
except Exception as e:
194220
return f"Error: {str(e)}"

0 commit comments

Comments
 (0)