pipeline-sdlc/wwwroot/workspace_edit.xterm
ymq f3e81a69db security: Wterm(workspace_edit) bwrap沙箱化,防 rm -rf/sudo提权/越界/网络攻击
- vi 编辑包进 bwrap 沙箱:只暴露 workspace(挂/home) + 只读系统目录
- --unshare-user/pid/ipc/uts/net 隔离,no_new_privileges 阻断 sudo setuid
- bwrap 缺失时拒绝终端(安全优先,不给完整 shell)
2026-08-13 18:33:31 +08:00

84 lines
2.5 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
import shlex
import shutil
file_id = (params_kw or {}).get('id', '').strip()
uid = await get_user()
if not uid:
uid = 'user-01'
dbname = get_module_dbname('pipeline-sdlc')
workspace_base = '/d/pipeline/workspaces'
async with DBPools().sqlorContext(dbname) as sor:
recs = await sor.sqlExe(
"SELECT current_project_id FROM pipeline_agent_settings WHERE user_id=${u}$", {"u": uid})
pid = getattr(recs[0], 'current_project_id', '') if recs else ''
ws_dir = ''
if pid:
proj = await sor.sqlExe("SELECT name, org_id, workspace_dir FROM sd_projects WHERE id=${p}$", {"p": pid})
if proj:
ws = getattr(proj[0], 'workspace_dir', '') or ''
if ws.startswith('/'):
ws_dir = ws
else:
pname = getattr(proj[0], 'name', '')
org_id = getattr(proj[0], 'org_id', '0') or '0'
ws_dir = workspace_base + '/' + org_id + '/' + pname
if not file_id or not ws_dir:
r = DictObject()
r.host = 'localhost'
r.username = 'pipeline'
r.cmdargs = ['echo 未指定文件']
return r
full_path = ws_dir + '/' + file_id
# 路径穿越校验
real_ws = os.path.realpath(ws_dir)
real_full = os.path.realpath(full_path)
if not real_full.startswith(real_ws + os.sep):
r = DictObject()
r.host = 'localhost'
r.username = 'pipeline'
r.cmdargs = ['echo 非法路径']
return r
# bwrap 沙箱路径(不存在则拒绝终端,安全优先,不给完整 shell
bwrap = shutil.which('bwrap')
if not bwrap and os.path.exists('/d/pipeline/pipeline-app/bin/bwrap'):
bwrap = '/d/pipeline/pipeline-app/bin/bwrap'
r = DictObject()
r.host = 'localhost'
r.username = 'pipeline'
if not bwrap:
r.cmdargs = ['echo 沙箱不可用,已拒绝终端访问']
return r
# bwrap 沙箱:只暴露 workspace挂载到 /home 可写)+ 只读系统目录,
# 隔离 user/pid/ipc/uts/net防 rm -rf /、sudo 提权、越界访问、网络攻击
cmd = (
bwrap +
' --unshare-user --unshare-pid --unshare-ipc --unshare-uts --unshare-net'
' --die-with-parent'
' --ro-bind /usr /usr'
' --ro-bind /bin /bin'
' --ro-bind /sbin /sbin'
' --ro-bind /lib /lib'
' --ro-bind /lib64 /lib64'
' --ro-bind /etc /etc'
' --proc /proc'
' --dev /dev'
' --tmpfs /tmp'
' --bind ' + shlex.quote(real_ws) + ' /home'
' --chdir /home'
' --setenv HOME /home'
' -- vi ' + shlex.quote(file_id)
)
r.cmdargs = [cmd]
return r