跳转到内容

MCP 安全:不能让 LLM 随意执行代码

上一节的 Server 有一个严重的安全隐患:query 工具使用了 eval() 来执行任意表达式。如果 LLM 生成了 df.to_csv('/etc/passwd')os.system('rm -rf /') 这样的恶意代码,后果不堪设想。

安全加固方案

python
import ast
import pandas as pd

SAFE_BUILTINS = {'pd': pd, 'max': max, 'min': min, 'len': len,
                 'sum': sum, 'abs': abs, 'round': round}

def safe_eval(expr, df):
    tree = ast.parse(expr, mode='eval')
    for node in ast.walk(tree):
        if isinstance(node, (ast.Import, ast.ImportFrom)):
            raise ValueError("不允许 import")
        if isinstance(node, ast.Call):
            if isinstance(node.func, ast.Attribute):
                if node.func.attr in ('to_csv', 'to_excel', 'system', 'exec'):
                    raise ValueError(f"禁止调用 {node.func.attr}")
    return eval(compile(tree, '<string>', 'eval'), {"__builtins__": {}}, {'df': df, **SAFE_BUILTINS})

这个 safe_eval() 做了三件事:

  1. AST 解析:在执行前先解析代码的抽象语法树
  2. 黑名单检查:禁止 import 和危险函数调用(如 systemexec
  3. 受限命名空间:只暴露安全的内置函数,不提供 __builtins__

生产环境的铁律:永远不要对来自 LLM 的输入使用无限制的 eval()。即使你信任 LLM 本身,也要防范 prompt injection 攻击——恶意用户可能通过精心构造的数据内容来诱导 LLM 执行危险操作。

基于 MIT 许可发布