From fcb56fb814fd6bfb34be7b1dde7bf730a2913604 Mon Sep 17 00:00:00 2001 From: ymq Date: Fri, 18 Sep 2026 13:23:59 +0800 Subject: [PATCH] =?UTF-8?q?fix(security):=20cockpit=E8=B7=A8=E7=A7=9F?= =?UTF-8?q?=E6=88=B7=E9=97=A8=E7=A6=81(2026-09-18=E9=93=B6=E8=81=94?= =?UTF-8?q?=E4=BA=8B=E6=95=85=E5=AE=9E=E9=94=A4)=E2=80=94=E2=80=94?= =?UTF-8?q?=E2=91=A0picker=E5=85=A8=E8=A1=A8=E6=97=A0=E8=BF=87=E6=BB=A4?= =?UTF-8?q?=E6=94=B9=E6=9C=AC=E4=BA=A7=E7=BA=BF+=E6=9C=AC=E4=BA=BA?= =?UTF-8?q?=E5=88=9B=E5=BB=BA(=E6=97=A7=E7=89=88=E4=BB=BB=E4=BD=95?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E7=94=A8=E6=88=B7=E5=8F=AF=E6=9E=9A=E4=B8=BE?= =?UTF-8?q?=E5=85=A8=E9=83=A8=E6=9C=BA=E6=9E=84=E9=A1=B9=E7=9B=AE);?= =?UTF-8?q?=E2=91=A1context=5Fupdate=E5=8A=A0=E5=BD=92=E5=B1=9E=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C(=E5=90=8C=E6=9C=BA=E6=9E=84+=E6=9C=AC=E4=BA=BA?= =?UTF-8?q?=E5=88=9B=E5=BB=BA,owner.superuser=E6=94=BE=E8=A1=8C),=E5=A0=B5?= =?UTF-8?q?'=E4=BB=96=E6=9C=BA=E6=9E=84=E9=A1=B9=E7=9B=AEid=E5=86=99?= =?UTF-8?q?=E8=BF=9B=E8=87=AA=E5=B7=B1=E4=BC=9A=E8=AF=9D=E6=8C=87=E9=92=88?= =?UTF-8?q?=E2=86=92=E5=B7=A5=E4=BD=9C=E7=A9=BA=E9=97=B4/=E8=AF=BB?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E8=B6=8A=E6=9D=83'=E9=93=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- wwwroot/api/cockpit_context_update.dspy | 22 ++++++++++++++++++++++ wwwroot/api/cockpit_project_picker.dspy | 17 ++++++++++++++--- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/wwwroot/api/cockpit_context_update.dspy b/wwwroot/api/cockpit_context_update.dspy index 6e285c7..039f30a 100644 --- a/wwwroot/api/cockpit_context_update.dspy +++ b/wwwroot/api/cockpit_context_update.dspy @@ -17,6 +17,28 @@ if not pid and not iid: dbname = get_module_dbname('pipeline-sdlc') +# 归属门禁(2026-09-18 银联事故实锤):旧版无校验,任何登录用户可把**他机构** +# 项目 id 写进自己的会话指针(cockpit 上下文栏直传),随后工作空间列表/读文件 +# 端点按指针解析目录 → 看到他机构项目文件。校验对齐 agent_project_popup 切换 +# 门禁:同机构 + 本人创建(owner.superuser 放行,与 _check_confirm_operator 同口径)。 +if pid: + async with DBPools().sqlorContext(dbname) as _gsor: + _pr = await _gsor.sqlExe( + "SELECT org_id, created_by FROM sd_projects WHERE id=${p}$ LIMIT 1", {"p": pid}) + await _gsor.sqlExe("COMMIT", {}) + if not _pr: + return json.dumps({"success": False, "error": "项目不存在"}, ensure_ascii=False) + _porg = getattr(_pr[0], 'org_id', '') or '' + _pby = getattr(_pr[0], 'created_by', '') or '' + _uorg = await get_userorgid() or '' + if _pby != uid: + from pipeline_service.human_task_capability import _get_user_roles + _roles = await _get_user_roles(_gsor, uid) + if "owner.superuser" not in _roles or (_porg and _uorg != _porg): + return json.dumps({"success": False, + "error": "无权切换到该项目(仅限本人创建的项目)"}, + ensure_ascii=False) + async with DBPools().sqlorContext(dbname) as sor: # Upsert agent_settings existing = await sor.sqlExe( diff --git a/wwwroot/api/cockpit_project_picker.dspy b/wwwroot/api/cockpit_project_picker.dspy index c82fe99..c6e44b6 100644 --- a/wwwroot/api/cockpit_project_picker.dspy +++ b/wwwroot/api/cockpit_project_picker.dspy @@ -1,12 +1,23 @@ -# cockpit_project_picker.dspy - Returns all projects as {value, text} for dropdown +# cockpit_project_picker.dspy - Returns projects as {value, text} for dropdown # Used by cockpit context bar project picker +# +# 跨租户修复(2026-09-18 银联事故实锤):旧版全表无过滤,任何登录用户能枚举 +# 全部机构的全部项目(含他机构标书项目),配合 cockpit_context_update 无归属 +# 校验可把他机构项目写进自己的会话指针 → 工作空间/读文件端点随之越权看到他 +# 机构文件。可见范围对齐 agent_project_popup 切换门禁(用户 2026-09-11 拍板): +# 本产线 + 本人创建。 dbname = get_module_dbname('pipeline-sdlc') +uid = await get_user() +if not uid: + return [] + async with DBPools().sqlorContext(dbname) as sor: recs = await sor.sqlExe( - "SELECT id, name FROM sd_projects WHERE pipeline_id='sdlc_general' ORDER BY name", - {} + "SELECT id, name FROM sd_projects WHERE pipeline_id='sdlc_general' " + "AND created_by=${u}$ ORDER BY name", + {"u": uid} ) rows = []