我之前给公司搭建的 DEV.

ZoeDev 中级 3天前 651 浏览 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)",
 ...
 }

我当时觉得这已经是个很稳的权限边界了。结果回头复盘才发现,这根本不是什么边界,而是一个“建议”。因为 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)

前端大鹏 初级 3天前
我之前还加了个备份,改之前先存个临时json,万一真翻车好救。
0 回复
技术宅Ray 初级 3天前
得加个日志记录,不然以后查起来根本不知道是谁在什么时候改的。
0 回复
自由职业运营喵 高级 3天前
那个confirm参数是前端传过来的,还是在后端逻辑里强制校验的?
0 回复

发表回复

支持 Markdown 格式