← 返回
安全技术

你的 Agent 有一扇侧门:MCP 策略不能只查工具清单

✍️ zhirenhun 📅 2026/11/4 👁 43 阅读 ⏱ 9 分钟
你的 Agent 有一扇侧门:MCP 策略不能只查工具清单

在MCP Dev Summit Toronto上,埃森哲的Michael Forrester讲了一个故事:一名员工想让自己的Agent发邮件。公司没给这个Agent配邮件工具,于是它自己写了个PowerShell脚本,借用该员工本人的访问权限,通过Outlook把邮件发了出去。

整个过程没出任何乱子。Michael明确表示,这不算安全违规:Agent用的是已获批准的机器上本来就有的能力。从Agent的MCP服务器上移除一个工具,并不能移除对应的操作,只是关上了一扇门,而Agent非常擅长找到别的门。

我把这些别的路径称为“侧门”。只要你的Agent能以已登录用户的身份运行shell或操控浏览器,它就有侧门,而你的MCP策略看不到这些侧门。

赶在Agent之前找到侧门

从你关心的操作出发,而不是从工具清单出发。先挑一个:发送邮件。然后列出Agent能达成这一操作的所有途径:

对每条途径,记下邮件服务看到的是谁的身份。这个身份决定了服务会放行什么。MCP途径可能携带一个限定范围的app身份;shell和浏览器途径携带的是用户身份,附带该用户被允许做的一切。

让邮件服务自己说“不”

像agentgateway这样的网关,适合用来控制Agent能看到和调用哪些MCP工具。但它拦不住根本不经过它的流量,而侧门恰恰不经过它。

所以,要把决策放在所有途径最终都会到达的地方:服务本身。NVIDIA的Chris Alexiuk在多伦多也表达了同样的观点,谈到他们的MCP-as-a-service层时,他说访问检查应设在服务边界上,编码助手不会自动获得研究Agent所拥有的权限。

对 Microsoft 365 上的邮件来说,这意味着要给 Agent 一个独立身份,只授予写草稿的权限,别的什么都不给。微软的权限参考文档把 Mail.ReadWrite 描述为允许应用创建、读取、更新和删除邮件,并明确说明它不包含发送权限。通过 sendMail 发送需要 Mail.Send,所以不要授予这个权限。由人来审阅草稿并亲自发送。

这里有个陷阱,就是多伦多那件事暴露的问题。如果 Agent 还能访问用户自己已登录的 Outlook 或浏览器,那么只给草稿权限的身份就形同虚设。解决办法在于 Agent 的运行环境:给它的 shell 和浏览器分配独立的沙箱账户,不装邮件客户端,也不保留任何已保存的会话。

试着走一遍流程

用测试租户或测试账户,千万别用真实邮箱。给 Agent 配好你计划上线的全部工具和运行时,然后让它未经批准直接发一封邮件。你要的结果是每条路径都失败。

正门应该在网关处就被拦下。然后用 Agent 的身份检查 Graph 这条路径:

# Signed in as the agent's test identity, consented to Mail.ReadWrite only
Connect-MgGraph -Scopes "Mail.ReadWrite"

$draft = New-MgUserMessage -UserId "agent-test@contoso.com" -BodyParameter @{
  subject      = "Side door test"
  body         = @{ contentType = "Text"; content = "If this arrives, the boundary failed." }
  toRecipients = @(@{ emailAddress = @{ address = "you@contoso.com" } })
}

# The draft should exist. This send should be denied.
Send-MgUserMessage -UserId "agent-test@contoso.com" -MessageId $draft.Id

然后像多伦多那位 Agent 一样,从 Agent 自己的 shell 里试试侧门:

$outlook = New-Object -ComObject Outlook.Application
$mail = $outlook.CreateItem(0)
$mail.To = "you@contoso.com"
$mail.Subject = "Side door test"
$mail.Send()

在正确配置的沙箱运行时里,这段代码还没开始跑就会失败,因为根本没有 Outlook 可供连接。如果它居然发送成功了,那你就找到了自己的侧门。

还有一点:Agent 发送失败并不能说明问题。它可能只是写了个糟糕的脚本。请用 Agent 的身份亲自运行上面的调用,这样才能确认是服务端拒绝了请求,而不只是模型出了问题。

查邮箱,别信 Agent

Agent 会毫不犹豫地告诉你它发了邮件。但只有邮件服务才知道真相。每次测试后,检查测试邮箱的“已发送邮件”和租户的消息跟踪,并把网关日志放在旁边对照。网关展示的是前门,邮箱展示的才是一切。

工具列表从来就不是边界。真正的边界是邮件服务针对 Agent 所持身份拒绝执行的那些操作——而要知道边界在哪里,唯一的办法就是试着走过去。

——

广告 广告
🧑‍💻

zhirenhun

一个热爱技术的程序员,喜欢分享前沿AI知识和开发经验。

ai mcp security automation