CodeMender默认开沙箱:--unrestricted什么时候才能用
安全 Agent 最容易出现的悖论是:
为了验证漏洞,
它需要执行更多命令。
但执行得越自由,
安全风险越大。
Google 的 CodeMender CLI 已把 process-level sandbox 设成默认行为。当前官方说明里,CLI 会默认把编译、测试、Shell 等 Agent 提议的命令放进 OS 级沙箱;同时仍保留:
--sandbox=false
以及:
--unrestricted
这类绕过方式。
真正值得工程团队关注的,不是某个 Flag,而是:
“验证能力更强”不能等于“在开发机上放弃执行边界”。
第一原则:默认沙箱必须是Secure Default
安全工具以前常见:
Sandbox:
可选
用户忘记开:
直接在本机执行
CodeMender 后来把沙箱改成默认启用,这个方向更合理。
所有 Agent Code Execution 都应该:
默认隔离
显式升级权限
而不是:
默认全权限
出问题再加限制
--unrestricted真正适合什么
它不应该成为:
“命令失败就加这个”
的通用解决办法。
更合理的使用场景只有:
专门隔离的验证环境
一次性VM
无生产Credential
受控网络
可销毁文件系统
也就是说:
环境本身已经是Sandbox
以后,进程级命令策略才可以适当放宽。
两层沙箱不要混
第一层:
Infrastructure Sandbox
例如:
gVisor
MicroVM
Disposable VM
第二层:
Process / Command Sandbox
限制 Agent 在环境里具体能做什么。
如果只有第二层:
一旦Command Policy被绕过
Host仍然危险
如果只有第一层:
Agent可能在Sandbox里破坏大量数据
或滥用网络
所以更稳:
Infrastructure Isolation
+
Command Policy
我会定义3个Execution Profile
profiles:
inspect:
shell: restricted
network: deny
filesystem: readonly
verify:
shell: sandboxed
network: allowlist
filesystem: workspace-write
unrestricted-verify:
shell: unrestricted
network: deny-by-default
infrastructure: disposable-vm
unrestricted-verify 的重点不是 unrestricted。
而是:
Disposable VM
Profile不能由模型自己选择
危险:
Agent:
“这个验证需要unrestricted。”
↓
自动升级
正确:
Agent提出需求
↓
Policy Engine
↓
Risk Classification
↓
人工/自动批准
模型只能:
request profile
不能:
grant itself profile
一个Execution Request
public record ExecutionRequest(
String runId,
String agentId,
ExecutionProfile requestedProfile,
String reason,
String commandHash,
RiskLevel risk) {
}
Policy 决定:
ALLOW
DENY
REQUIRE_APPROVAL
Verify和Exploit要分开
安全 Agent 的目标应该是:
证明问题存在
而不是:
最大化利用效果
所以验证用例尽量做:
Minimal Reproduction
例如:
触发异常
证明越权路径存在
证明不变量被破坏
不要为了“更确定”继续扩大影响。
我会给Verification定义Blast Radius
verification:
max_files_modified: 5
max_network_targets: 1
max_runtime_seconds: 120
max_processes: 128
production_credentials: false
超过直接停止。
这比一句:
“请谨慎验证”
强得多。
网络必须默认Deny
安全验证最危险的环境之一是:
本机有公司VPN
Agent有Shell
网络全通
这时一个“验证”动作可能意外碰到:
真实内网
生产API
Metadata Endpoint
所以:
network=deny
应成为默认。
需要下载依赖:
Internal Mirror
需要验证 HTTP:
只开放目标测试服务
不要给验证环境生产Secret
即使网络隔离,也不要注入:
AWS_PROD_KEY
DATABASE_PROD_PASSWORD
GITHUB_ADMIN_PAT
验证环境用:
Synthetic Credential
Test Tenant
Mock Service
如果确实要访问受控真实系统:
短期Credential
最小Scope
只读优先
File System也要限制
安全 Agent 可能运行:
编译
测试
Patch
通常只需要项目 Workspace。
不应该看到:
~/.ssh
~/.aws
浏览器Cookie
整个Home
所以 Mount:
/project
就够。
不要:
-v $HOME:/home
Process Limit不能省
即使是沙箱,失控进程也能造成 DoS。
至少:
CPU
Memory
PID
Timeout
Stdout
Disk
全部有限额。
例如:
limits:
cpu: 2
memory: 2Gi
pids: 256
timeout: 180s
disk: 4Gi
stdout: 20Mi
为什么Stdout也要限
一个命令持续打印:
大量日志
可以拖垮:
Agent上下文
日志系统
网络
存储
所以超过:
20MiB
截断。
同时保留:
truncated=true
让 Agent 知道结果不完整。
unrestricted前一定要做Environment Attestation
不要只相信:
配置里写着isolated=true
执行前实际检查:
是不是Disposable VM
有没有生产Secret
Network Policy是否生效
Mount是否只读
可以生成:
public record EnvironmentAttestation(
String environmentId,
String imageDigest,
boolean disposable,
boolean productionCredentialAbsent,
String networkPolicyHash,
String mountPolicyHash) {
}
不满足:
禁止unrestricted
命令本身也要留Hash
command
working_directory
environment
profile
Canonicalize 后算:
command_hash
审批和审计都绑定它。
如果审批后命令变化:
重新审批
一个Execution Ledger
create table agent_execution_ledger (
execution_id varchar(128) primary key,
run_id varchar(128) not null,
profile varchar(64) not null,
command_hash varchar(64) not null,
environment_id varchar(128) not null,
exit_code int,
outcome varchar(32) not null,
started_at timestamptz not null,
completed_at timestamptz
);
以后可以分析:
有多少任务请求过unrestricted
多少真的批准
哪些Agent最频繁
unrestricted使用率应该非常低
指标:
unrestricted_execution_total
/
all_execution_total
如果达到:
20%
30%
说明默认沙箱能力不够,或者团队在滥用 Escape Hatch。
正常应该是极少数。
Escape Hatch要有Expiry
如果某个 Repo 临时允许:
unrestricted
不要永久写配置。
public record ExecutionException(
String repoId,
ExecutionProfile profile,
String reason,
String approvedBy,
Instant expiresAt) {
}
到期自动恢复默认。
Sandbox Failure不能自动升级权限
例如命令:
Permission denied
错误行为:
自动加--unrestricted重试
正确:
判断失败原因
↓
生成Permission Upgrade Proposal
↓
重新Policy
很多安全事故就是从:
“为了让测试先跑通”
开始的。
一个Upgrade Proposal
{
"current_profile": "verify",
"requested_profile": "unrestricted-verify",
"failed_command_hash": "sha256:...",
"reason": "sandbox denied ptrace",
"environment_attestation": "attest-918"
}
Reviewer 能看清楚为什么需要升级。
验证完成以后环境应该直接销毁
不要把 unrestricted 环境留着:
以后可能还要用
正确:
Create
→Verify
→Extract Artifact
→Destroy
Artifact 只允许:
Patch
Test Result
Trace
Minimal Evidence
不要整个磁盘打包出来。
最少测这10种情况
1. 默认沙箱确实开启
2. --sandbox=false需要显式批准
3. unrestricted只允许Disposable环境
4. 生产Credential存在时禁止升级
5. Network Policy不合格时禁止升级
6. Command Hash变化后审批失效
7. Timeout能杀死进程
8. PID限制能挡住失控进程
9. Sandbox失败不会自动升级
10. 验证完成后环境自动销毁
CodeMender 把沙箱改成默认,是一个非常值得所有 Coding Agent 借鉴的方向。
真正成熟的执行模型应该是:
默认受限
需要时申请升级
升级必须证明环境安全
高权限只存在几分钟
完成后立即销毁
--unrestricted 不应该是“让命令终于跑通”的快捷键。
它应该是一个明确的 Escape Hatch,而且只能在已经足够隔离的验证环境里使用。
当 Agent 可以编译、测试和执行 Shell 后,真正决定安全性的已经不是模型提示词,而是 Runtime 有没有把这种权限升级做成一条可审计、可限时、可撤销的系统流程。
更多企业级 AI 应用、Agent、RAG 与模型工程化内容,我会继续整理在 智元界:
https://www.zyentor.com/