智能体技能(Skills)安全扫描工具
1. 前言
在大模型技术狂飙突进的今天,以 OpenClaw(国内开发者常称之为“小龙虾”)为代表的 AI 智能体(Agent)框架正以前所未有的速度重塑人机交互的范式。开发者仅需几句提示词(Prompt)和几个技能插件(Skills),就能快速构建出功能强大的 AI 助手。然而,这种“乐高式”的敏捷开发在极大降低技术门槛的同时,也打开了潘多拉的魔盒。Skills 作为大模型能力的延伸,赋予了 AI 操作文件系统、调用外部 API 甚至执行系统命令的权力。一旦这些“技能”本身存在安全隐患,AI 就不再是得力的助手,而可能沦为攻击者手中的利刃。因此,对大模型 Skills 进行严格的安全检查,已不再是锦上添花的选项,而是关乎数据隐私、系统稳定乃至业务存亡的底线要求。
下面将介绍三种常见的技能安全扫描工具。通过这三种工具的设计,我们可以了解如何构建一个健壮的技能安全扫描工具。
2. skill-security-scan
skill-security-scan 是一个命令行工具,用于扫描和检测 Claude Skills 的安全风险。在安装第三方 Skills 前,使用此工具进行安全审查,用于防止恶意代码窃取数据或破坏系统。
项目由 WellAlly Technology 开发者发起并维护,致力于为开发者社区提供安全可靠的工具。
2.1. 检查技术
主要通过模式适配(正则表达式)的配置来进行技能扫描。
- 例如:skill-security-scan/src/rules/command.py
class SystemCommandRule(SecurityRule):
"""系统命令规则"""
def match(self, content: str) -> List[Match]:
"""
匹配系统命令执行模式
Args:
content: 文件内容
Returns:
List[Match]: 匹配结果
"""
matches = []
lines = content.split('\n')
for i, line in enumerate(lines, 1):
# 检测 os.system
if re.search(r'\bos\.system\s*\(', line):
matches.append(Match(
line=i,
pattern=line.strip(),
confidence=0.80
))
# 检测 subprocess.call/shell=True
if re.search(r'subprocess\.(call|run|Popen).*shell\s*=\s*True', line):
matches.append(Match(
line=i,
pattern=line.strip(),
confidence=0.85
))
# 检测 exec 函数
if re.search(r'\bexec\s*\(', line):
matches.append(Match(
line=i,
pattern=line.strip(),
confidence=0.75
))
return matches
可以在:reference/doc/skills/skill_security/Skill-Security-Scanner_config.yaml 中查看其他检查的正则配置。
2.2. 检查的缺陷
- 检测规则:
- 🔴 CRITICAL (严重)
- NET001: 外部网络请求到非官方域名
- FILE001: 访问敏感文件(SSH 密钥、.env 等)
- FILE002: 危险文件操作(rm -rf /, chmod 777)
- CMD001: 执行危险系统命令(sudo, dd)
- INJ001: 代码注入模式
- INJ003: 后门植入
- 🟡 WARNING (警告)
- CMD002: 系统命令调用(os.system, subprocess)
- INJ002: 动态代码执行(eval, exec)
- DEP001: 全局包安装
- DEP002: 强制版本覆盖
- 🔵 INFO (提示)
- 代码混淆模式
- 隐藏命令
- 🔴 CRITICAL (严重)
3. anthropics Skill Security Scanner
skill-security-analyzer v2.0 是一个综合性安全扫描器,旨在检测 Claude Code skills 中的恶意代码模式。拥有 40+ 检测模式和在其测试套件上 100% 的检测率,这个元技能代表了 Claude Skills 生态系统的关键防御层——保护用户免受命令注入、凭证窃取、数据泄露和复杂的逃避技术的侵害。
3.1. 检查流程

