Skip to content

[security][less-computer] 批准 sudo/dd/chmod/chown 后护栏 deny 未解除(静默空操作)+ 注入畸形 allow 规则 #679

@appergb

Description

@appergb

现象

Less Computer(语音 Agent)护栏在用户「批准」sudo / dd / chmod / chown 这几类高风险命令后,命令仍被拦截 —— 用户点了批准却像没生效(静默空操作),同时还会向 allowed_tools 注入一条畸形 allow 规则。

根因(已读源码确认)

coding_agent/guard.rs 维护两份手写、无共享映射的清单,两者格式不一致:

  • HIGH_RISK_PATTERNSguard.rs:12-33)的 key 是命中子串,带空格/参数:"sudo ""dd if=""chmod -r 777 /""chown -r"
  • default_deny_rules()guard.rs:70-110)是前缀说明符:"Bash(sudo:*)""Bash(dd:*)""Bash(chmod:*)""Bash(chown:*)"

批准流(coordinator/dictation.rs:765-770):

let allow_rules = approved_patterns.iter().map(|p| format!("Bash({p}:*)")).collect();
deny.retain(|d| !allow_rules.iter().any(|a| a == d));   // 仅按“完全相等”移除

于是 "sudo "Bash(sudo :*)(多一个空格)≠ deny Bash(sudo:*) → deny 没被移除 → 命令仍被拦;同时把畸形规则 Bash(sudo :*) 注进 allow。dd if= / chmod -r 777 / / chown -r 同理。risk_equivalent_patterns 只覆盖 rm / force-push / git-clean,救不了这 4 个。

安全权衡(重要)

这是 fail-closed(批准无效,命令仍被拦)而非放行漏洞。但正确修法需要设计判断:直接让「批准 sudo」去掉 Bash(sudo:*) 会把整类 sudo 放给 agent,风险更大。倾向方案是把无法用安全前缀表达的 pattern(sudo/dd 等)标记为不可批准,或为每个 pattern 建立显式 pattern → deny_rule 映射,让「批准」与「deny 解除」严格一一对应、且不引入畸形 allow。

建议

  1. 用单一数据表统一 HIGH_RISK_PATTERNS ↔ deny_rule,消除两份清单漂移。
  2. 决策:这几类是否允许被批准;若允许,批准时按映射精确解除对应 deny,不注入畸形 allow。
  3. 单测:每个「可批准」pattern 的 deny 规则确实被解除路径匹配;不可批准的 pattern 不产生 allow。

来源:2026-06-16 全仓多 Agent 审计(护栏专项)。需安全设计评审。

Metadata

Metadata

Assignees

Labels

P2Medium prioritybugSomething isn't workingsecuritySecurity vulnerability or concern

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions