OpenClaw 技能装载审计:给 7×24 常驻的「龙虾」划定可验证的权限边界
摘要:OpenClaw(社区昵称「龙虾」)把个人 AI 助手从「用时才开」的任务型工具,变成了 7×24 常驻、多渠道触达的网关型 Agent。技能装得越多,它的触发面就越宽------而大多数人只做过「装完跑一次」的首跑验收,没人回答过更关键的问题:这些技能会在什么消息上被谁触发、实际拿到什么权限、更新之后行为变没变。本文从常驻 Agent 与任务型 Agent 的结构性差异入手,拆解静默触发、权限累积、供应链漂移三类典型风险,给出一套可落地的触发面审计与最小权限断言方法,并附配套审计脚本,帮助你在自己的龙虾上把「装了什么」变成「验证过什么」。
一、现象:技能装得越多,越聪明还是越危险
OpenClaw 是过去一年个人 Agent 生态里增长最快的项目之一。它的形态和 CLI 工具完全不同:一个跑在自己机器上的自托管网关,把 WhatsApp、Telegram、Slack 这类消息渠道接到本地的大模型和工具链上,人不在电脑前也能随时指挥它干活,进程一开就是数周数月。因为吉祥物是一只龙虾,社区里大家都管它叫「龙虾」,管部署它叫「养一只龙虾」(项目主仓见 openclaw/openclaw,部署与技能机制的文档在 docs.openclaw.ai)。
养龙虾的乐趣很大程度上来自装技能。技能目录里放一个说明文档加几个脚本,龙虾就会多一门手艺:查快递、记账、追 RSS、生成日报。社区里技能市场琳琅满目,新手的典型路径是照着别人分享的技能清单一路装下去,一周装三十个,恨不得把龙虾武装成瑞士军刀。
但一位长期观察者的话值得在这里重提。他在讨论 Agent 使用趋势时写道:大家使用 OpenClaw 这类 Agent 的频率越来越高之后,人类直接操作软件的频率反而下降了,软件的入口正在被 Agent 接管。这个判断对生产力是好消息,对安全是坏消息:当 Agent 成为入口,针对入口的一切攻击面也就随之转移到了 Agent 身上------而你往它身上装的每一个技能,都是这个攻击面上的一扇小门。
问题在于,绝大多数人验证技能的方式,还是从任务型工具时代迁移过来的老习惯:看一遍 README,装上,自己试一次,能跑就收工。这种「首跑验收」在 CLI 工具上是合理的------你主动敲命令,会话结束就销毁。但在常驻网关上,它连及格线都算不上:首跑只验证了「你本人主动发起」这一条路径,而常驻 Agent 的技能有大量非主动触发路径------群聊里的一条闲聊、一个定时任务、一次 webhook 回调,都可能把某个技能悄悄注入上下文。
笔者在朋友的龙虾上做过一次统计:四十多个技能里,有十七个会在「非本人消息」上被激活,其中九个的脚本直接读取宿主机的环境变量文件。而主人对此的感知是:这些技能我都试过,没问题。他试过的确实没问题------他试的只是自己发起的那条路径。
二、机制剖析:常驻 Agent 的「触发面」模型
要理解首跑验收为什么不够,得先看清常驻网关与任务型 CLI 在结构上的根本差异。
任务型 CLI 是拉模式 :你不敲命令,什么都不会发生;触发源永远是你本人;会话结束,上下文销毁,技能加载留下的痕迹也随之消失。常驻网关是推模式:它持续监听外部事件,任何能触达渠道的东西------私聊消息、群聊消息、定时任务、webhook、甚至记忆系统自己的自动整理------都可能成为把技能推进上下文的推手。
text
任务型 CLI Agent(拉模式) 常驻网关 Agent(推模式)
┌───────────────────────┐ ┌───────────────────────────┐
入口 │ 你主动敲下命令 │ │ 渠道消息 / cron / webhook │
│ 触发源 = 你本人 │ │ 触发源 = 任何能发消息的人 │
│ │ │ 与任何定时事件 │
├───────────────────────┤ ├───────────────────────────┤
生命 │ 会话结束即销毁 │ │ 常驻数周数月 │
周期 │ 技能只在本次会话加载 │ │ 技能跨会话持续生效 │
├───────────────────────┤ ├───────────────────────────┤
权限 │ 继承当前目录权限 │ │ 继承宿主机全量权限 │
│ 会话即权限边界 │ │ API key / 文件 / shell 常驻 │
└───────────────────────┘ └───────────────────────────┘
这张图里有三个结构性差异,每一个都在放大技能的风险。
第一是触发源的枚举难度。任务型 Agent 的触发源集合是「你本人」,一个元素,天然封闭。常驻网关的触发源集合是开放的:群成员、陌生私信、定时器、上游服务的回调。你无法保证它们都是善意的,甚至无法保证它们都是人。
第二是技能生效的持续性。任务型会话里,技能描述注入一次、正文读一次,会话结束全部作废。常驻网关里,技能是长期挂载的:今天装的一个记账技能,三个月后还在影响每一次消息路由,而三个月后的你已经忘了它描述里那句「必要时可访问文件系统」是什么意思。
第三是权限的常驻暴露 。技能脚本默认与宿主进程同权限。任务型工具里这最多是一次会话内的暴露;常驻网关里,等于把这些权限 7×24 挂在公网渠道后面。Anthropic 工程团队在介绍 Agent Skills 的文章里,把技能的渐进式加载(描述常驻、正文按需、脚本直执行)描述为一种上下文经济学(参见 Equipping agents for the real world with Agent Skills)。这个设计在任务型场景是优雅的,但在事件驱动架构里恰好放大了问题:装载越自动,「谁在什么时候把什么装进了上下文」就越没人知道。
把三个差异合起来,可以提炼出本文的核心概念:任务型 Agent 的验收单位是「会话」,常驻 Agent 的验收单位是「触发面」。会话是一次性的、可枚举的;触发面是持续的、部分开放的。给常驻龙虾做技能验收,你必须先枚举所有能让技能进入上下文的事件路径,再逐条验证------这正是首跑验收天然做不到的事。
三、三种典型风险:常驻龙虾的技能病历
触发面画不出来,风险就会以三种形态找上门。以下三种在真实案例里出现频率最高,可以当成常驻 Agent 技能问题的「三大病历」。
病历一:静默触发。 某个带脚本的技能被一条无关消息意外激活。典型场景:家人在群里发了一句「今天天气真不错」,龙虾的天气技能不但被激活,还顺手注册了一个每天早上八点的定时播报------因为技能描述里写着「为用户提供天气服务时可以设置定时提醒」。这类事件的可怕之处在于它完全不报错:没有异常,没有告警,只在记忆文件里留下一行谁也不会去看的记录。等主人发现时,僵尸定时任务已经跑了两周。
静默触发还有一种更隐蔽的连锁形态:一个技能的输出恰好落在另一个技能的触发条件上。群里有人随手转发了一篇公众号文章,RSS 追踪技能把它存进了待读列表,摘要技能又对它生成了一段带链接的点评发回群里,群友回复链接又触发新一轮摘要------两个技能各自都在按设计工作,合起来却组成了一个没人要求过的自动回复循环。单技能首跑验收永远测不出这种组合行为,因为验收时你根本不会把两个技能的触发条件串起来想。
病历二:权限累积。 技能脚本与宿主同权限,意味着装一个技能就多一份对 .env 文件、文件系统、shell 的潜在访问。这不是理论风险:安全研究者发布的 ClawHavoc 报告在公开技能与工具仓库里识别出 1184 个恶意技能,累计安装量高达 24.7 万次;Snyk 的 ToxicSkills 报告进一步指出,超过三分之一的被检技能存在不同程度的安全风险。在任务型工具里,一次会话的暴露窗口是几分钟;在常驻网关里,这些技能是 7×24 站在你所有 API key 旁边的。两者的差距不是程度,是性质。
病历三:供应链漂移。 技能目录本质上是一棵没有 lockfile 的依赖树。技能作者更新了描述文件,触发条件就变了;更新了脚本,权限面就变了。没人会在技能自动更新后重新验证一遍------大多数人甚至不知道技能已经更新了。三个月前验收过的技能,如今可能已经是另一个行为体。供应链漂移把「装技能时的验证」变成了一个持续失效的承诺。
| 风险形态 | 典型触发路径 | 首跑验收能否覆盖 | 暴露窗口 |
|---|---|---|---|
| 静默触发 | 无关消息/事件误激活技能 | 否,首跑只测主动路径 | 单次触发,但可注册持久副作用 |
| 权限累积 | 技能脚本越权读写敏感资源 | 部分,仅当首跑恰好触发越权分支 | 7×24 常驻 |
| 供应链漂移 | 技能更新后行为变化 | 否,验收的是旧版本 | 更新后持续 |
三种病历的共同根源与首跑验收的局限是同一件事:验证的粒度错了。装技能时你验证的是「这个技能能不能完成任务」,而常驻系统要求你验证的是「这个技能在什么条件下被谁触发、能碰什么、坏了谁知道」。
四、验证方法:触发面审计与最小权限断言
与其在出事之后翻记忆文件,不如在装技能和养龙虾的过程中建立三道可执行的验证工序:触发面扫描、最小权限断言、行为回归。以下方法在我们的实践里跑通过完整闭环。
4.1 触发面扫描:让每条消息留下激活记录
第一步是构造一个消息样本集,模拟龙虾日常会收到的事件。样本分三类:正常闲聊 (期望:不激活任何带脚本的技能)、正常指令 (期望:激活目标技能)、诱导样本 (与技能描述擦边的表述,用来测触发边界的松紧)。把三类样本按真实比例混合------如果龙虾主要泡在群聊里,闲聊样本就占大头------然后逐条注入,记录每个样本实际激活了哪些技能。产出两个核心指标:误触发率 (闲聊样本激活了带脚本技能的比例)和漏触发率(指令样本没有激活目标技能的比例)。前者是安全指标,后者是可用性指标,两个都要看------把触发条件描述得足够生硬可以让误触发归零,代价是指令也唤不醒技能,那不是治理成功,是把龙虾治成哑巴。
扫描的落地关键在日志:注入样本前先打开技能加载追踪,确保每条消息对应「实际加载了哪些技能描述、读了哪些正文、执行了哪些脚本」的完整记录,再把它整理成「样本 × 技能」的激活矩阵存档。没有这份矩阵,所谓的扫描就只是「感觉没触发」;有了它,行为回归和周期审计才有可比对的基线。经验阈值可以参考:闲聊误触发率超过 5%,就该收紧对应技能的触发描述;诱导样本误触发率超过两成,这个技能要么降级要么绑定渠道。
4.2 最小权限断言:给技能目录做一次权限面体检
第二步是静态审计:扫描技能目录,解析每个技能的说明文档与脚本,提取其中的敏感操作------shell 执行、文件读写、网络请求、环境变量访问------对照你声明的 allowlist 生成权限面报告。下面是我们在用的审计脚本骨架:
python
# lobster_audit.py ------ OpenClaw 技能触发面与权限面审计脚本
import json, re
from pathlib import Path
SKILLS_DIR = Path("~/.openclaw/skills").expanduser()
SENSITIVE_PATTERNS = {
"shell": [r"child_process", r"\bexec\b", r"\bspawn\(", r"os\.system"],
"fs": [r"fs\.(read|write|append)", r"readFile", r"writeFile"],
"network": [r"fetch\(", r"http\.request", r"axios\.", r"net\.connect"],
"secret": [r"\.env", r"process\.env", r"api[_-]?key", r"token"],
}
ALLOWLIST = { # 每个技能声明的最小权限集(人工评审后填写)
"daily-report": {"fs": True, "network": True, "shell": False, "secret": False},
}
def audit_skill(skill_dir):
report = {"skill": skill_dir.name, "capabilities": {}, "overruns": []}
declared = ALLOWLIST.get(skill_dir.name, {})
for cap, patterns in SENSITIVE_PATTERNS.items():
hits = []
for f in skill_dir.rglob("*"):
if f.suffix in {".js", ".ts", ".py", ".sh", ".md"}:
text = f.read_text(encoding="utf-8", errors="ignore")
hits += [f"{f.name}:{m.start()}" for p in patterns
for m in re.finditer(p, text, re.IGNORECASE)]
report["capabilities"][cap] = len(hits)
if hits and not declared.get(cap):
report["overruns"].append(
f"未声明权限 {cap},却存在 {len(hits)} 处引用")
return report
results = [audit_skill(d) for d in SKILLS_DIR.iterdir() if d.is_dir()]
Path("audit_report.json").write_text(
json.dumps(results, ensure_ascii=False, indent=2), encoding="utf-8")
for r in results:
flag = "OVER-RUN" if r["overruns"] else "ok"
print(f"[{flag:>8}] {r['skill']}: "
f"{ {k: v for k, v in r['capabilities'].items() if v} }")
跑完这个脚本,你会得到一份「每个技能实际引用了什么 vs 你以为它需要什么」的对照表。实践中这份报告几乎总能查出意外:你以为只读天气的技能里有 fetch,你以为纯本地的技能里有 shell。查出来的项,要么补进 allowlist 并说明理由,要么直接删掉技能------没有第三种「先放着」的选项,因为「先放着」就是权限累积的开始。
4.3 行为回归:更新不算数,重跑才算数
第三步针对供应链漂移。任何技能更新后,用 4.1 的同一组消息样本重跑一遍,diff 前后两次的激活矩阵:有没有技能在新版本里被更多样本激活?有没有原本干净的技能开始引用敏感操作?把每次的激活矩阵和审计报告按版本归档,你就有了一条可回溯的行为时间线。龙虾是常驻系统,它的验证也必须是周期性的------建议把 4.2 的静态审计挂进龙虾自己的 cron,每周一跑,报告发给自己。让龙虾审计自己养的技能,是这类系统最自然的闭环。
4.4 三个实施陷阱
这套方法落地时有三个坑。一是审计样本全是自己的语气 :龙虾在群聊里收到的话和你在终端里敲的话风格完全不同,用自己口吻构造的样本测出来的误触发率会严重低估,样本必须混入真实的群聊语料。二是只在清醒时段审计 :大量技能会注册定时任务,半夜跑、清早跑,白天审计根本观察不到;触发面扫描必须覆盖 cron 路径,方法是把样本集扩成「消息样本 + 定时任务快照」两份。三是审计一次就束之高阁:常驻系统的安全姿势是持续过程,第一次审计报告再漂亮,三个月后也只是一份过期文件。
五、实战案例:一台 40 技能龙虾的体检与瘦身
用一次真实的审计把方法串起来。一位朋友的龙虾运行了半年,技能目录膨胀到四十多个,症状是「偶尔在群里自言自语,记忆文件里多出一些没人交代过的任务」。
审计分两步。静态权限体检先出结果:四十多个技能里,九个的脚本直接引用了宿主机的环境变量路径或 API key 相关模式,十七个存在 shell 执行引用,三个已经半年没有更新、其描述与实际行为明显不符(作者中途改过功能,README 还是旧的)。触发面扫描随后补上另一半:用两周的真实群聊语料加三十条诱导样本回放,十七个技能会在「非本人消息」上被激活,其中一个记账技能被一句「这月花销有点大」触发,还试图读取整月的银行导出文件。
整改方案不是一刀切删除,而是分四级处理:保留 十二个经得起审计的技能;降级 六个------把 shell 与 secret 权限从脚本里摘除或改为只读;绑定渠道 四个高风险技能,限制为「仅主人私聊可触发」,群聊消息一概不响应;移除其余的僵尸技能与越权技能。最后给龙虾挂上每周一的自检 cron,自动重跑静态审计并把 diff 汇总成一句话日报。
两周后的数据:误触发从每天三到五次降到两周合计一次(那次是诱导样本本身表述模糊,属可接受边界),权限面引用总数从三十一处降到九处,且每一处都有 allowlist 声明与理由。主人最直观的感受反而是「龙虾变聪明了」------因为上下文里不再有十几个技能描述在互相干扰,消息路由明显变准。
值得一提的还有这次审计的时间成本:静态体检脚本当天晚上就跑完,触发面扫描因为要等两周真实语料积攒,前后花了三个晚上的人工整理,而龙虾本身没有下线过。这个投入和它保护的暴露面相比几乎可以忽略------毕竟这台龙虾背后是宿主机上全部的 API key、一份银行导出和一整个家庭群的聊天上下文。安全预算永远该和被保护资产的价值对齐,而不是和「出事概率很低」的侥幸对齐。
这个案例最有价值的启示是:审计的目标不是把技能删到最少,而是让每一个留下的技能都有被验证过的存在理由。瘦身只是审计的副产品,真正的产出是那份「谁、在什么条件下、能碰什么」的边界清单。
六、总结与展望
回到开头的问题:常驻龙虾的技能,装得越多越好吗?本文的答案是------装得越多,触发面越宽,验证义务越重;没有配套验证的技能数量增长,是在用未来的事故换取现在的便利。
三条原则值得写进每一台龙虾的运维手册:验收单位从「会话」换成「触发面」,枚举所有能把技能推进上下文的事件路径;权限从「继承」换成「声明」,每个技能的敏感操作必须有 allowlist 背书;审计从「一次性」换成「周期性」,让技能更新和月度体检一样成为例行公事。
展望接下来的一年,常驻个人 Agent 的技能治理大概率会向移动端 App 的权限模型靠拢:安装时声明权限、运行时按需弹窗、事后可随时撤销。协议层与运行时终会把这些机制内置进来。但在那一天到来之前,触发面审计是你唯一能依赖的防线------而且即便平台内置了治理,用自己的样本集实测出触发边界这件事,依然没人能替你做。
而这一切背后的主线始终没变:技能的真实风险与真实能力一样,都不该由它的自我描述决定,而应该由你在自己的环境里实测出的证据决定。 README 写得再清爽的技能,描述得再无害的触发条件,都可能在你的群聊语料、你的文件布局、你的定时任务组合下越界。验证真实行为,而不是轻信自我描述------这既是给龙虾装技能的规矩,也是所有常驻自动化系统活下去的前提。
如果你也在养自己的常驻 Agent,想知道别人是怎么组织和验证技能的,可以去看看 DeepSkill 的作品展厅,那里汇集了大量带着实战痕迹的技能作品,比任何宣传语都更接近「验证过」三个字。
关于 Deep Skill Finder
Deep Skill Finder 是一个面向 AI Agent 时代的技能发现与评测平台,致力于回答一个核心问题:如何验证 Agent/Skill 的真实能力,而不是轻信自我描述。平台通过结构化的能力画像、真实任务实测数据与社区反馈机制,帮助开发者从海量技能中筛选出真正可靠的那一批。
获取方式:在主流 Agent 客户端中搜索 Deep Skill Finder 相关技能即可安装使用;也可以通过技能市场、社区推荐等渠道获取。安装后,你可以用它来检索、对比、评测各类 Agent Skill,为自己的工作流挑选经过验证的能力组件。选技能如同选队友,口碑要看实战记录,而不是自我介绍。