运行 AI 生成题解前:静态预筛、沙箱与日志脱敏
模型生成的代码和用户提交的代码都属于不可信输入。它们不能在业务服务进程或宿主机上直接执行。静态检查有帮助,但不是安全边界;真正的隔离要由独立执行环境、最小权限和资源配额共同提供。
1. 分层防护的职责
flowchart TD A[不可信代码] --> B[解析与策略检查] B --> C[独立沙箱调度器] C --> D[最小权限运行环境] D --> E[受限输出与审计] F[密钥与业务服务] -.不挂载.-> D- 解析层用于拒绝不支持的语言特性、无效包和过大的输入;不能假设黑名单可识别所有恶意行为。
- 沙箱必须默认无网络、无宿主机挂载、非 root,并限制 CPU、内存、进程数、输出大小和执行时间。
- 业务凭证不应注入到沙箱的环境变量、卷或镜像层中。
2. 静态检查只做预筛选
Go 可以先解析 import,但不能仅靠禁用os/exec、net/http等包来保证安全:可利用路径不限于这些 import,语言和运行时也会变化。静态检查应作为资源节省和反馈工具,所有通过检查的代码仍必须进入隔离环境。
func ValidateGoImports(code string) error { fset := token.NewFileSet() f, err := parser.ParseFile(fset, "main.go", code, parser.ImportsOnly) if err != nil { return fmt.Errorf("parse code: %w", err) } for _, imp := range f.Imports { if strings.Trim(imp.Path.Value, `\"") == "net/http" { return errors.New("network packages are not supported in this runner") } } return nil }策略需与题目执行需求一致。例如完全只读根文件系统时,需要显式提供受限的临时工作目录来写入待编译文件。
3. 沙箱的最低要求
应由专门的执行服务创建短生命周期工作空间,并使用经维护的隔离运行时。以下 Docker 参数仅用于说明基本方向,不是完整生产配置:
docker run --rm --network=none --read-only --cap-drop=ALL \ --security-opt=no-new-privileges --pids-limit=64 \ --memory=128m --cpus=0.5 sandbox-image还需要针对运行时评估用户命名空间、seccomp、文件挂载、镜像来源和容器逃逸修复。执行器必须限制 stdout/stderr 的大小,并在超时后确认子进程被回收。
4. 密钥与日志
密钥应由专用的密钥管理服务或运行时身份机制提供给需要调用模型的业务服务,执行沙箱不应持有这类权限。日志默认记录请求 ID、语言、资源结果和策略命中原因;不要记录完整源码、请求头或凭证。脱敏正则可以减少意外泄露,但不能替代日志字段白名单。
5. 安全边界在隔离环境,不在黑名单
不可信代码的安全边界不应建立在“模型大概不会生成危险代码”或某一条 AST 规则上。把执行服务、凭证和业务服务隔离开,再用最小权限与可审计的资源限制收紧边界,才是可持续的做法。