The create-namespace dialog validates slugs client-side before sending the request, and its pattern was still ASCII-only. SlugValidator has accepted Unicode letters, numbers and symbols since #196, so the form rejected slugs the server accepts. Signed-off-by: D41910 <158550716+D41910@users.noreply.github.com>
15 KiB
自定义静态分析规则
概述
Cisco skill-scanner 的静态分析引擎包含两种规则类型:
- Regex 规则(
signatures.yaml):基于正则表达式的模式匹配,按行扫描 - YARA 规则(
*.yara):基于 YARA 引擎的多模式匹配,支持跨行和组合条件
两种规则都打包在 cisco-ai-skill-scanner 的 Python 包内部,Scanner HTTP API 不提供运行时加载外部规则的接口。要注入自定义规则,需要在 Docker 构建或启动阶段覆盖包内文件。
包内规则路径
/usr/local/lib/python3.11/site-packages/skill_scanner/
├── data/
│ ├── rules/
│ │ └── signatures.yaml # Regex 规则定义
│ └── yara_rules/
│ ├── code_execution_generic.yara
│ ├── command_injection_generic.yara
│ ├── credential_harvesting_generic.yara
│ ├── prompt_injection_generic.yara
│ ├── ... (共 13 个 .yara 文件)
│ └── tool_chaining_abuse_generic.yara
└── core/
└── rules/
├── patterns.py # RuleLoader - 加载 signatures.yaml
└── yara_scanner.py # YaraScanner - 加载 *.yara 文件
加载逻辑:
RuleLoader读取data/rules/signatures.yaml,逐条编译正则表达式YaraScanner读取data/yara_rules/目录下所有.yara文件,编译为 YARA 规则集
两个加载器都支持通过构造函数传入自定义路径,但 HTTP API 层没有暴露此参数。
注入自定义规则的方式
方案 A:Docker 卷挂载(开发环境推荐)
在 docker-compose.yml 中将本地规则目录挂载到容器内,覆盖包内文件:
# docker-compose.yml
services:
skill-scanner:
build: ./scanner
ports:
- "8000:8000"
volumes:
# 追加自定义 Regex 规则(覆盖原有 signatures.yaml)
- ./scanner/rules/signatures.yaml:/usr/local/lib/python3.11/site-packages/skill_scanner/data/rules/signatures.yaml:ro
# 追加自定义 YARA 规则(覆盖整个 yara_rules 目录)
- ./scanner/rules/yara/:/usr/local/lib/python3.11/site-packages/skill_scanner/data/yara_rules/:ro
优点:改规则后重启容器即可生效,不需要重新构建镜像
缺点:升级 scanner 版本时,官方新增的规则不会自动包含进来,需要手动合并
方案 B:Dockerfile COPY(生产环境推荐)
在 Dockerfile 构建阶段把自定义规则 COPY 进镜像:
FROM python:3.11-alpine
WORKDIR /app
RUN apk add --no-cache --virtual .build-deps gcc musl-dev libffi-dev && \
pip install --no-cache-dir cisco-ai-skill-scanner && \
apk del .build-deps && \
addgroup -S app && \
adduser -S app -G app && \
mkdir -p /tmp/skillhub-scans && \
chown app:app /tmp/skillhub-scans
# 覆盖 Regex 规则
COPY rules/signatures.yaml /usr/local/lib/python3.11/site-packages/skill_scanner/data/rules/signatures.yaml
# 覆盖 YARA 规则目录
COPY rules/yara/ /usr/local/lib/python3.11/site-packages/skill_scanner/data/yara_rules/
USER app
EXPOSE 8000
CMD ["skill-scanner-api", "--host", "0.0.0.0", "--port", "8000"]
优点:规则随镜像版本管理,可追溯、可回滚
缺点:每次改规则都需要重新构建镜像
方案 C:追加而非覆盖(保留官方规则 + 自定义扩展)
如果希望保留官方规则并追加自定义规则:
Regex 规则:将官方 signatures.yaml 的内容复制出来,在末尾追加自定义规则后整体覆盖。
YARA 规则:官方的每个 .yara 文件是独立的,只需把自定义 .yara 文件放入同一目录即可。YARA 加载器会自动扫描目录下所有 .yara 文件。
推荐的目录结构:
scanner/
├── Dockerfile
├── rules/
│ ├── signatures.yaml # 完整的 Regex 规则(官方 + 自定义)
│ └── yara/
│ ├── code_execution_generic.yara # 官方规则(保留)
│ ├── command_injection_generic.yara # 官方规则(保留)
│ ├── credential_harvesting_generic.yara # 官方规则(保留)
│ ├── ... # 其他官方规则
│ └── skillhub_custom.yara # ← 自定义 YARA 规则
└── README.md
Regex 规则定义方法(signatures.yaml)
格式
- id: RULE_UNIQUE_ID # 唯一标识符,大写下划线命名
category: <threat_category> # 威胁分类(见下方枚举)
severity: <severity_level> # 严重级别(见下方枚举)
patterns: # 正则表达式列表(匹配任一即触发)
- "regex_pattern_1"
- "regex_pattern_2"
exclude_patterns: # 排除模式(可选,匹配则跳过)
- "safe_pattern"
file_types: # 适用的文件类型(见下方枚举)
- python
- bash
description: "规则描述" # 检测到时显示的说明
remediation: "修复建议" # 建议的修复方式
可用的 category 值
| category | 说明 |
|---|---|
prompt_injection |
Prompt 注入和指令覆盖 |
command_injection |
命令和代码注入 |
data_exfiltration |
数据泄露和隐私违规 |
unauthorized_tool_use |
未授权工具和权限滥用 |
obfuscation |
代码混淆和恶意软件指标 |
hardcoded_secrets |
硬编码密钥和凭证泄露 |
social_engineering |
社会工程和误导性元数据 |
resource_abuse |
资源滥用和拒绝服务 |
policy_violation |
策略违规 |
可用的 severity 值
| severity | 说明 |
|---|---|
CRITICAL |
严重 — 明确的恶意行为 |
HIGH |
高危 — 高风险安全问题 |
MEDIUM |
中危 — 需要关注的可疑行为 |
LOW |
低危 — 轻微问题或建议 |
INFO |
信息 — 仅供参考 |
可用的 file_types 值
| file_types | 匹配的文件扩展名 |
|---|---|
python |
.py |
bash |
.sh, .bash, .zsh |
markdown |
.md |
manifest |
SKILL.md(仅扫描 frontmatter) |
binary |
二进制文件 |
示例:自定义 Regex 规则
# ============================================================================
# 自定义规则:SkillHub 特定检测
# ============================================================================
# 检测使用 SkillHub 内部 API 的可疑行为
- id: SKILLHUB_INTERNAL_API_ACCESS
category: data_exfiltration
severity: HIGH
patterns:
- "skillhub\\.internal"
- "/api/v1/admin"
- "X-Internal-Token"
file_types: [python, bash]
description: "Skill attempts to access SkillHub internal APIs"
remediation: "Skills should not access internal management APIs"
# 检测试图修改其他技能包的行为
- id: SKILLHUB_SKILL_TAMPERING
category: unauthorized_tool_use
severity: CRITICAL
patterns:
- "skillhub[_-]storage"
- "/tmp/skillhub-scans"
- "skill_versions.*UPDATE"
file_types: [python, bash]
description: "Skill attempts to tamper with SkillHub storage or other skills"
remediation: "Remove code that accesses SkillHub internal storage"
# 检测过大的依赖安装
- id: SKILLHUB_EXCESSIVE_DEPS
category: resource_abuse
severity: MEDIUM
patterns:
- "pip install .{200,}"
- "requirements\\.txt.*\\n.*torch"
- "pip install.*tensorflow"
exclude_patterns:
- "# optional"
- "# dev only"
file_types: [python, bash]
description: "Skill installs very large dependencies that may abuse resources"
remediation: "Use lightweight alternatives or document why large dependencies are needed"
正则表达式语法说明
- 使用 Python
re模块语法 (?i)— 不区分大小写\\b— 单词边界(?<!...)— 反向否定前瞻,如(?<!re\\.)\\bcompile匹配compile()但排除re.compile()[^)]*— 匹配括号内的任意内容- 每条 pattern 独立匹配,命中任意一条即触发该规则
YARA 规则定义方法
格式
rule rule_name {
meta:
author = "YourTeam"
description = "规则描述"
classification = "harmful" // harmful | suspicious | info
threat_type = "THREAT TYPE" // 大写,用于分类展示
strings:
// 定义要匹配的字符串模式
$pattern_name = /正则表达式/i // 正则(i=不区分大小写)
$literal_str = "固定字符串" // 精确匹配
$hex_pattern = { 48 65 6C 6C } // 十六进制匹配
// 排除模式
$safe_pattern = /安全模式/
condition:
// 布尔逻辑组合
not $safe_pattern and
(
$pattern_name or
($literal_str and $hex_pattern)
)
}
meta 字段说明
| 字段 | 必填 | 说明 |
|---|---|---|
author |
是 | 规则作者 |
description |
是 | 规则描述,检测到时显示 |
classification |
是 | harmful(有害)、suspicious(可疑)、info(信息) |
threat_type |
是 | 威胁类型标签(大写),如 CODE EXECUTION、CREDENTIAL HARVESTING |
strings 模式类型
strings:
// 1. 正则表达式(最常用)
$regex = /pattern/i // i = 不区分大小写
$regex2 = /multi\nline/s // s = 跨行匹配
// 2. 精确字符串
$text = "exact match" // 区分大小写
$nocase = "match" nocase // 不区分大小写
$wide = "match" wide // 宽字符(UTF-16)
// 3. 十六进制模式
$hex = { E8 ?? ?? ?? FF } // ?? = 通配符
$hex2 = { E8 [2-4] FF } // [2-4] = 2到4字节通配
condition 逻辑运算
condition:
// 布尔运算
$a and $b // 同时匹配
$a or $b // 匹配任一
not $a // 不匹配
($a or $b) and not $c // 组合
// 计数
#a > 3 // $a 出现超过 3 次
any of ($pattern*) // 任一 $pattern* 匹配
all of ($required*) // 所有 $required* 都匹配
2 of ($a, $b, $c) // 三个中匹配任意两个
// 文件大小
filesize < 1MB // 文件小于 1MB
示例:自定义 YARA 规则
将以下内容保存为 scanner/rules/yara/skillhub_custom.yara:
//////////////////////////////////////////
// SkillHub 自定义检测规则
// 检测针对 SkillHub 平台的特定威胁
//////////////////////////////////////////
rule skillhub_namespace_abuse {
meta:
author = "SkillHub Security"
description = "Detects attempts to manipulate SkillHub namespaces or escalate privileges"
classification = "harmful"
threat_type = "PRIVILEGE ESCALATION"
strings:
// 尝试访问其他命名空间
$ns_traversal = /namespace[_\-]?id\s*=\s*['\"][^'\"]+['\"]/i
$ns_override = /X-Namespace-Override/i
// 尝试伪造身份
$mock_user = /X-Mock-User-Id/i
$admin_escalation = /role\s*=\s*['\"](admin|super_admin)['"]/i
// 排除测试代码
$test_file = /def\s+test_/
$test_import = /import\s+pytest/
condition:
not $test_file and
not $test_import and
(
$ns_traversal or
$ns_override or
$mock_user or
$admin_escalation
)
}
rule skillhub_scan_evasion {
meta:
author = "SkillHub Security"
description = "Detects attempts to evade security scanning"
classification = "harmful"
threat_type = "SCAN EVASION"
strings:
// 检测文件在扫描后执行的延迟加载
$delayed_import = /importlib\.import_module\s*\(\s*[a-z_]+\s*\)/i
$dynamic_exec = /getattr\s*\(\s*__import__/i
// 检测条件性恶意代码(仅在非扫描环境执行)
$env_check_scanner = /os\.environ\.get\s*\(\s*['"]SCANNER/i
$env_check_sandbox = /os\.environ\.get\s*\(\s*['"]SANDBOX/i
// 排除合法用途
$legitimate_plugin = /plugin_loader|extension_manager/i
condition:
not $legitimate_plugin and
(
($delayed_import and $env_check_scanner) or
($dynamic_exec and $env_check_sandbox) or
($delayed_import and $dynamic_exec)
)
}
测试自定义规则
验证 Regex 规则语法
# 在容器内验证 signatures.yaml 能否被正确解析
docker exec skillhub-skill-scanner-1 python3 -c "
import yaml
with open('/usr/local/lib/python3.11/site-packages/skill_scanner/data/rules/signatures.yaml') as f:
rules = yaml.safe_load(f)
print(f'Loaded {len(rules)} rules')
for r in rules:
print(f\" {r['id']} [{r['severity']}] {r['category']}\")
"
验证 YARA 规则语法
# 在容器内验证所有 .yara 文件能否被编译
docker exec skillhub-skill-scanner-1 python3 -c "
import yara
from pathlib import Path
rules_dir = Path('/usr/local/lib/python3.11/site-packages/skill_scanner/data/yara_rules')
for f in sorted(rules_dir.glob('*.yara')):
try:
yara.compile(filepath=str(f))
print(f' OK: {f.name}')
except yara.SyntaxError as e:
print(f' FAIL: {f.name} -> {e}')
"
端到端测试
# 创建包含可疑代码的测试技能包
mkdir -p /tmp/test-custom-rule
cat > /tmp/test-custom-rule/SKILL.md << 'EOF'
---
name: test-custom
description: A test skill for custom rule validation
version: 1.0.0
---
This is a test.
EOF
cat > /tmp/test-custom-rule/main.py << 'EOF'
import os
# 这段代码应触发自定义规则
mock_header = "X-Mock-User-Id: admin"
EOF
cd /tmp/test-custom-rule && zip -r /tmp/test-custom.zip .
# 提交扫描
curl -s -X POST http://localhost:8000/scan-upload \
-F "file=@/tmp/test-custom.zip" | python3 -m json.tool
注意事项
-
版本升级:升级
cisco-ai-skill-scanner时,官方规则会被覆盖。使用方案 A(卷挂载)时需手动合并新规则;使用方案 B(Dockerfile COPY)时需在 Dockerfile 中重新 COPY。 -
规则 ID 唯一性:Regex 规则的
id字段必须全局唯一。建议自定义规则使用SKILLHUB_前缀避免与官方规则冲突。 -
YARA 规则命名:YARA 文件名作为 namespace,
rule名称必须全局唯一。建议自定义规则文件使用skillhub_前缀。 -
性能影响:正则表达式过于复杂或 YARA 规则过多会增加扫描时间。建议定期评估规则数量和扫描耗时。
-
误报管理:新增规则后应用测试技能包验证,关注
exclude_patterns(Regex)和condition中的排除逻辑(YARA),避免误报。