news 2026/9/19 20:35:31

信息流控制(IFC)标签流转实战指南:Agent Control Specification 的无状态标签流模型

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
信息流控制(IFC)标签流转实战指南:Agent Control Specification 的无状态标签流模型

信息流控制(IFC)标签流转实战指南:Agent Control Specification 的无状态标签流模型

【免费下载链接】agent-governance-toolkitAI Agent Governance Toolkit — Policy enforcement, zero-trust identity, execution sandboxing, and reliability engineering for autonomous AI agents. Covers 10/10 OWASP Agentic Top 10.项目地址: https://gitcode.com/GitHub_Trending/ag/agent-governance-toolkit

Agent Control Specification(ACS)将信息流控制(Information Flow Control, IFC)实现为一种无状态(stateless)标签流策略模型:核心运行时只在干预点评估策略,自身不存储标签、不传播污染(taint),也不内置任何 IFC 检查逻辑,全部溯源(provenance)跟踪责任由宿主(host)承担。本文以 policy-engine/docs/ifc-label-flow.md 为主体,结合 Rego 参考库、Cedar 镜像、manifest 示例与一致性测试用例,完整讲解源标签如何在快照中进入、工具清单如何声明放行级别(clearance)、策略如何执行 no write down 判定、以及result_labels如何在不破坏无状态性的前提下跨轮次传递标签流。读完你将能够:理解 ACS 的 IFC 快照契约与失败关闭(fail-closed)语义、为工具正确声明clearance/security_labels、用agent_control_specification.lib.ifc(或 AGT 库存agt.ifc)编写 no write down 策略、并通过verdict_propagating实现跨轮次标签传播。

设计核心:无状态判定 + 宿主持有溯源

ACS 的 IFC 模型刻意把"判定"与"溯源"分离:

  • 核心(core)负责判定:在约定的干预点(intervention point,如pre_tool_callinputoutput)评估配置好的策略,基于当次调用传入的快照数据返回 verdict。
  • 宿主(host)负责溯源:宿主在数据流经 prompt、模型调用、工具结果(tool results)、记忆(memory)以及输出准备(output preparation)等环节时,为数据附加标签;在每一个 sink 处,宿主调用 ACS 并把进入该 sink 的数据标签放在input.snapshot.ifc.source_labels中交给策略。

这一分工的直接收益是:运行时无需保存任何跨调用的状态,水平扩展、无状态部署、缓存友好,且策略结果完全由"当前快照 + 策略"决定,具备可复现性。从源码结构看,参考 Rego 库 policy/lib/ifc.rego 全部由纯函数构成(dominatesmax_sensitivityflow_allowedverdict等),没有任何副作用或内部状态,正是这种无状态模型的实现证据。

关于无状态运行时的更完整讨论,可参见 policy-engine/docs/stateless-runtime.md 与 policy-engine/docs/snapshot-contract.md。

快照契约:ifc.source_labels与失败关闭语义

默认快照字段为ifc.source_labels,其值必须是标签字符串数组。规范 SPECIFICATION.md 第 212 行附近明确约定:

The snapshot label convention isinput.snapshot.ifc.source_labels. The value MUST be an array of label strings. Policies MUST treat a missing field, a non array value, an empty array, or an unknown label as a denial unless a host specific policy proves a lower sensitivity by other means.

也就是说,以下任何情况都必须失败关闭(fail closed),即按拒绝处理:

情况处理
source_labels字段缺失拒绝
值不是数组拒绝
数组为空拒绝
包含未知标签(不在格中)拒绝
标签之间不可比较(incomparable)拒绝

AGT 快照路径与上游库的差异(重要坑点)

需要特别注意的是,快照中标签的具体路径随宿主 SDK 表面不同而不同。上游agent_control_specification.lib.ifc库读取的是input.snapshot.ifc.*;而 AGT(Agent Governance Toolkit)宿主 SDK 按 AGT-SNAPSHOT-1.0.md §2.2 / §2.7 填充的是:

  • input干预点:input.snapshot.input.ifc.source_labels
  • output干预点:input.snapshot.response.ifc.result_labels