3.2. 检查技术
3.2.1. 检查的核心技术是模式适配(正则匹配)。
- 例如:
def _check_indirect_execution(self, content: str, file_path: Path):
"""Detect indirect code execution via getattr, __import__, etc."""
patterns = [
# getattr patterns
(r'getattr\s*\([^,]+,\s*[\'"][^\'"]*(?:system|exec|eval|compile|open)[^\'"]*[\'"]',
self.CRITICAL, "getattr accessing dangerous function names"),
# String concatenation to build function names
(r'getattr\s*\([^,]+,\s*[^)]*\+[^)]*\)',
self.CRITICAL, "Dynamic function name via string concatenation"),
# __builtins__ manipulation
(r'__builtins__\s*\[|getattr\s*\(__builtins__',
self.CRITICAL, "__builtins__ manipulation"),
# Class traversal (sandbox escape)
(r'__class__\.__base__\.__subclasses__',
self.CRITICAL, "Class hierarchy traversal (sandbox escape pattern)"),
# Dictionary-based execution
(r'\{[^}]*[\'"](?:exec|eval|system)[\'"][^}]*\}\[',
self.CRITICAL, "Dictionary-based function call obfuscation"),
# Lambda with dangerous functions
(r'lambda[^:]*:\s*(?:exec|eval|__import__|getattr)',
self.HIGH, "Lambda wrapping dangerous operations"),
# importlib with concatenation
(r'importlib\.import_module\s*\([^)]*\+[^)]*\)',
self.CRITICAL, "Dynamic module import with string manipulation"),
]
3.2.2. yaml.safe_load 检查 YAML 中的问题
- 例如:
# Second: Actually parse YAML safely
try:
parsed = yaml.safe_load(frontmatter_text)
# Check for suspicious keys recursively
if isinstance(parsed, dict):
self._check_yaml_keys_recursive(parsed, "SKILL.md frontmatter")
except yaml.constructor.ConstructorError as e:
self.findings.append({
"severity": self.CRITICAL,
"category": "YAML Injection",
"title": "YAML attempts to construct Python objects",
"description": f"Error: {str(e)}",
"location": "SKILL.md frontmatter",
"impact": "Arbitrary code execution via YAML deserialization"
})
3.3. 检查的主要缺陷
| 编号 | CWE编号 | cwe描述 | 问题 | 举例 |
|---|---|---|---|---|
| 1 | CWE-913 | 对动态管理代码资源的控制不当 | 间接执行 | getattr(os, 'system') |
| 2 | CWE-78 | 操作系统命令注入 | 命令注入 | os.system() |
| 3 | CWE-78 | 操作系统命令注入 | Shell注入 | subprocess.run(['/bin/bash', '-c']) |
| 4 | CWE-502 | 不可信数据的反序列化 | YAML注入 | !!python/object |
| 5 | CWE-522 | 不充分的凭证保护机制 | 凭证窃取 | open('.ssh/id_rsa') |
| 6 | CWE-749 | 泄露危险的方法或函数 | 沙箱逃逸 | __class__.__bases__ |
| 7 | CWE-1106 | 符号常量使用不足 | 拼写错误/仿冒 | import request vs requests |
| 8 | CWE-327 | 使用已被攻破或存在风险的密码学算法 | 高级编码混淆 | codecs.decode(..., 'rot_13') |
| 9 | CWE-506 | 内嵌恶意代码 | 逻辑炸弹/时间炸弹 | if datetime.now().day == |
| 10 | CWE-74 | 输出中的特殊元素转义处理不恰当(注入) | 环境变量注入 | os.environ['LD_PRELOAD'] |
| 11 | CWE-913 | 动态管理代码资源的控制不恰当 | 导入钩子劫持 | sys.meta_path.insert |
4. Cisco Skill Scanner
Cisco Skill Scanner是一款针对 AI 代理技能的安全扫描器。能够检测提示注入、数据泄露和恶意代码模式。结合基于模式的检测 (YAML + YARA)、 作为判断的 LLM 和行为数据流分析 ,最大化对潜在威胁的检测覆盖率,同时最小化误报。
支持按照 Agent Skills 规范的 OpenAI Codex Skills 和 Cursor Agent Skills 格式。
架构展示了一个混合式(Hybrid)安全扫描框架。它不仅仅依赖单一的 LLM,而是采用了 “传统静态分析 + 威胁情报 + LLM 深度推理” 的组合拳策略。
4.1. 工具特点
- 多引擎检测:
采用多中分析方式对Skill进行检测,包括:静态分析、行为数据流、大型语言模型语义分析和基于云的扫描,实现分层的覆盖; - 误报过滤:
元分析仪显著降低噪声,同时保持检测能力; - CI/CD 集成:
用于 GitHub 代码扫描的 SARIF 输出, 可重复使用的 GitHub Actions 工作流程 ,构建失败的退出码。 - 预提交钩子:
标准的预提交框架集成,用于每次提交前扫描技能; - 可扩展性:
用于自定义分析器的插件架构,便于自定义的分析器和扩展。
4.2. Skill Scanner 架构
流程图详细描绘了 Skill 扫描器(Skill Scanner) 的核心工作流程。流程展示了一个从数据加载、多阶段分析(结合传统静态分析与 LLM 大模型分析)、后处理到最终报告生成的完整自动化流水线。

