Havenlon|AI 时代的执行控制(六):Execution Gap:审批和真实执行之间的那道缝
摘要在传统安全模型里人们习惯把审批通过看成一个动作被允许执行的终点。但在真实系统里审批通过并不是终点而只是一个中间状态。因为审批发生在某一个时刻执行发生在另一个时刻。审批看到的是一个请求执行面对的是一个运行时环境审批判断的是当时是否允许执行要处理的是现在是否仍然应该发生。这两者之间天然存在一道缝这道缝就是 Execution Gap。它不是简单的流程漏洞也不是某个产品功能没做好而是所有高风险系统都会面对的结构性问题检查发生在前执行发生在后判断发生在请求侧结果发生在现实侧。在 AI Agent、Tool Calling、自动化脚本、Web3 交易、企业系统集成越来越普遍之后这道缝会被进一步放大。因为从意图到审批从审批到工具调用从工具调用到真实执行中间每一步都可能发生变化。所以AI 时代的安全问题不只是有没有审批而是审批之后执行之前那道缝里发生了什么一、审批通过只是某一刻的判断审批的本质是在某一个时间点对某一个请求做出判断。以一笔付款申请为例审批系统看到的是申请人是谁、金额多少、收款对象是谁、业务理由是什么、是否在预算内、审批人是否同意然后在这个时刻给出结论可以通过。这个判断并不一定错问题在于它只代表那个时刻。审批通过的那一刻参数可能是正确的权限可能是合规的收款对象可能是可信的上下文可能是完整的。但执行并不一定在同一刻发生——它可能发生在几秒后、几分钟后、几个小时后甚至几天后。在这段时间里系统状态可能变化参数可能变化环境可能变化权限可能变化攻击者也可能介入。所以审批通过只能说明在审批发生的那个时刻请求看起来被允许。它不能天然证明在执行发生的那个时刻动作仍然安全。这就是 Execution Gap 的起点。二、检查和执行之间永远存在时间差在安全工程里有一个经典问题叫 TOCTOUTime of Check to Time of Use也就是检查时到使用时之间的差异。简单说就是系统检查某个条件时它是安全的但真正使用这个条件时它可能已经变了。在传统软件安全里这经常出现在文件权限、资源访问、并发状态、锁竞争等场景中——系统检查一个文件可以被访问但在真正打开之前文件被替换了系统检查一个对象属于用户 A但在执行操作前对象关系发生了变化。这个问题放到 AI 和业务执行系统里就变得更大。审批就是 Check执行就是 Use审批检查的是某个请求是否允许执行使用的是这个判断结果去触发现实动作。但问题是审批时安全不代表执行时安全。只要检查和执行不是同一个不可分割的原子动作中间就有缝。而高风险系统里攻击者最喜欢的就是这道缝。尤其在自动化系统里这个时间差可能非常短甚至只有毫秒级。但短不代表不存在——毫秒对人来说来不及反应对一段自动化程序来说却足够完成一次参数替换。值得注意的是TOCTOU 这个概念在传统软件安全里主要被当作一种并发编程的技术缺陷来处理解决办法往往是加锁、用原子操作、或者在使用时刻重新校验。但当它上升到审批与执行这个业务层面时情况变得更棘手审批和执行之间隔着的不再是几行代码的执行间隙而是可能横跨多个系统、多个团队、多个时间尺度的完整业务流程。你没法简单地对一整套跨系统的业务流程加锁也没法让审批和执行变成一个不可分割的原子动作。正因如此业务层面的 Execution Gap比代码层面的 TOCTOU 更难通过传统手段消除它需要的不是一把锁而是一层能在执行时刻重新做判断的独立控制。三、Execution Gap 不只是时间差也是状态差很多人以为 Execution Gap 只是审批到执行之间隔了一段时间但它不只是时间差更重要的是状态差——审批看到的是一个状态执行面对的是另一个状态。审批时订单还未退款执行时订单可能已经被退款过一次审批时权限申请对象是普通成员执行时这个账号可能已经被提升过权限审批时收款地址是 A执行时地址可能被替换成 B审批时脚本版本是安全的执行时脚本可能已经被更新审批时 Agent 计划看起来合理执行时工具调用链可能已经被污染。这就是状态差。系统不能只保存一个通过的状态然后在后续执行时无条件相信它因为真正执行时世界已经不是审批时的世界。所以执行控制必须在执行前重新看一次最终状态——这不是重复审批而是验证现在即将发生的动作是否仍然符合当初被允许的边界四、Execution Gap 也是语义差除了时间差和状态差还有一层更隐蔽的问题语义差。审批系统审批的是一个业务语义比如给供应商付款处理客户退款转移资产到安全地址——这些都是人能理解的业务语言。但执行系统真正执行的是参数和动作调用哪个 API、传哪个 amount、传哪个 address、传哪个 permission_scope、导出哪个 table、广播哪笔 transaction。审批的是语义执行的是参数这里面也有一道缝因为业务语义到执行参数之间需要转换而转换过程可能出错。正如系列前面讨论过的AI Agent 和 Tool Calling 让这个问题更明显用户表达的是自然语言 IntentAI 生成的是工具调用参数审批系统看的可能是任务摘要执行端拿到的却是具体的 API 请求。如果中间没有独立的绑定关系就可能出现审批时看起来是小范围操作、执行参数却变成了大范围操作审批时看起来是普通权限、执行参数却包含了管理员权限审批时看起来是指定客户数据、执行参数却导出了更多数据。这不是审批人一定失误而是语义到执行之间存在转换损耗。AI 时代这个损耗会更危险因为模型越强越会自动补全语义而一旦补全结果进入执行端就可能产生真实后果。五、Execution Gap 也是信任域差审批和执行往往不在同一个信任域里。审批系统可能在 SaaS执行系统可能在本地业务系统可能在云端Agent 可能在另一个运行环境工具可能来自第三方服务最终动作可能发生在链上、银行、生产服务器或物理设备上。这些系统之间并不天然可信。如果执行端只是相信审批系统给出的一个已通过状态那么攻击者不一定需要攻击执行端他只需要让执行端相信审批已经通过。这就非常危险——他可以伪造审批状态篡改 SaaS 返回重放旧的通过结果替换中间请求污染 Agent 上下文或者利用缓存、队列、异步任务之间的状态差。审批系统可以提供信号但不能成为执行端唯一的信任根。执行端必须有自己的边界判断。这也呼应了系列此前的一个核心观点当一切都处在同一个信任域、或者执行端无条件信任外部状态时攻击者要攻破的就不再是执行本身而是想办法让执行端相信某个状态已经通过。六、AI Agent 会把 Execution Gap 压缩也会放大AI Agent 有一个很特别的影响它会同时压缩和放大 Execution Gap。说它压缩是因为 AI 能让从意图到执行的路径变得非常短。过去需要人一步一步操作现在 Agent 可以在几秒内完成理解、计划、调用和执行。从用户体验看Gap 变短了但从安全角度看Gap 反而更难观察——因为中间转换太快人来不及看审批来不及细看工具调用可能连续发生多个动作可能在一个任务里被串起来。说它放大是因为 Agent 增加了更多转换层自然语言转任务任务转计划计划转工具工具转参数参数转执行执行结果再转下一步计划。每一层都可能偏离。所以 AI Agent 不是简单地减少 Execution Gap它只是把原来可见的人工间隔变成了更快、更自动、更隐蔽的系统间隔。过去人慢Gap 里还可能被人发现异常现在 AI 快Gap 里的异常可能直接变成执行结果。七、Tool Calling 让 Execution Gap 进入每一次调用在 Tool Calling 系统里Execution Gap 不只存在于整个任务开始和结束之间它存在于每一次工具调用之前。比如一个 Agent 要处理退款它会依次查询订单、判断退款条件、生成退款金额、调用退款接口、更新客户状态、发送通知、记录结果。每一步都有自己的小型 Execution Gap查询结果是否可靠退款条件是否仍然成立金额是否被正确计算退款接口参数是否被污染客户状态是否已经改变如果系统只在任务开始时批准一次然后允许 Agent 后续连续调用工具就等于把一整条执行链都交给了初始的审批状态。这不够因为执行链越长Gap 越多。每一次高风险工具调用都应该被视为一个新的执行点尤其当工具调用会改变真实状态时不能只靠前面的判断。执行控制必须靠近真实动作而不是只停在任务入口。八、异步系统会让这道缝更大现代业务系统大量使用异步架构消息队列、任务调度、Webhook、事件驱动、批处理任务、延迟执行、后台 Worker、跨系统同步。这些机制提高了系统扩展性但也会扩大 Execution Gap因为一个请求被审批通过之后不一定立刻执行——它可能进入队列等待 Worker 消费等待外部系统响应等待定时任务触发等待链上确认等待第三方 API 回调。这中间任何状态都可能变化。审批通过时风险可能可控Worker 执行时条件可能已经不同。如果系统没有在执行前重新验证就会出现旧审批触发新执行、旧状态驱动新动作、旧参数在新环境下生效、旧权限在变更后仍被使用、旧 Intent 在新的上下文里被继续执行。这就是异步系统里的 Execution Gap。AI Agent 加上异步工具调用之后这个问题会更复杂因为 Agent 可能把一个长任务拆成多个异步步骤而每一步都可能同时跨越时间、状态和信任域三重差异。九、Web3 场景里的 Execution Gap 更不可逆在 Web3 场景中Execution Gap 特别危险因为很多执行结果不可逆。审批时看到的可能是转给某个地址、调用某个合约、授权某个额度但真正签名或广播时可能已经发生变化to 地址被替换chain_id 错误合约方法被伪装calldata 被污染授权额度过大交易路径被替换前端显示和真实签名内容不一致。如果系统只在前端或 SaaS 层显示已确认然后底层签名设备或执行端无条件相信这个状态就会产生巨大风险因为链上执行没有传统意义上的撤销按钮一旦签名广播很多结果无法恢复。所以 Web3 更需要执行前的最后一层独立验证——不是只看人是否点击了确认不是只看 SaaS 是否审批通过不是只看前端显示是否正确而是要看最终要签的东西是否仍然符合被允许的 Intent 和策略边界这就是 Execution Gap 在数字资产场景里的核心问题。十、企业系统里的 Execution Gap 更常见很多人以为 Execution Gap 只存在于极端安全场景其实企业系统里到处都是。在权限系统里审批通过的是给某人开项目权限执行时可能开成了更高权限或者开到了错误项目或者因为群组继承导致实际权限范围扩大。在数据导出里审批通过的是导出某客户数据执行时查询条件可能扩大或者导出了关联数据或者生成了可公开访问的链接。在运维脚本里工单批准的是重启某个服务执行时脚本可能影响多个服务或者运行环境不是预期环境。在财务流程里审批通过的是支付某笔款执行时收款账户、金额、币种、付款批次可能发生变化甚至批量任务里包含了未审批的对象。这些问题本质都是一样的审批看到的和最终执行的不完全是同一个东西。所以 Execution Gap 不是一个理论概念它是企业系统里长期存在、但经常被流程语言掩盖的问题。之所以说被流程语言掩盖是因为在事故复盘时这些问题很容易被归因到别的地方去。权限开大了会被记成配置失误数据导出多了会被记成查询条件写错脚本影响了别的服务会被记成运维操作不规范。这些归因本身没有错但它们都停留在具体操作的层面掩盖了背后那个共同的结构性成因——审批环节所批准的那个东西和执行环节实际发生的那个东西从来没有被系统强制校验过是否一致。只要这个结构性成因不被正视类似的事故就会换着不同的表象反复出现而每一次都被当成孤立的、可以靠下次更仔细来避免的个案。十一、为什么多加审批不能消除 Execution Gap面对 Execution Gap最常见的反应是那就多加几层审批。但这只能部分缓解不能根本解决因为多加审批仍然是在 Check 层增加判断它不能自动保证 Use 层的执行参数不变。如果审批后的执行链路仍然可以被污染多几层审批也只是让一个错误请求获得更多合法外衣。比如五个人审批了 A最后执行了 B——这时问题不在于审批人数不够而在于 A 和 B 之间没有被强绑定。审批流程越长甚至可能越容易让人产生错觉这么多人都看过了应该没问题。但真正执行时如果参数被替换、环境变化、状态过期、工具链污染多人审批也可能挡不住。Execution Gap 的解法不是无限叠加审批而是让执行端在最后一刻独立验证即将执行的 B是否就是被审批允许的 A如果不是就应该拒绝。这不是审批问题而是执行一致性问题。十二、真正要解决的是绑定Execution Gap 的核心解法不是相信审批而是绑定审批与执行。也就是说审批的对象是什么、最终执行的对象是什么两者必须能被验证为同一个边界内的动作。这需要几个关键的绑定关系。第一Intent 与执行参数绑定用户的原始意图不能被执行参数任意扩大。第二Approval 与最终动作绑定审批通过的范围必须和最终执行动作一致。第三策略与执行条件绑定限额、时间、对象、频次、权限、风险等级必须在执行前仍然有效。第四执行与证据绑定执行发生后必须能证明它基于什么条件发生。第五控制与执行端绑定执行端不能只接收外部的通过状态而要能独立验证。这才是真正的执行控制——不是多一个流程节点不是多一个按钮不是多一条日志而是让被允许的东西和真正发生的东西之间有一种可验证的关系。这五个绑定关系里最容易被忽略、也最关键的是第一个Intent 与执行参数的绑定。因为其他几个绑定多少还能在现有系统里找到雏形——审批系统记录了批准范围策略引擎记录了限额规则日志系统记录了执行过程。唯独用户最初到底想要什么和系统最终到底执行了什么参数之间的对应关系在绝大多数系统里是断裂的用户的原始意图往往在被转化成一个个中间状态、任务摘要、工具参数的过程中逐层丢失了。等到执行端拿到最终参数时它已经完全无从知晓这个参数到底是不是忠实地反映了用户最初的那句话。绑定要做的就是把这条从意图到参数的链路重新接起来让最终执行的每一个关键字段都能追溯回它对应的那个被允许的意图。十三、执行控制层必须靠近执行点如果控制层离执行太远它就很容易退化成另一个审批系统。真正的执行控制必须靠近执行点因为风险是在执行前最后一刻确定的付款前、转账前、签名前、广播前、导出前、删库前、开权限前、执行脚本前、设备动作前、策略变更前。越靠近执行点越能看到最终参数越能判断状态是否变化越能阻断被污染的动作越能留下真实的执行证据。这就是为什么执行控制不能只停在 SaaS、前端、审批流或业务系统里——这些地方可以参与治理但最终边界必须站在真实动作发生之前。否则系统控制的只是请求是否好看而不是执行是否安全。十四、Execution Gap 解释了为什么需要独立边界Execution Gap 最重要的启发是审批和执行不是同一个事件。既然不是同一个事件就不能用一个审批状态替代最终的执行判断既然中间存在时间差、状态差、语义差、信任域差就必须有一层系统在执行前重新验证。这层系统不能完全依赖发起方不能完全依赖业务系统不能完全依赖 Agent不能完全依赖 SaaS 状态不能完全依赖前端显示不能完全依赖日志承诺。它必须有独立判断能力至少要能看见最终执行参数验证策略是否仍然有效确认对象没有被替换确认范围没有被扩大确认高风险动作没有绕过控制在必要时拒绝执行并在执行后留下独立证据。这就是执行控制层存在的理由——它不是为了替代审批而是为了守住审批无法覆盖的那道缝。结语Execution Gap 是 AI 时代必须被看见的一道缝。它存在于审批和执行之间存在于 Intent 和工具调用之间存在于业务语义和执行参数之间存在于 SaaS 状态和本地执行之间存在于模型计划和现实动作之间存在于检查发生的时刻和执行发生的时刻之间。过去人一直站在这道缝里——人会看、会停、会核对、会怀疑、会在最后一步重新确认。但 AI Agent、Tool Calling、自动化脚本和异步系统正在让这道缝变得更快、更隐蔽、更难观察。所以AI 时代的安全不能只问有没有审批更要问审批之后执行之前谁守住那道缝如果没有这一层审批通过只是一个状态执行发生才是现实而真正的风险往往就藏在状态到现实之间。这也是本系列接下来要继续展开的地方为什么静态的审批规则天生挡不住动态发生的执行风险为什么当执行系统和审批系统处在同一个信任域里软件往往管不住软件为什么真正的执行控制必须独立于业务系统之外单独存在不可绕过、防篡改、可验证为什么是执行控制层不可退让的底线一个只能说不的系统为什么反而是最安全的设计以及把执行权真正关进笼子会成为 AI 时代新的安全常识。审批看见的是请求执行改变的是世界。真正的安全边界必须站在两者之间。