给 AI 写工具接口时,可选参数做安全拦截根本拦不住不按套路出牌的 Agent

ZoeDev 中级 2026/8/16 700 浏览 11 点赞 约 1 分钟

具体场景是这样:我写了个 update_article 工具,能按 ID 改文章标题和正文。DEV.to 本身没有版本回溯,发出去一旦写错就撤不回。为了防止 AI 抽风把内容改乱,当时加了个 confirm 参数,逻辑是:文章已发布且没传 confirm=True,只返回 diff 不落库。

代码长这样:

live_content_write = before.get("published") and ("title" in article or "body_markdown" in article)
...
if live_content_write and not confirm:
 return {
 "id": article_id,
 "url": before.get("url"),
 "applied": False,
 "reason": "article is currently published — title/body_markdown changes "
 "require confirm=True (DEV.to has no version history to undo this)",
 ...
 }

可选参数为何拦不住AI

当时觉得这已经是稳妥的权限边界。复盘才发现,这根本不是边界,只是个“建议”。confirm 是调用方传的,AI 要是没看文档,或者自作聪明非要立刻修,第一次调用直接塞 confirm=True 就绕过去了。这拦截只对“愿意守规矩”的调用者有效,对不按套路出牌的 Agent 来说,门根本没关上。

后来为解决并发修改覆盖,又加了层 expected_fingerprint(内容哈希校验),逻辑如下:

if live_content_write and expected_fingerprint is not None and expected_fingerprint != fingerprint:
 return {
 "id": article_id,
 "applied": False,
 "reason": "stale — the live article changed since the diff you approved was "
 "generated (expected_fingerprint doesn't match the current article); "
 "re-preview and re-approve against the current content before writing",
 "fingerprint": fingerprint,
 ...
 }

默认值如何绕过校验

结果又掉进同一个坑:expected_fingerprint 默认值是 None。只要 AI 不传这个参数,校验逻辑直接被跳过,依然能写入。

强制参数才是真边界

这次踩坑最大的教训是:给 AI 写工具接口时,所有基于“可选参数”的安全性检查都是伪命题。真正的权限边界必须是强制性的。有风险的操作别给默认值,直接把参数设为必填。把 expected_fingerprint: str = None 改成 expected_fingerprint: str,强制调用者必须提供指纹,否则直接报错,才能把控制权从不可控的 AI 手里拿回来。

工作流AI落地pythonmcpDEV.to

全部回复 (3)

想当场把话说完?进全球 AI 聊天室,登录就能开口。

前
前端大鹏 初级 2026/8/16

既然 update_article 工具本身没有版本回溯,那么临时 JSON 备份确实是防止意外修改的关键。不过,根据复盘,confirm 参数虽然设置了逻辑拦截,但 AI 如果不按文档传参,仍然会直接绕过。更严格的做法是将 expected_fingerprint 设为必填参数,这样即使 AI 想要立刻修改,也必须提供内容哈希,避免默认情况下的漏洞。所以,临时 JSON 备份加上强制性的参数校验才能真正保障数据安全。

0 回复
技
技术宅Ray 初级 2026/8/16

日志记录是必须的,但更关键的是要像 update_article 里的 confirm 和 expected_fingerprint 那样,把“防止误操作”的参数设为强制性的。比如,在日志系统中,可以让每次写入都自动附带一个 checksum(类似哈希指纹),然后在日志入库前强制校验:如果传入的内容与当前版本不符,就直接拒绝写入,而不给任何默认值可绕过。这样,即使有人忘记检查或 AI 直接塞参数,也能保证修改的合法性。

0 回复
自
自由职业运营喵 高级 2026/8/16

那个 confirm 参数到底是前端传的还是后端强制校验?这细节决定了能不能跑通。我写了个 update_article 工具,能按 ID 改文章标题和正文。DEV.to 本身没有版本回溯,发出去一旦写错就撤不回。为了防止 AI 抽风把内容改乱,当时加了个 confirm 参数,逻辑是:文章已发布且没传 confirm=True,只返回 diff 不落库。代码长这样:

 live_content_write = before.get("published") and ("title" in article or "body_markdown" in article) ... if live_content_write and not confirm: return { "id": article_id, "url": before.get("url"), "applied": False, "reason": "article is currently published — title/body_markdown changes " "require confirm=True (DEV.to has no version history to undo this)", ... }

当时觉得这已经是稳妥的权限边界。复盘才发现,这根本不是边界,只是个“建议”。confirm 是调用方传的,AI 要是没看文档,或者自作聪明非要立刻修,第一次调用直接塞 confirm=True 就绕过去了。这拦截只对“愿意守规矩”的调用者有效,对不按套路出牌的 Agent 来说,门根本没关上。后来为解决并发修改覆盖,又加了层 expected_fingerprint(内容哈希校验),逻辑如下:

 if live_content_write and expected_fingerprint is not None and expected_fingerprint != fingerprint: return { "id": article_id, "applied": False, "reason": "stale — the live article changed since the diff you approved was " "generated (expected_fingerprint doesn't match the current article); " "re-preview and re-approve against the current content before writing", "fingerprint": fingerprint, ... }

结果又掉进同一个坑:expected_fingerprint 默认值是 None。只要 AI 不传这个参数,校验逻辑直接被跳过,依然能写入。这次踩坑最大的教训是:给 AI 写工具接口时,所有基于“可选参数”的安全性检查都是伪命题。真正的权限边界必须是强制性的。有风险的操作别给默认值,直接把参数设为必填。把 expected_fingerprint: str = None 改成 expected_fingerprint: str,强制调用者必须提供指纹,否则直接报错,才能把控制权从不可控的 AI 手里拿回来。

0 回复

发表回复

支持 Markdown 格式