因此,如果 AGT 用户直接导入上游agent_control_specification.lib.ifc,该库会在 AGT 宿主上永远读不到标签、每次都失败关闭。这正是 AGT 提供库存替代库 policy/lib/agt_ifc.rego(包名agt.ifc)的原因——其文件头注释明确指出:AGT 用户必须导入data.agt.ifc而不是上游包

agt.ifc除了与上游函数表面完全对齐(dominatesmax_sensitivityflow_allowedallowdenyverdictverdict_propagating及其_with_lattice变体)之外,还额外提供三个便捷辅助函数:

  • source_labels:读取input.snapshot.input.ifc.source_labels,非数组时回退为[]
  • result_labels:读取input.snapshot.response.ifc.result_labels,非数组时回退为[]
  • allow_if_dominates(sink_clearance, labels):no write down 判定的 AGT 简写,内部委托给verdict

对应的测试 policy/lib/agt_ifc_test.rego 中test_source_labels_reads_agt_input_pathtest_does_not_read_upstream_ifc_path直接验证了这两条路径的差异:即使上游路径input.snapshot.ifc.source_labels下放了["secret"],AGT 辅助函数看到的依然是[]

工具清单元数据:clearancesecurity_labels

工具(tool)的放行级别是manifest 元数据,声明在工具目录(tools catalog)中。规范 SPECIFICATION.md 第 186 行说明,tools是按工具名索引的目录,每个条目除类型与 ID 外不限制其他成员;一个条目可以声明clearance标签、security_labels数组以及宿主自定义字段。第 214 行进一步明确:

  • clearance:单个标签,命名该 sink 能接收的最大敏感性(maximum sensitivity)
  • security_labels:描述 sink 属性或能力的标签数组(如externalcontrolledretrieval)。

运行时把这两个字段直接投影进策略输入input.tool,即input.tool.clearanceinput.tool.security_labels无需核心代码改动。这是典型的"清单驱动(manifest-driven)"设计:新增工具的 IFC 属性只需改清单,不触碰运行时。

以仓库自带的 IFC 示例 examples/ifc_agent/manifest.yaml 为例:

agent_control_specification_version: 0.4.0-alpha.1 metadata: name: "ifc-agent" policies: ifc_policy: type: rego bundle: ./policy data_paths: - ../../policy/lib/ifc.rego query: data.agent_control_specification.ifc_agent.verdict intervention_points: pre_tool_call: policy_target: "$.tool_call.args" policy_target_kind: tool_args tool_name_from: "$.tool_call.name" policy: id: ifc_policy query: data.agent_control_specification.ifc_agent.pre_tool_call_verdict tools: public_egress: type: Tool id: public_egress clearance: public security_labels: [external] trusted_archive: type: Tool id: trusted_archive clearance: confidential security_labels: [controlled]

注意data_paths特意只指向policy/lib/ifc.rego这一单个文件,而不是整个policy/lib/目录——因为该目录下的*_test.rego兄弟文件会被 OPA 的数据加载器一并加载(manifest 中的注释明确记录了这一点)。示例中public_egress工具仅允许接收public级数据(对外出口),trusted_archive工具允许接收至confidential级数据(受控归档)。

默认格与 Rego 参考库

库包agent_control_specification.lib.ifc提供默认的敏感性格(lattice)public < internal < confidential < secret,并在此基础上提供支配(dominance)、最大敏感性(maximum sensitivity)、允许判定与拒绝判定辅助函数。集成者可以传入自己的格数据对象(lattice data object)以支持额外标签与偏序(partial order)。

默认格在 policy/lib/ifc.rego 中定义为自反闭包形式(每个标签支配自身及其以下所有标签):

default_lattice := {"dominates": { "public": ["public"], "internal": ["public", "internal"], "confidential": ["public", "internal", "confidential"], "secret": ["public", "internal", "confidential", "secret"], }}

库提供的主要函数及其语义:

