跳至主要内容 跳至导航 跳至页脚

AI 智能体安全与防护机制

Rediacc CLI 如何防止 AI 编程助手泄露密钥、覆盖凭据或提升权限::知识门控、脱敏处理、祖先验证覆盖以及哈希链接审计日志。

当 Claude Code、Cursor、Gemini CLI、Copilot CLI 或其他任何 AI 编程助手驱动 rdc 时,CLI 对其的处理方式与坐在键盘前的人类不同。本页说明智能体能做什么、不能做什么,以及即使智能体试图绕过防护机制,这些机制依然有效的原因。

快速参考::智能体能做和不能做的事

操作智能体默认行为如何为特定用途解锁
rdc config show(已脱敏)✅ allowed
rdc config field get --pointer <pointer>(脱敏占位符或摘要)✅ allowed
rdc config field get --pointer <pointer> --digest✅ allowed
rdc config field set --pointer <pointer>(公开字段)✅ allowed
rdc config field set --pointer <pointer>(敏感字段,提供正确的 --current✅ allowed
rdc config edit --dump(已脱敏的 JSONC)✅ allowed
rdc config audit {log, tail, verify}✅ allowed
rdc config field set --pointer <pointer>(敏感字段,无 --current🔴 refused提供 --current "<旧值>"
rdc config field get --pointer <pointer> --reveal🔴 refused改用 --digest
rdc config show --reveal🔴 refused使用不带参数的 rdc config show
rdc config edit(交互式编辑器)🔴 refused由人类在启动智能体前设置 REDIACC_ALLOW_CONFIG_EDIT=*
rdc config edit --apply <file>🔴 refused相同的覆盖方式
rdc config field rotate --pointer <pointer>🔴 refused相同的覆盖方式;使用交互式确认
rdc term connect -m <machine>(直接 SSH 到机器)🔴 refused先 fork 一个仓库,再连接到 fork

所有被拒绝的操作都会以 outcome: refused 和原因写入审计日志。

智能体的检测方式

当以下任一条件为真时,CLI 将进程视为智能体:

  • REDIACC_AGENTCLAUDECODEGEMINI_CLICOPILOT_CLI 之一设置为 "1",或 CURSOR_TRACE_ID 被设置(任何值)。
  • 在 Linux 上:祖先链中任何父进程的环境变量中包含上述变量之一(通过 /proc/<pid>/environ)。即使智能体使用 env -i 或包装脚本删除了自己的变量,父进程链仍会告知 CLI 是谁启动了它。

检测每个进程只运行一次并被缓存。无法禁用。

知识门控模型

敏感变更遵循 passwd(1) 惯例:要修改一个密钥,必须证明你已经知道它。

  • 想要轮换存储在 /credentials/cfDnsApiToken 的 API 令牌?
  • CLI 询问:“当前值是什么?”
  • 智能体通过 --current "$OLD" 提供明文。CLI 对 $OLD 进行 SHA-256 哈希,并与当前存储值的摘要进行比较。匹配 → 写入通过。不匹配 → 拒绝,记录审计。

模型简单,但关闭了三个攻击面:

  1. 静默轮换:没有预先访问 $OLD 的智能体无法用自己选择的值替换它。
  2. 探测式泄露:摘要响应从不包含明文;即使审计日志被攻破,也只显示 expected abc12345…, got deadbeef…,而不是底层值。
  3. 意外覆盖用户配置:每次都需要明确的 --currentset 操作不会自动覆盖。

实际示例

# 获取脱敏占位符的短摘要(对智能体安全)。
$ rdc config field get --pointer /credentials/cfDnsApiToken
{"pointer": "/credentials/cfDnsApiToken", "value": "<redacted:secret>:abc12345"}

# 尝试无证明地覆盖::拒绝。
$ rdc config field set --pointer /credentials/cfDnsApiToken --new '"agent-picked-value"'
 Precondition failed: sensitive path requires --current (or --rotate-secret)

# 提供当前明文::允许。
$ rdc config field set --pointer /credentials/cfDnsApiToken \
    --current "$OLD_CF_TOKEN" \
    --new   "$NEW_CF_TOKEN"
Set /credentials/cfDnsApiToken

如果智能体从未拥有 $OLD_CF_TOKEN,它就无法满足前提条件,轮换被拒绝。拥有它的用户仍然可以通过编辑器或从 shell 传入 --current 来完成操作。

默认脱敏

每个读取敏感状态的 rdc 命令::config showconfig field getconfig machine listconfig edit --dump::对密钥字段返回脱敏占位符而非明文:

"sshKey":       "<redacted:credential>:9f3a2c1b"
"cfDnsApiToken":"<redacted:secret>:abc12345"
"storages.s3-prod.vaultContent": "<redacted:secret>:1f2e3d4c"

占位符的 8 位十六进制后缀是 sha256(canonicalize(value)) 的前 8 个字符::足以一眼区分两个不同的值,但不足以逆向推导。智能体可以使用占位符跟踪某个值是否发生了变化,而无需查看该值。

--reveal 为交互式 TTY 上的人类取消脱敏。智能体无论 TTY 状态如何都会被拒绝。每次授予都会写入 reveal_granted 审计条目;每次拒绝都会写入 refused 条目,并附带操作者的智能体信号。

REDIACC_ALLOW_CONFIG_EDIT 覆盖

某些操作::交互式编辑器、--applyfield rotate::是为人类设计的,没有对智能体安全的路径。如果你明确希望智能体执行其中一项,可以设置:

export REDIACC_ALLOW_CONFIG_EDIT='*'          # 完全绕过
# 或
export REDIACC_ALLOW_CONFIG_EDIT='/credentials/ssh/privateKey,/infra/cfDnsZoneId'
# (逗号分隔的范围 glob::每段允许 * 通配符)

……智能体会继承它。

关键细节:覆盖必须出现在祖先链中智能体上方的进程中。如果智能体在自己的环境中设置它(或在其启动的子 shell 中),CLI 会拒绝并告知你:

Interactive editor is blocked in agent environments (REDIACC_ALLOW_CONFIG_EDIT was set but ancestry verification failed: the override must be set by your shell, not by an agent).

效果:智能体不能通过在会话中途运行 export REDIACC_ALLOW_CONFIG_EDIT='*' 来绕过防护机制。只有父进程(在启动智能体之前,你在终端中的操作)才能打开那扇门。

审计日志

每次变更、每次拒绝、每次 --reveal 授予都会向 ~/.config/rediacc/audit.log.jsonl(模式 0600,10 MB 时轮换)写入一行 JSONL。每行都经过哈希链接:其 prevHash 字段为 sha256("<上一行>")。篡改任何一行都会破坏此后所有行的链。

{"ts":"2026-04-21T10:02:47.831Z","actor":{"kind":"agent","agentSignals":["CLAUDECODE"]},"command":"config field set","paths":["/credentials/cfDnsApiToken"],"outcome":"ok","configId":"...","configVersion":48,"prevHash":"sha256:9f3a..."}
{"ts":"2026-04-21T10:02:51.114Z","actor":{"kind":"agent","agentSignals":["CLAUDECODE"]},"command":"config edit","paths":[],"outcome":"refused","reason":"agent without REDIACC_ALLOW_CONFIG_EDIT=*","prevHash":"sha256:abc1..."}
{"ts":"2026-04-21T10:03:05.220Z","actor":{"kind":"human"},"command":"config show --reveal","paths":[],"outcome":"reveal_granted","configId":"...","configVersion":48,"prevHash":"sha256:deac..."}

检查

# 列出最近的条目
rdc config audit log --since 24h

# 按指针 glob 过滤
rdc config audit log --path '/credentials/*'

# 仅显示智能体发起的条目
rdc config audit log --actor agent

# 实时流式传输新条目(Ctrl+C 停止)
rdc config audit tail

# 验证哈希链是否完整
rdc config audit verify
# → "Chain integrity verified across 247 entries."
#   或
# → "Chain broken at line 103: file has been tampered with or corrupted."

审计日志中绝不会出现的内容

  • 明文密钥值
  • 密码短语、令牌、SSH 密钥
  • --current 前提条件不匹配时的新旧值(仅 8 位摘要前缀)

该日志可安全地与安全审计人员共享,或附在错误报告中。

行为模型的局限性

智能体防护机制是行为性的,而非密码学性的。在与配置文件相同的 UID 下运行的有意或经过指示的智能体,始终可以执行 cat ~/.config/rediacc/rediacc.json 并读取明文,因为该文件对进程是可读的。

如需真正的密码学强制,请使用加密配置存储:密钥存储在服务器端,每个敏感字段携带字段级别的 HMAC 承诺,账户 Worker 会拒绝 --current 前提条件与存储哈希不匹配的写入。服务器永远不会看到明文::零知识::但门控仍然被强制执行。

本地文件路径是”轻松的路也是安全的”。远程存储路径是”困难的路也是困难的”。

快速方案

允许智能体轮换单个云端令牌

# 以你自己的身份,在启动智能体之前:
export REDIACC_ALLOW_CONFIG_EDIT='/credentials/cfDnsApiToken'
claude-code              # 或 cursor、gemini 等

现在智能体可以执行 config field rotate /credentials/cfDnsApiToken --new …,但仍无法编辑 /credentials/ssh/privateKey 或打开交互式编辑器。

允许智能体进行广泛的配置编辑会话

export REDIACC_ALLOW_CONFIG_EDIT='*'
claude-code

智能体可以打开 rdc config edit,使用 --reveal,并运行 field rotate。每个操作仍会以 actor.kind: agentCLAUDECODE 信号记录在审计日志中。

了解智能体被允许访问的字段

rdc config field list --sensitive --output json

返回每个指针模板、其类型(secret / credential / pii / identifier),以及是否已提交到服务器端 HMAC 信封。

另请参阅