guardx · 安全围栏原语集
一句话:给 Agent 运行时用的安全原语——凭据脱敏、出站管控、Shell 裁决、
权限判定、提示注入卫生。每包一个机制面,零编排语义,可单独取用。
oagentkit 模块矩阵的 tier 0 安全层。与矩阵其余仓的关系:
textx/runtime 是零依赖底座,guardx 与它们同级;agent/toolgate 等编排层
在它们之上消费本仓原语。与 oekit(Go 微服务工具链)是两套独立矩阵,
本仓的 audit 子模块依赖 oekit 的 logx,不是其子品牌。
三个 module,两个零依赖
| module |
包 |
外部依赖 |
github.com/oagentkit/guardx |
fence injectband logredact egress permgate |
无 |
github.com/oagentkit/guardx/audit |
audit |
oekit/logx |
github.com/oagentkit/guardx/bashguard |
bashguard |
mvdan.cc/sh/v3 |
主模块零外部依赖:只想脱敏的下游 import "github.com/oagentkit/guardx/logredact"
不会把日志库和 shell 解析器拖进自己的模块图(Go 的模块图会把被依赖模块的
require 一并拉进来)。
两个子模块是嵌套 module(子目录自带 go.mod),但 import 路径没变——
下游代码一行不用改,只是 go.mod 里多一条 require。
包清单
| 包 |
行数 |
职责 |
bashguard |
~1014 |
Shell 命令规则 DSL 与处置裁决:Analyze(cmd, *Table) Decision。基于 mvdan.cc/sh 做真语法解析(非字符串匹配),对命令逐条匹配规则集得出放行/告警/拒绝裁决 |
permgate |
~500 |
能力门禁:Capability / Rule / Ruleset / Decision。判定链以 deny 优先于 approval,输出可审计的裁决结构 |
logredact |
~477 |
凭据脱敏:日志与异常面在落盘/外发前的凭据抹除 |
egress |
~475 |
出站 URL 守卫(SSRF):scheme 白名单 + 目标地址逐 IP 过策略(回环/RFC1918/链路本地/CGNAT/保留段) |
fence |
~284 |
提示注入卫生(数据侧):把不可信内容圈进显式数据区,并中和内容中伪造的围栏标记,防其越出数据区取指令待遇 |
audit |
~163 |
审计留痕:结构化审计事件 |
injectband |
~121 |
提示注入卫生(系统侧):给系统带外注入打来源标记,并转义 body 内伪造的同形标签,防身份伪造 |
「行数」口径 = 生产代码 + 测试代码总和。
提示注入的两个方向
fence 与 injectband 互补,不是替代关系——它们封的是相反两个方向:
不可信内容(工具返回 / diff / 抓取正文)
│
├─→ fence.Data() 圈进数据区,标记「这是数据,不得当指令」
│
系统带外注入(历史对话 / 目标续跑 / 工具护栏提示)
│
└─→ injectband.Wrap() 标记「这是系统说的」,并转义伪造同形标签
只做 fence 是不够的:系统提示与用户文本在模型眼里仍是同一等公民,攻击者不必
逃出数据区,只需在数据区里写一个像系统注入的标签即可抬升自己的权限。
injectband 补的正是这个身份伪造缺口。
已知的误用陷阱
egress 不解析 DNS。 checkHost 对域名直接返回放行(return nil // 域名:不解析)。
因此任何人直接拿 egress.Check(url) 挡住 LLM 可控 URL,会得到零 DNS-rebinding
防护——真正的 SSRF 防线在调用方的解析层(逐 IP 判定)。本包只提供逐 IP 策略判定
这个原语,不承担解析职责。需要解析后判定的场景(如编排内核的 netguard)应自行
解析后逐 IP 调用。
门禁
CI 是薄调用层:规则本体在 oagentkit/.github 的共享工作流,
各仓 ci.yml 只传 go-version。改门禁规则只改那一个仓,本仓不动。
go test ./... -cover # 本机验证(主模块)
gofmt -l . && go vet ./...
(cd audit && go test ./...) # 嵌套子模块各自验
(cd bashguard && go test ./...)
嵌套子模块由 CI 的共享工作流自动发现并测试(build + test -race),
也自动各跑一次 go mod tidy -diff 门禁。
macOS:本机 go build/test 一律带 CGO_ENABLED=0(新 SDK 27.0 与 CLT linker 不兼容)。
边界纪律
- 本仓只有机制,没有策略内容。 规则表、词表、阈值、命名都属于调用方:
bashguard 给裁决机制不给规则集,permgate 给判定链不给具体能力清单。
把「哪些命令危险」写成代码里的常量,就是把调用方的资产焊进原语仓。
- 不得引入领域词。 本仓是 tier 0,地板被所有下游继承——任何一层业务味
都会顺着依赖树扩散到矩阵每一层。
- 新增包必须带测试,且覆盖率不靠删用例达标。