函数语义
dominates(clearance, label)/dominates_with_lattice(lattice, clearance, label)判断放行级别是否支配某标签(要求两个参数都是字符串,并在格中查找闭包)
max_sensitivity(labels)/_with_lattice计算一组标签的最大敏感性(集合中存在一个标签支配其余所有标签)
flow_allowed(clearance, labels)/_with_lattice组合判定:count(labels) > 0且 clearance 支配最大敏感性
allow(...)/deny(...)/verdict(...)/_with_lattice返回{"decision": "allow"}或拒绝判定对象
propagated_labels(labels)/_with_lattice返回[max_sensitivity(labels)](连接语义,见下文)
verdict_propagating(...)/_with_lattice允许时额外携带result_labels的判定(见下文)

dominates_with_lattice的实现通过object.get(lattice, "dominates", {})读取格对象,再在dominates[clearance]闭包列表中查找目标标签;max_sensitivity_with_latticeevery other in labels保证被选中的标签支配集合内全部其余标签。`AGT 库存库 policy/lib/agt_ifc.rego 的函数表面与上述完全一致,只是快照路径改为 AGT 路径。

violation函数统一生成拒绝判定:

violation(clearance, labels) := { "decision": "deny", "reason": "ifc_clearance_violation", "message": sprintf("IFC clearance violation for sink clearance %v and data labels %v.", [clearance, labels]), }

No Write Down:sink 处的判定规则

策略在 sink 处强制no write down(禁止向下写):只有当 sink 的clearance支配传入的每一个源标签的最大敏感性时,sink 才允许接收数据;否则策略返回拒绝判定,reasonifc_clearance_violation。规范 SPECIFICATION.md 第 218 行给出了 MUST 级要求:若标签不可比较,比较必须失败关闭;策略发出的拒绝判定应使用reason = ifc_clearance_violationdecision = deny

一个典型的 no write down 策略(基于agt.ifc的 AGT 写法):

package my_app.ifc import data.agt.ifc import rego.v1 default verdict := {"decision": "allow"} # 读取 AGT 快照上的源标签(input 干预点) source_labels := ifc.source_labels # sink 放行级别来自清单投影 sink_clearance := input.tool.clearance # no write down:clearance 必须支配所有源标签 verdict := ifc.verdict(sink_clearance, source_labels)

也可以直接用agt.ifc.allow_if_dominates(sink_clearance, labels)简写。测试 policy/lib/agt_ifc_test.rego 中:

  • test_clearance_dominates_data_allowsflow_allowed("secret", ["confidential"])为真,verdict("secret", ["confidential"]).decision == "allow"
  • test_data_exceeds_clearance_deniesdeny("internal", ["confidential"])返回decision == "deny"reason == "ifc_clearance_violation"
  • test_missing_and_empty_labels_deny_fail_closed:即使 clearance 是最高级secret,空标签数组依然拒绝;
  • test_incomparable_labels_deny_fail_closed:自定义格public < piipublic < pcipiipci不可比较,flow_allowed_with_lattice(lattice, "pii", ["pci"])为假。

result_labels:无状态运行时的跨轮次标签通道

这是本模型最巧妙的部分:核心不保存任何状态,但标签流依然可以跨轮次(across turns)延续

  • 策略 MAY 在其输出中包含result_labels——一个描述 sink 产生数据的标签字符串数组。
  • 核心把这个数组原样(verbatim)返回verdict.result_labels中,除此之外不做任何事:不存储、不传播污染、不自行做 IFC 检查。
  • 宿主负责把返回的标签与产生出来的数据(工具结果或模型输出)一起持久化,并在后续、其策略目标派生于该数据的评估中,把它们作为ifc.source_labels再次提供。

这样,标签流的延续完全由宿主的数据生命周期驱动,运行时始终保持无状态。verdict 的 wire schema spec/schema/wire/verdict.schema.json 中result_labels的注释即描述了这一契约:核心原样返回,宿主持久化并在后续评估中重新供给,核心不存储也不传播。

规范 SPECIFICATION.md 第 296 / 308 行附近还给出两个重要补充:

  1. 规范化失败关闭:当result_labels存在但不是字符串数组时,输出规范化失败,产生runtime_error:policy_output_invalid
  2. 宿主不得为未发生的行为传播标签:对于没有实际产生数据的判定(如deny,包括被审批缝(approval seam)否决的可升级deny),宿主不得传播result_labels——该成员只在 sink 数据真正产出时才有意义。因此库辅助函数在非 allow 判定上省略result_labels

库辅助:verdict_propagating的连接(join)语义

verdict_propagatingverdict_propagating_with_lattice返回一个 allow 判定,其result_labels是输入源标签的join(最大敏感性)

verdict_propagating(clearance, labels) := verdict if { not flow_allowed(clearance, labels) verdict := violation(clearance, labels) } else := {"decision": "allow", "result_labels": propagated_labels(labels)} if { flow_allowed(clearance, labels) }

这些辅助函数假设敏感性格是全序的,并把结果折叠成单个支配标签——对于public < internal < confidential < secret这类有序链,这是正确默认:多个来源的数据取最高级标签,不会丢失敏感性。测试test_verdict_propagating_returns_joined_label验证:verdict_propagating("secret", ["public", "confidential", "internal"])返回decision == "allow"result_labels == ["confidential"]

丰富格(compartment / category)下的注意事项

如果策略运行在具有独立 compartment 或类别(例如piipci)的更丰富格上,且没有任何单一输入标签支配其余标签,不要使用verdict_propagating辅助函数——它们会把结果折叠为单一标签,从而丢失溯源。此时策略应直接自行发出result_labels,要么返回完整的源标签集合,要么返回显式 join 后的标签,保证溯源不丢失。这是原文档明确给出的边界条件,也是编写自定义传播策略时必须遵守的规则。

完整可运行示例:Rust + Rego 的 ifc_agent

仓库提供了一个开箱即跑的 IFC 示例 examples/ifc_agent/README.md,采用 Rego 策略包、无 annotator,在pre_tool_call干预点通过比较snapshot.ifc.source_labels与投影的工具 clearance 执行 no write down 策略。

运行方式(opa必须在PATH上):

cargo run -p agent_control_specification --example ifc_agent --quiet

策略本体 examples/ifc_agent/policy/ifc_agent.rego:

package agent_control_specification.ifc_agent import data.agent_control_specification.lib.ifc import rego.v1 default verdict := {"decision": "allow"} default pre_tool_call_verdict := {"decision": "allow"} verdict := pre_tool_call_verdict if { input.intervention_point == "pre_tool_call" } source_labels := object.get(object.get(input.snapshot, "ifc", {}), "source_labels", []) sink_clearance := object.get(input.tool, "clearance", "") pre_tool_call_verdict := ifc.verdict_propagating(sink_clearance, source_labels) if { input.intervention_point == "pre_tool_call" }

驱动演示 examples/ifc_agent/demo.rs 展示了完整的"零配置构建 + 标签传播"闭环:

  1. AgentControl::from_path("manifest.yaml")零配置构建——manifest 声明了 Rego 策略包且无 annotator,from_path直接接线捆绑的 OPA 策略分发器;
  2. public数据发往public_egress:允许,且verdict.result_labels == ["public"](传播标签);
  3. 下一轮把传播标签作为source_labels送回,数据流向trusted_archive(clearanceconfidential支配public):再次允许,标签原样继续传播——演示了"宿主跨轮次回灌标签、运行时保持无状态";
  4. confidential数据发往public_egress:拒绝,reason == Some("ifc_clearance_violation")

预期判定与 manifest、策略、演示代码的对应位置,示例 README 的 "Where to look" 一节都做了标注,便于对照学习。

Cedar 镜像:预计算闭包 +containsAll

AGS 在 policy/cedar-lib/ifc.cedar 中提供了 IFC 标签流库的 Cedar 镜像。由于Cedar 无法在策略评估过程中迭代集合来计算格闭包,镜像采用"宿主预计算"策略:

  • 宿主把格闭包预先计算为资源实体(resource entity)属性clearance_dominated_labels——一个字符串集合,命名该 sink clearance 支配的每一个标签;
  • Cedar 策略用集合运算符.containsAll表达 IFC 规则:当资源 clearance 没有支配快照上的每一个源标签(或标签集合为空)时,forbid触发。

该文件实现了四个 forbid 规则:ifc_clearance_violation_input(input 干预点源标签不被支配)、ifc_clearance_violation_output(output 干预点结果标签不被支配)、以及针对空标签集合的ifc_clearance_violation_empty_input/_empty_output——后两者把"空标签失败关闭"用显式 forbid 落到了 Cedar 语义里。

选择建议(文件头注释明确说明):

  • 需要格灵活性(在评估时选择格)的作者,留在 Rego 库data.agt.ifc,它暴露了dominates_with_latticeverdict_with_lattice等按调用时传入格文档的函数;
  • 采用 Cedar 的作者,当格变化时需要重新加载实体(reload entities),因为闭包是预计算进实体属性的。

一致性测试与验证

IFC 行为由两层测试覆盖:

  1. Rego 单元测试policy/lib/agt_ifc_test.rego(上文已多次引用):覆盖支配允许、超限拒绝、不可比较失败关闭、空/缺失标签失败关闭、多标签取最大敏感性、传播连接、AGT 路径读取、上游路径不可见等全部关键语义;
  2. 一致性(conformance)用例tests/conformance/cases/spec-18-ifc.case-01.json 与 spec-18-ifc.case-02.json,对应规范第 18 节:
    • case-01:search工具 clearance 为internal,快照源标签["internal"],判定allow
    • case-02:同样的工具与清单,快照源标签改为["confidential"](超过 clearance),判定denyreason = ifc_clearance_violation

两个用例都声明 Rust / Python / Node SDK 为 required、.NET 为 optional,并在references中同时指向 policy/lib/ifc.rego 与本文主体文档 docs/ifc-label-flow.md,是理解规范意图最直接的对照样本。

信任边界:完整宿主插桩是前提

原文档最后一句给出了模型的信任边界:该模型依赖完整的宿主插桩。以下情形不在 ACS 的保证范围之内

  • 未插桩的数据路径(数据绕过了宿主附加标签的环节);
  • 宿主侧的标签丢失(宿主没有把标签正确附加或持久化);
  • 不调用 ACS 的 sink(数据在未经策略评估的出口流出)。

换句话说,ACS 的 IFC 保证是"判定时刻的正确性",而"每个数据点都被标记、每个出口都被评估"属于宿主责任。在设计系统时,应把pre_tool_callinputoutput等干预点全部接入 ACS,并在数据生命周期中严格执行"产生数据 → 持久化result_labels→ 后续作为source_labels回灌"的循环,否则标签流会在未插桩处静默断裂。相关宿主义务在 SPECIFICATION.md 第 17 节有完整定义,可结合 policy-engine/docs/security-model.md 与 policy-engine/docs/stateless-runtime.md 进一步了解整体安全模型。

【免费下载链接】agent-governance-toolkitAI Agent Governance Toolkit — Policy enforcement, zero-trust identity, execution sandboxing, and reliability engineering for autonomous AI agents. Covers 10/10 OWASP Agentic Top 10.项目地址: https://gitcode.com/GitHub_Trending/ag/agent-governance-toolkit

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 20:33:19

Agent生产落地五层架构与MCP/A2A实战避坑指南

1. 这张图谱不是“未来预测”&#xff0c;而是当下正在发生的产业切片你点开任何一篇讲Agent的文章&#xff0c;十有八九开头就是“Agent是AI的下一代范式”“2026年将全面爆发”。这话没错&#xff0c;但错在——它把正在剧烈演化的现实&#xff0c;包装成一张等待兑现的支票。…

作者头像 李华
网站建设 2026/9/19 20:31:21

AI论文写作工具千笔:提升科研效率的智能助手

1. 项目概述作为一名在学术圈摸爬滚打多年的研究者&#xff0c;我深知论文写作过程中的痛点。从文献检索到格式排版&#xff0c;每个环节都耗费大量时间。最近导师强力推荐的"千笔"AI论文工具&#xff0c;彻底改变了我的科研工作流。这款工具不仅整合了文献管理、写作…

作者头像 李华
网站建设 2026/9/19 20:31:00

MindSpore单卡LoRA微调大模型全流程实战

昇思MindSpore这个框架&#xff0c;真正上手做过大模型LoRA微调的人其实比想象中少。我最早是在一张24G显卡上拿7B模型做全参微调&#xff0c;显存直接爆掉&#xff0c;后来切到LoRA才把方案跑通&#xff0c;那段时间踩过的坑够写好几篇笔记。今天这篇就来盘一盘&#xff0c;用…

作者头像 李华