fix(isolation): 第6层泄漏——通用会话工作空间总根可枚举所有产线项目
实测发现:工具层隔离生效后,LLM 改用 list_files/run_command 浏览
WORKSPACE_BASE 总根({base}/{org}/{产线}/…全量可见),从目录名
枚举出所有产线的全部项目。
修复:
- workspace.py 新增 generic_workspace_dir():通用会话专属目录 _general/{uid}
- agent_loop_v2: generic 会话文件根改专属目录(_resolve_ws_path 越界保护圈死)
- agent_loop_v2: run_command 对通用会话执行层拒绝(shell 无法圈禁在目录内)
- schema 层剔除 shell 类工具(配合 pipeline-core)
This commit is contained in:
parent
b99fb4cc13
commit
5c28fed040
@ -55,6 +55,12 @@ _PROJECT_TOOL_NAMES = {
|
||||
"pause_project", "resume_project", "delete_project",
|
||||
}
|
||||
|
||||
# 产线耦合工具(2026-09-05 第 6 层泄漏修复):run_command 的 shell 无法圈禁
|
||||
# 在目录内(cwd 只是起点,命令可 cd/绝对路径访问全工作空间),纯通用会话
|
||||
# 一律剔除。read_file/list_files/search_files/write_file 受 _resolve_ws_path
|
||||
# 越界保护,配合通用会话专属工作目录(_general/{user})天然隔离,保留。
|
||||
_GENERIC_DENIED_TOOLS = {"run_command"}
|
||||
|
||||
|
||||
# ── 默认工具定义(在 pipeline-core 未加载时使用)──
|
||||
|
||||
@ -457,6 +463,18 @@ class AgentExecutor:
|
||||
# 6. 项目空间键:generic→'general'(通用助手),否则用真实 pipeline_id(产线之间隔离)
|
||||
self.space = GENERAL_SPACE if self.generic else (self.pipeline_id or GENERAL_SPACE)
|
||||
|
||||
# 7. 通用会话专属工作目录(2026-09-05 第 6 层泄漏修复):默认文件根是
|
||||
# WORKSPACE_BASE 总根({base}/{org}/{产线}/… 全量可见),LLM 用
|
||||
# list_files/read_file 就能从目录名枚举所有产线的项目。通用会话改用
|
||||
# 用户专属目录 _general/{user_id},_resolve_ws_path 越界保护把它圈死。
|
||||
if self.generic:
|
||||
from .workspace import generic_workspace_dir
|
||||
self.workspace_dir = generic_workspace_dir(self.user_id)
|
||||
try:
|
||||
os.makedirs(self.workspace_dir, exist_ok=True)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
async def _resolve_skills_base_dir(self):
|
||||
"""技能根目录 = 全局 skills/(单一技能树,所有机构共享读,2026-08-21 重构)。"""
|
||||
try:
|
||||
@ -809,6 +827,11 @@ class AgentExecutor:
|
||||
if self.generic and tool_name in _PROJECT_TOOL_NAMES:
|
||||
return ("FAIL: 当前是通用助手会话(未挂产线插件),不提供项目管理能力,"
|
||||
"无法查看或操作任何产线的项目。")
|
||||
# 产线耦合工具拦截(2026-09-05 第 6 层):run_command 的 shell 无法圈禁
|
||||
# 在工作目录内,通用会话一律拒绝。
|
||||
if self.generic and tool_name in _GENERIC_DENIED_TOOLS:
|
||||
return ("FAIL: 当前是通用助手会话,不提供命令执行能力。"
|
||||
"如需处理文件,可直接上传文件,我会读取上传内容作答。")
|
||||
|
||||
# 通用内建工具映射(core 内核,产线无关)。
|
||||
# 产线专属工具(create_task/diagnose_project 等)已迁移到 sdlc_ability 能力包,
|
||||
|
||||
@ -15,6 +15,18 @@ WORKSPACE_BASE = '/d/pipeline/workspaces'
|
||||
GENERAL_SPACE = 'general'
|
||||
|
||||
|
||||
def generic_workspace_dir(user_id: str) -> str:
|
||||
"""纯通用会话的专属工作目录(2026-09-05 产线隔离第 6 层修复)。
|
||||
|
||||
通用会话没有项目,文件工具的文件根若用 WORKSPACE_BASE 总根,
|
||||
LLM 可浏览 {base}/{org}/{产线}/… 从目录名枚举所有产线的项目。
|
||||
改为每用户专属目录 _general/{user_id},配合 _resolve_ws_path 的
|
||||
越界保护,把通用会话的文件视野圈死在自己的目录内。
|
||||
"""
|
||||
uid = (user_id or 'anonymous').replace('/', '_').replace('..', '_') or 'anonymous'
|
||||
return os.path.join(WORKSPACE_BASE, '_general', uid)
|
||||
|
||||
|
||||
def build_workspace_path(workspace_base, org_id, space, name, project_id=''):
|
||||
"""构建项目 workspace 路径:{base}/{org_id}/{space}/{name}。
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user