下面是各个阶段的说明:
4.2.1. 加载与预处理
目标: 将原始的技能文件转化为系统可处理的标准数据模型。
加载: 通过 SkillLoader.load_skill() 启动,读取原始的技能包或文件。
提取: ContentExtractor.extract_skill_archives() 负责解压或提取归档文件中的具体内容。
建模: 将提取出的碎片化文件合并,构建成统一的 Skill 模型,为后续分析做准备。
4.2.2. 阶段一:非 LLM 分析器
目标: 使用传统的、确定性的方法进行快速扫描和基础分析。这一阶段包含多个并行或串联的分析模块,不依赖大语言模型,因此速度较快且成本较低。
主要包含以下分析器:
- 静态分析器
检查代码结构和文本内容。静态分析仪是主要的确定性检测引擎。它结合了 YAML 签名匹配、YARA-X 规则扫描、基于 Python 的检查和文件库存分析,无需外部服务即可检测安全威胁。 - 字节码分析器
深入到底层指令集进行分析。 - 管道分析器
检查工作流或数据处理管道的逻辑。 - 行为分析器
模拟或推断技能的运行时行为。行为分析仪使用静态代码分析、AST 解析和数据流跟踪,检测需要理解代码行为和数据流的威胁。与基于模式的检测不同,它通过跟踪数据在代码中的流动,以识别多步攻击。 - VirusTotal 分析器
利用外部威胁情报库(VirusTotal)检查文件哈希或内容的恶意特征。 - AI 防御分析器
专门针对 AI 安全(如提示注入、越狱)的检测。 - 触发器分析器
分析技能被激活的条件和逻辑。
4.2.3. 阶段二:带增强的 LLM 分析器
LLM 和元分析仪被推迟到第二阶段,以便从第一阶段结果中获得丰富的上下文。
目标: 利用大语言模型的推理能力进行深度语义分析,并结合第一阶段的发现。
上下文增强: 这是一个关键步骤。系统会将 阶段一 产生的分析结果(如静态分析警告、VirusTotal 标记等)构建成“增强上下文”。
LLM 分析器: 结合增强上下文,让 LLM 对技能进行更深层次的理解和判断,减少幻觉,提高准确性。
元分析器: 可能用于分析技能的元数据或进行更高层级的逻辑校验。
4.2.4. 后处理
目标: 对原始分析结果进行清洗、优化和标准化,以确保报告的质量和可操作性。
在分析和报告之间,扫描仪执行一系列规范化和策略执行步骤:
- 抑制误报: 如果 VirusTotal 验证了某些二进制文件是安全的,则抑制相关的发现(减少噪音)。
- 规则执行: 强制执行用户或系统配置的“禁用规则”。
- 严重性调整: 根据特定策略覆盖默认的严重程度评级。
- 评分计算: 计算“可分析性分数”,评估该技能被分析的程度和质量。
- 生成发现: 基于评分生成具体的分析发现项。
- 标准化与去重: 统一格式并去除重复的报警。
- 元数据注释: 添加共现元数据(即哪些问题经常一起出现)。
- 策略指纹: 附加策略指纹,用于追踪本次扫描所依据的策略版本。
4.2.5. 输出
目标: 将最终结果呈现给用户或集成到其他系统中。
构建结果: 组装最终的 ScanResult 对象。
多格式报告,支持多种输出格式,满足不同需求:
| 输出格式 | 报告器 | 注释 |
|---|---|---|
| 摘要 | 内置 | 人类可读的控制台输出 |
| json | JSONReporter | 机器可读,支持漂亮的选项 |
| markdown | MarkdownReporter | 支持详细选项 |
| 表格 | TableReporter | 表格控制台输出 |
| sarif | SARIFReporter | 静态分析结果交换格式 |
| html | HTMLReporter | 样式化 HTML 报告 |
4.3. 架构的特点
- 优点: 结合了传统工具的准确性与速度(阶段一)以及 LLM 的语义理解能力(阶段二)。
- 流程严谨: 特别强调了后处理环节(去重、抑制误报),这对于降低安全工具的误报率至关重要。
4.4. 静态分析器
源代码 → 解析器 → 控制流图 → 数据流分析 → 污点追踪
↓ ↓
语义分析 过程间分析

注: 代码中只给出较为简单的 python 的静态分析器,特别是数据流需要进一步的完善。
5. 总结
- 文章介绍了三种不同的Skill安全扫描工具设计。其中前两种整体设计上还是采用传统的静态检查方式:基于模式适配(正则表达式)的方式完成 skill 的安全检查;
- Cisco Skil Scanner 给出了与传统检查工具不同的检查方式,静态分析(多检查器集成)+ LLM 的方式 + 误报消减。这种模式将成为未来的一段时间(直到完全被LLM取代)安全检查工具的主要设计模式。
- 点赞
- 收藏
- 关注作者
评论(0)