一、整体定位

Matplotlib Skill 是 OpenClaw 标准可视化技能(Skill),依托三层Tool治理、代码沙箱双层防护、可插拔 ToolAdapter 插槽实现;
用于Agent根据自然语言自动生成图表代码、渲染图片,输出图片链接/二进制图片,支撑报表、数据分析、趋势绘图场景。
整套能力由三部分协同:

  1. skills/matplotlib/SKILL.md:技能契约(第一层Tool治理,柔性引导)
  2. Matplotlib 代码执行沙箱(第二层ToolAdapter执行层)
  3. 正则前置拦截 + Preamble运行时锁死 + 非特权容器账号(代码沙箱双层防护兜底)

核心痛点

  1. Matplotlib 默认后端容易打开宿主机GUI窗口、读取本地文件、发起内网请求;
  2. AI容易生成恶意代码:遍历目录、导出密钥、连接内网数据库、反弹Shell;
  3. 绘图代码长时间运行、超大图片生成耗尽内存;
  4. 生成图片路径混乱,存在跨会话图片文件互相覆盖、泄漏风险;
  5. 多并发绘图请求文件竞态、临时文件残留堆积磁盘。

二、Matplotlib Skill 基础架构

1. 文件结构(标准化Skill目录)

skills/
└── matplotlib/
    ├── SKILL.md          # 技能描述、调用规范、示例代码
    ├── skill.yaml        # 技能元数据:名称、入参、标签、依赖、资源限额
    └── runtime/          # 沙箱配套静态资源、字体配置

2. SKILL.md 承载内容(三层Tool治理【第一层:业务引导层】)

属于六层提示词体系第4层(工具与技能流程层),自动载入Agent上下文。
核心约束写入SKILL.md:

  1. 调用方式:matplotlib_plot(code: str, width, height, dpi)
  2. 强制约定:
    • 必须使用 Agg 无GUI后端;禁止 plt.show()
    • 图片仅允许保存至沙箱内部临时目录
    • 禁止读取沙箱外部路径文件
    • 代码内禁止发起网络请求、导入os.system/subprocess高危模块
  3. 标准代码模板示例,引导模型写出合规绘图代码;
  4. 输出约定:执行成功返回图片访问URL,失败返回结构化报错。

注意:SKILL.md 仅为提示词引导;模型幻觉绕过规范写出恶意代码时,依靠沙箱双层防护硬拦截

3. 执行入口链路(完整调用流程)

LLM 根据SKILL.md生成 matplotlib_plot 工具调用
        ↓
三层Tool治理第三层:rules.md 全局规则前置校验(RulePolicySpan)
        ↓
进入ToolAdapter → 分发至matplotlib专用代码沙箱
        ↓
第一层防护:正则静态扫描(拦截高危导入、内网访问、文件遍历)
        ↓
第二层防护:启动非特权隔离容器,自动注入Matplotlib专用Preamble
        ↓
Preamble强制初始化安全环境 → 执行AI绘图代码
        ↓
渲染图片写入沙箱临时隔离目录
        ↓
沙箱执行结束,同步将图片上传至对象存储/临时静态服务,生成可访问URL
        ↓
销毁沙箱、全盘清理临时文件
        ↓
图片URL作为tool_result返回Agent

三、Matplotlib 专用沙箱安全机制(双层防护复用+专项增强)

复用前文【代码沙箱双层防护:正则 + Preamble + 特权账号】基础体系,并针对Matplotlib场景做定向加固。

3.1 第一层:正则静态前置扫描(容器创建前执行)

内置定向黑名单正则,除通用高危规则外,额外增加绘图场景专属拦截规则:

  1. 拦截导入高危模块
import os|import subprocess|import socket|import requests
from os import|from subprocess import
  1. 拦截GUI相关调用
