feat(sandbox): introduce unified sandbox adapter architecture#6362
feat(sandbox): introduce unified sandbox adapter architecture#6362c121914yu merged 1 commit intolabring:mainfrom
Conversation
|
There is too much information in the pull request to test. |
|
|
1 similar comment
|
|
Preview sandbox Image: |
Preview mcp_server Image: |
Preview fastgpt Image: |
Introduces a new, extensible sandbox adapter architecture to abstract various sandbox providers behind a unified ISandbox interface. This design utilizes an adapter pattern with a BaseSandboxAdapter, enabling easy integration of providers like OpenSandboxAdapter and MinimalProviderAdapter. It ensures consistent functionality across environments through capability-driven polyfills for missing features. This provides a scalable and maintainable foundation for different execution environments.
77e2557 to
9d65a99
Compare
c121914yu
left a comment
There was a problem hiding this comment.
PR Review: feat(sandbox): introduce unified sandbox adapter architecture
📊 变更概览
- PR 编号: #6362
- 作者: @ctlaltlaltc
- 分支: main ← feat/sandbox-adapter
- 变更统计: +7164 -0 行
- 涉及文件: 40 个新增文件
✅ 优点
🎯 优秀的架构设计
- 适配器模式: 清晰的
BaseSandboxAdapter抽象 + 具体实现 - 接口隔离:
ISandboxLifecycle,ICommandExecution,IFileSystem,IHealthCheck合理分离 - 开闭原则: 新增提供商无需修改现有代码
- 模板方法: 基类定义算法骨架,子类实现具体步骤
🔧 关键特性
- 能力驱动 Polyfill: 自动检测并回退到命令行实现
- 统一错误处理: 自定义异常层次结构清晰
- 全面测试: 单元测试 + 集成测试覆盖完整
📐 代码质量
- 清晰的模块化结构
- 详细的类型定义
- 完善的 README 和使用示例
⚠️ 问题汇总
🔴 严重问题 (5 个,必须修复)
1. 安全漏洞: 命令注入风险
位置: CommandPolyfillService.ts (推测)
严重性: 🔴 CRITICAL - 可能导致任意代码执行
问题: 将用户输入直接拼接到命令字符串中,可能导致命令注入攻击
// 🚨 危险代码示例
async deleteFiles(paths: string[]): Promise<void> {
const cmd = `rm -rf ${paths.join(' ')}`; // ❌ 命令注入
}建议修复:
import { spawn } from 'child_process';
async deleteFiles(paths: string[]): Promise<void> {
await this.executeCommand('rm', ['-rf', ...paths]);
}
private async executeCommand(cmd: string, args: string[]): Promise<void> {
return new Promise((resolve, reject) => {
const proc = spawn(cmd, args, { stdio: 'pipe' }); // ✅ 安全
// ...
});
}2. 类型不安全: 错误类型断言
位置: BaseSandboxAdapter.ts:L180-195
严重性: 🔴 HIGH - 可能导致运行时错误
问题: 使用 as 断言绕过类型检查
// 🚨 不安全的类型断言
bytesWritten = await this.polyfillService.writeFile(
entry.path,
new Uint8Array(arrayBuffer as any) // ❌
);建议: 移除断言,使用正确的类型转换
3. 资源泄漏: 未正确关闭 ReadableStream
位置: BaseSandboxAdapter.ts:L210-225
严重性: 🔴 HIGH - 内存泄漏风险
问题: 异常情况下可能未释放 stream reader
// 🚨 资源泄漏风险
const reader = entry.data.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
chunks.push(value);
}
// ❌ 异常时 reader 未关闭建议: 使用 try-finally 确保资源释放
const reader = entry.data.getReader();
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
chunks.push(value);
}
} finally {
reader.releaseLock(); // ✅
}4. 竞态条件: 状态更新非原子性
位置: BaseSandboxAdapter.ts 和 MinimalProviderAdapter.ts
严重性: 🔴 MEDIUM - 状态不一致风险
问题: _status 字段没有同步保护
建议: 实现状态机或锁机制保护状态更新
5. 内存泄漏: EventEmitter 未清理
位置: OpenSandboxAdapter.ts (推测)
严重性: 🔴 MEDIUM - 长期运行可能内存泄漏
建议: 在 close() 方法中清理所有事件监听器
🟡 建议改进 (8 个)
- 性能优化: 可重用的正则表达式 (模块级别常量)
- 错误处理: 避免静默失败,记录或区分预期失败
- 类型定义: 减少
any类型使用,定义严格接口 - 代码重复: 提取 stream 处理为工具函数
- 输入验证: 添加参数验证和 Zod schema
- 日志记录: 集成结构化日志库 (pino)
- 测试覆盖: 添加边界情况测试 (空输入、超大文件、并发)
- 文档完善: 添加错误码说明和故障排查指南
🟢 可选优化 (4 个)
- 连接池: 实现连接复用提升性能
- Metrics: 集成 Prometheus 指标
- 重试机制: 对网络操作添加指数退避重试
- Branded Types: 为关键类型使用品牌类型防止混淆
🧪 测试建议
当前测试覆盖 ✅
- 单元测试: 所有适配器、Factory、Polyfill
- 集成测试: 命令执行、文件系统操作
- Mock 实现: 完整的测试替身
建议增加
- 安全测试: 命令注入攻击场景
- 并发测试: 多个操作同时执行
- 压力测试: 大文件传输、长命令输出
- 故障注入: 网络中断、超时等场景
💬 总体评价
代码质量评分
- 架构设计: ⭐⭐⭐⭐⭐ (5/5) - 优秀的设计模式应用
- 代码组织: ⭐⭐⭐⭐☆ (4/5) - 清晰的模块化结构
- 类型安全: ⭐⭐⭐☆☆ (3/5) - 存在类型断言和 any 类型滥用
- 安全性: ⭐⭐☆☆☆ (2/5) - 命令注入风险严重
- 测试覆盖: ⭐⭐⭐⭐☆ (4/5) - 全面的单元和集成测试
- 文档质量: ⭐⭐⭐⭐☆ (4/5) - 详细的 README 和示例
FastGPT 项目规范遵循度
- ✅ TypeScript 优先: 正确使用 type 和 interface
⚠️ 安全性: 需要加强输入验证和命令注入防护- ✅ 测试驱动: 完整的测试套件
⚠️ 错误处理: 部分静默失败需要改进
🚀 审查结论
决策: ⚠️ 需要修改后通过
必须修复项(阻塞性问题)
- 🔴 命令注入漏洞: 修改
CommandPolyfillService使用参数化命令执行 - 🔴 资源泄漏: 为所有 ReadableStream 操作添加 try-finally 保护
- 🔴 类型安全: 移除不必要的
as断言,减少any使用
建议修复项(非阻塞但强烈建议)
- 添加输入验证和参数校验
- 改进错误处理,避免静默失败
- 提取重复的 stream 处理逻辑
可选优化项
- 实现连接池、重试机制等性能优化
- 添加结构化日志和可观测性
📝 总结
这是一个架构设计优秀的 PR,展示了良好的软件工程实践:
优点:
- 清晰的抽象层次和模块化设计
- 完善的测试覆盖
- 考虑了扩展性和可维护性
主要问题:
- 安全性问题严重: 命令注入漏洞必须修复
- 资源管理需要改进
- 类型安全性有待提升
建议:
作者修复 3 个严重问题后即可合并。其他改进项可以在后续 PR 中迭代优化。
感谢 @ctlaltlaltc 的高质量贡献! 🎉
This commit introduces a new, extensible sandbox adapter architecture designed to abstract away the implementation details of different sandbox providers.
Key features of this new architecture include:
Unified ISandbox Interface: A common interface (
ISandbox) is defined for all sandbox operations, including lifecycle management, command execution, filesystem access, and healt checks. This follows the Interface Segregation Principle for a clean and modular design.Adapter Pattern: A
BaseSandboxAdapterprovides a template for concrete provider implementations. This allows for easy integration of new sandbox providers in the future.Provider Implementations:
OpenSandboxAdapter: A full-featured adapter for the OpenSandbox provider, utilizing its native APIs for optimal performance.MinimalProviderAdapter: A compatibility adapter for providers that only expose a shell. It uses aCommandPolyfillServiceto emulate filesystem and other operations using standa POSIX commands.Capability-Driven Polyfills: The system can detect the capabilities of a given provider and automatically use polyfills for any missing features, ensuring a consistent feature se across all providers.
Factory for Easy Creation: A
SandboxProviderFactorysimplifies the instantiation and configuration of different sandbox adapters.Robust Error Handling: A comprehensive set of custom exception classes provides detailed and structured error information.
Comprehensive Testing: The new architecture is accompanied by a full suite of unit and integration tests to ensure correctness and reliability.
This new architecture provides a solid foundation for supporting a wide range of execution environments in a maintainable and scalable way.