当 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_AGENT、CLAUDECODE、GEMINI_CLI、COPILOT_CLI之一设置为"1",或CURSOR_TRACE_ID被设置(任何值)。- 在 Linux 上:祖先链中任何父进程的环境变量中包含上述变量之一(通过
/proc/<pid>/environ)。即使智能体使用env -i或包装脚本删除了自己的变量,父进程链仍会告知 CLI 是谁启动了它。
检测每个进程只运行一次并被缓存。无法禁用。
知识门控模型
敏感变更遵循 passwd(1) 惯例:要修改一个密钥,必须证明你已经知道它。
- 想要轮换存储在
/credentials/cfDnsApiToken的 API 令牌? - CLI 询问:“当前值是什么?”
- 智能体通过
--current "$OLD"提供明文。CLI 对$OLD进行 SHA-256 哈希,并与当前存储值的摘要进行比较。匹配 → 写入通过。不匹配 → 拒绝,记录审计。
模型简单,但关闭了三个攻击面:
- 静默轮换:没有预先访问
$OLD的智能体无法用自己选择的值替换它。 - 探测式泄露:摘要响应从不包含明文;即使审计日志被攻破,也只显示
expected abc12345…, got deadbeef…,而不是底层值。 - 意外覆盖用户配置:每次都需要明确的
--current;set操作不会自动覆盖。
实际示例
# 获取脱敏占位符的短摘要(对智能体安全)。
$ 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 show、config field get、config machine list、config 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 覆盖
某些操作::交互式编辑器、--apply、field 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: agent 和 CLAUDECODE 信号记录在审计日志中。
了解智能体被允许访问的字段
rdc config field list --sensitive --output json
返回每个指针模板、其类型(secret / credential / pii / identifier),以及是否已提交到服务器端 HMAC 信封。
另请参阅
- AI 智能体集成概览: 顶层介绍
- Claude Code 配置: 集成模板
- JSON 输出信封: 机器可读响应
- 加密配置存储: 服务器端密码学强制
- 账户安全: 运营商安全态势