plt\.show\(\)|plt\.ion\(\)|plt\.ioff\(\)
  1. 拦截外部文件读写(绝对路径、父目录穿越 ../
open\("\/|open\("\.\.\/|pd\.read_csv\("\/
  1. 拦截内网IP网络请求、nc/socat等渗透工具
  2. 拦截尝试写入沙箱以外路径保存图片
plt\.savefig\("\/|plt\.savefig\("\.\.\/

一旦匹配,直接拒绝创建沙箱,零资源消耗,写入Langfuse RulePolicySpan

3.2 第二层:Preamble 强制前置脚本(Matplotlib定制版)

沙箱执行顺序:【定制Preamble】 + AI生成绘图代码
Preamble自动完成强制安全初始化,不可跳过、不可被AI代码覆盖。

Preamble 四大核心作用
  1. 强制切换Agg无图形后端
import matplotlib
matplotlib.use("Agg")  # 禁止任何GUI后端,杜绝弹窗、宿主机显示抢占
  1. 劫持文件读写与savefig路径校验
    重写 plt.savefig()
  • 强制目标路径限定在沙箱内部 /sandbox/workspace/output/
  • 拦截外部绝对路径、../ 路径穿越;
  1. 删除/屏蔽高危系统API
    删除 os.systemsubprocess.call、socket网络接口;
  2. 资源硬限额注入
# 限制最大画布尺寸、最大DPI,防止超大图耗尽内存
MAX_WIDTH = 1600
MAX_HEIGHT = 1200
MAX_DPI = 150

3.3 底层容器账号隔离

  1. 统一使用 unprivileged 非特权UID运行,禁止elevated提升权限
  2. 每个绘图任务独立临时沙箱,独立工作目录;
  3. 沙箱网络策略:默认阻断内网网段,仅可选择性放开公网(可通过ConditionalOnToolGroup开关);
  4. 执行超时上限(默认20s),防止复杂绘图代码死循环、无限渲染。

四、资源隔离与文件生命周期防泄漏(专项重点)

4.1 临时文件隔离规则

  1. 每个沙箱独立随机命名工作目录;
  2. 绘图产出图片只允许写入沙箱内 ./output/
  3. 沙箱销毁时:rm -rf 全盘删除整个临时目录;
    ✅ 杜绝:多会话绘图文件互相覆盖、图片残留磁盘、跨用户读取他人图表。

4.2 图片分发链路隔离

沙箱内生成图片不直接对外暴露本地路径

  1. 执行成功后,代码沙箱内部读取二进制图片;
  2. 上传至独立临时对象存储/静态资源网关;
  3. 返回带时效签名的临时URL(默认TTL 30分钟,自动过期删除);
  4. Agent只能拿到URL,永远无法获取服务器本地文件路径。

4.3 并发安全配套(联动SessionLock、Per-Request)

  1. 同一会话受SessionLock保护,串行执行绘图Skill,避免同一会话并发创建多个沙箱引发资源风暴;
  2. 每个绘图请求拥有独立Per-Request上下文,Langfuse链路自动挂载绘图ToolRunSpan
  3. Cron定时任务调用绘图技能时,启用CronContextHolder,非阻塞抢占会话锁,不抢占前台用户算力。

五、与 OpenClaw 各大核心模块联动

5.1 联动三层Tool治理

  1. 第一层:SKILL.md 业务规范引导模型写出合规绘图代码;
  2. 第二层:ToolAdapter + matplotlib专用沙箱执行、资源限额;
  3. 第三层:rules.md 全局工具黑白名单,可全局启用/禁用matplotlib技能组。

示例 rules.md 配置片段

# 全局管控绘图技能
allow_tool_group: ["matplotlib"]
max_turn_tool_calls: 2 # 单轮最多两次绘图

5.2 联动 12+ ConditionalOnProperty

支持按环境、租户、Agent精细化开关:

  • ConditionalOnGlobalEnv:离线环境关闭公网访问;
  • ConditionalOnTenant:金融租户禁止绘图代码访问外部网络;
  • ConditionalOnAgentName:数据分析Agent启用,客服Agent直接禁用matplotlib工具组;
  • claw.tool.group.matplotlib.enable 总开关,一键下线绘图能力。

5.3 联动四层Langfuse追踪

一次绘图完整埋点链路:

  1. ToolRunSpan:记录传入代码、画布尺寸、dpi;
  2. 正则拦截事件生成独立 RulePolicySpan
  3. 记录指标:沙箱启动耗时、渲染耗时、图片大小、是否超时;
  4. 标签自动携带 skill=matplotlibcontext_type=user_request/cron_task

5.4 联动 SubAgent 安全约束

  1. 子代理默认继承收紧后的工具权限;可通过AGENTS.md控制子代理是否允许调用绘图技能;
  2. 子代理绘图沙箱同样强制非特权账号,禁止提升权限;
  3. 子代理生成图片URL回流父代理时,自动过滤沙箱内部本地路径,仅保留对外临时链接,防止路径泄露(防污染机制)。

5.5 联动 Context Compaction

绘图产生的超长报错堆栈、长代码文本,在Stage1预裁剪自动截断,避免大量日志撑爆上下文窗口;图片URL短字符串完整保留。

5.6 联动并发安全体系

  • 用户前台绘图:Per-Request 上下文;
  • 定时报表绘图(Cron生成日报图表):CronContextHolder,非阻塞SessionLock;
  • 多并发绘图受全局沙箱并发池限流,防止瞬间创建大量容器耗尽服务器资源。

六、完整风险防御矩阵

风险场景 防御手段
AI代码使用plt.show()尝试拉起GUI Preamble强制Agg后端 + 正则拦截
代码读取服务器敏感本地文件 Preamble劫持open + 路径白名单 + 沙箱目录隔离
绘图代码发起内网扫描、访问内部数据库 沙箱网络隔离 + 正则拦截网络模块
代码执行死循环、超大画布内存溢出 容器内存限额 + 执行超时强制kill
多用户绘图文件互相覆盖、图片残留 每任务独立随机沙箱目录,销毁全盘清理
模型写出带后门的Python代码 静态正则前置拦截 + Preamble删除高危API双层兜底
定时大量报表绘图抢占用户算力 Cron非阻塞SessionLock,会话繁忙自动跳过绘图任务

七、优缺点

优势

  1. 双层纵深安全,专门针对可视化场景加固,解决Matplotlib原生运行环境不安全问题;
  2. 引导层(SKILL.md)+执行层(沙箱)双约束,大幅降低模型写出违规代码概率;
  3. 文件、网络、权限、内存、超时全方位隔离,适合企业多租户私有化部署;
  4. 全链路可观测,绘图耗时、拦截事件、资源消耗完整埋点;
  5. 标准化Skill架构,可直接迁移Seaborn、Plotly等其他可视化工具,复用同一套沙箱底座。

短板

  1. 每个绘图任务新建销毁容器,存在少量启动开销;高频绘图场景建议沙箱预热池优化;
  2. 复杂中文图表需要预先在沙箱镜像内置中文字体,否则乱码;
  3. 极端混淆、动态拼接恶意代码可以绕过静态正则,依赖Preamble运行时兜底。

八、横向对比

原生AgentScope

无独立Skill规范;无Matplotlib专用沙箱;无Preamble环境锁定;代码直接在宿主进程运行,极易读取本地文件、拉起GUI,不适合生产。

OpenAI Codex

可以生成绘图代码,但没有托管隔离沙箱执行;代码需要本地环境运行,不存在文件隔离、网络管控。

Claude Code

本地执行Matplotlib,权限为当前操作系统用户,缺少容器隔离、路径劫持、网络阻断等企业安全能力。

OpenClaw Matplotlib Skill

标准化技能契约 + 专用强化沙箱 + 全链路权限/文件/网络隔离,深度融入整套UpClaw企业生产安全体系,满足多租户、私有化、可审计上线要求。

九、典型落地业务场景

场景1:企业数据分析Agent

用户自然语言:根据近30日订单数据绘制月度趋势柱状图

  1. LLM读取matplotlib SKILL.md,生成合规绘图代码;
  2. 正则扫描无高危指令,启动隔离沙箱;
  3. Preamble强制Agg后端,锁定输出目录;
  4. 渲染图片,上传静态存储返回临时URL;
  5. 沙箱销毁,临时文件全部清理;
  6. Agent将图片链接嵌入回答返回用户。

场景2:定时报表Cron任务

每日凌晨自动生成业务指标图表:

  1. CronContextHolder创建定时上下文;
  2. 非阻塞抢占SessionLock;会话空闲才执行绘图;
  3. 沙箱执行绘图,生成图片持久保存至报表系统;
  4. 全程独立观测标签,区分后台定时流量。

十、生产最佳实践规范

  1. 沙箱镜像预先预装所需中文字体,解决中文方框乱码;
  2. 生产环境保持沙箱内网网络阻断,确有公网需求才通过条件开关放开;
  3. 设置合理最大画布尺寸、执行超时、内存限额,防止资源耗尽;
  4. 临时图片URL设置较短过期时间,降低图片泄露风险;
  5. Langfuse配置告警:监控频繁触发matplotlib正则拦截,排查是否存在持续生成恶意代码的提示词漏洞。
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