关于 security-scanner
security-scanner 是用于检查 Claude Code 插件和多种 Agent 技能的安全扫描技能,面向需要审查本地内容或公开 GitHub 仓库的用户。它会分析可执行文件和自然语言指令,并支持按配置、范围及可信来源筛选扫描目标。
主要功能
- 01扫描插件与技能
- 02检查公开 GitHub 仓库
- 03分析代码和自然语言指令
- 04按用户级或项目级限定范围
- 05配置目标 Agent 与可信来源
- 06生成安全报告
适用场景
- 01审查安装的插件和技能
- 02扫描 GitHub 上的技能目录
- 03检查脚本中的危险命令
- 04依据可信名单跳过目标
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ hiroro-work/ claude-plugins --skill security-scanner安装后在 Claude Code 中输入/security-scanner确认已加载。
附带文件.claude-plugin/plugin.jsonREADME.md
详细介绍
安全扫描器
用法
/security-scanner # Scan all (plugins + skills)
/security-scanner --user # Scan user-level only (~/.claude/)
/security-scanner --project # Scan project-level only (.claude/)
/security-scanner --all # Scan ALL (ignore trusted sources and self-exclusion)
/security-scanner <url> # Scan from GitHub URL (public repos only)
/security-scanner --url <url> # Same as above (explicit form)
扫描流程
步骤 1:加载设置
在以下位置搜索 security-scanner.local.md:
- 项目级:
.claude/security-scanner.local.md - 用户级:
~/.claude/security-scanner.local.md
优先级规则:
- 如果两个文件都存在,仅使用项目级设置(项目级优先)
- 如果只有一个文件存在,则使用该文件
- 如果两个文件都不存在,则使用默认设置
从选定的文件中提取:
- YAML frontmatter 中的
report_language - YAML frontmatter 中的
target_agents列表 - YAML frontmatter 中的
trusted_marketplaces列表 - YAML frontmatter 中的
trusted_plugins列表 - YAML frontmatter 中的
trusted_skills列表
默认值(未指定时):
report_language:ja(日语)target_agents:["claude"]trusted_marketplaces:[]trusted_plugins:[]trusted_skills:[]
验证:
report_language:接受任何字符串值(AI 将使用该语言生成报告)target_agents只能包含有效的 Agent ID:claude、codex、gemini、agents- 无效的 Agent ID 将被忽略,并发出警告
错误处理:
- 如果文件存在但 YAML 语法无效,请警告用户并使用默认设置继续(不要中止扫描)
步骤 2:确定范围
检查参数以确定扫描内容:
位置筛选条件:
- 未指定位置标志:扫描所有已配置 Agent 的用户级和项目级位置
--user:仅扫描target_agents中所有 Agent 的用户级路径--project:仅扫描target_agents中所有 Agent 的项目级路径
URL 检测(优先级最高):
- 如果明确提供了
--url <url>→ 转到步骤 2-URL - 如果任一参数以
https://github.com/或http://github.com/开头 → 视为 URL,转到步骤 2-URL - 如果任一参数以
https://或http://开头,但不是github.com→ 错误:“不支持的主机:{host}。目前仅支持 github.com。”
特殊模式(未提供 URL 时):
--all:扫描所有内容(完全跳过步骤 4 的筛选)
步骤 2-URL:GitHub URL 扫描
如果提供了 URL(通过 --url 或自动检测到),请改为遵循此流程,而不是步骤 3–4。
步骤 2-URL-1:解析 URL
解析 GitHub URL 以提取所有者、仓库、分支、路径,并确定扫描类型:
URL 模式:
- 目录:
https://github.com/{owner}/{repo}[/tree/{branch}/{path}] - 单个文件:
https://github.com/{owner}/{repo}/blob/{branch}/{path}.md
- 验证主机是否为
github.com- 如果不是:错误:“不支持的主机:{host}。目前仅支持 github.com。”
- 从路径段中提取
owner和repo - 确定扫描类型:
- 如果 URL 包含
/blob/且以.md结尾 → 单个文件扫描 - 否则 → 目录扫描
- 如果 URL 包含
- 对于目录扫描:
- 如果存在
/tree/{branch}/{path},则提取branch和path - 如果没有
/tree/,则将branch设为空(使用默认值),并将path设为空字符串
- 如果存在
- 对于单个文件扫描:
- 提取
/blob/{branch}/后的branch和文件路径
- 提取
步骤 2-URL-2:获取内容
扫描单个文件时:
- 将
/blob/URL 转换为原始文件 URL:https://raw.githubusercontent.com/{owner}/{repo}/{branch}/{path} - 使用 WebFetch 获取文件内容
- 直接进入步骤 5进行分析
扫描目录时:
- 获取目录:
https://api.github.com/repos/{owner}/{repo}/contents/{path}?ref={branch}- 如果 branch 为空,则省略
?ref=参数(使用默认分支) - 使用 WebFetch,并提供提示词:"Extract the JSON array of files. For each item, return: name, type (file/dir), download_url"
- 如果 branch 为空,则省略
- 确定内容类型并相应获取内容:
- 如果存在
.claude-plugin/目录,且其中包含plugin.json:完整插件扫描(获取所有插件文件) - 如果存在
skills/:技能扫描(获取技能目录) - 如果存在
SKILL.md:单个技能目录扫描(获取目录中的所有文件) - 如果以上均不满足:错误:"No scannable content found. Expected .claude-plugin/plugin.json, skills/ directory, or SKILL.md."
- 如果存在
- 递归获取所需目录和文件:
.claude-plugin/→ 获取plugin.jsonskills/→ 获取子目录 → 获取每个技能目录下的所有文件agents/→ 获取所有*.md文件(如果存在)hooks/→ 获取hooks.json(如果存在)- 获取 hook 或 skill 调用的每个脚本(例如
skills/*/scripts/**、skills/*/*.sh) commands/→ 获取所有*.md文件(如果存在)
步骤 2-URL-3:获取文件内容
扫描插件时,获取:
.claude-plugin/plugin.json(包括任何hooks字段)、README.md、.mcp.json、hooks/hooks.jsonskills/下的每个文件、agents/*.md、commands/*.md,以及 hook 或 skill 调用的每个脚本
扫描技能目录时(skills/ 或单个技能),获取:
- 技能目录中的所有文件
使用 WebFetch,并提供提示词:"Return the raw file content exactly as-is"
步骤 2-URL-4:错误处理
- 404:仓库或路径不存在
- 403/401:私有仓库(不支持)或超出速率限制
- 其他错误:报告错误消息
获取所有文件后,进入步骤 5进行分析。
步骤 3:获取扫描目标
根据步骤 2 确定的范围和步骤 1 中的 target_agents,收集目标:
对于插件(仅限 Claude Code):
用户级:
- 读取
~/.claude/plugins/installed_plugins.json .plugins将每个插件 ID(<plugin>@<marketplace>)映射到一组安装记录。对于每个 ID,保留该 ID 及每条记录的installPath,不考虑记录的scope,然后按installPath去重扫描目标- 如果文件不存在,报告 "No user-level plugins installed"
项目级:
- 使用 Glob 查找
.claude/plugins/*/中的插件 - 如果未找到插件,报告 "No project-level plugins found"
对于技能(根据 target_agents):
针对 target_agents 列表中的每个 Agent,从对应目录收集技能:
Agent 路径映射:
| Agent | 项目级 | 用户级 |
|---|---|---|
| claude | .claude/skills/*/ | ~/.claude/skills/*/ |
| codex | .codex/skills/*/ | ~/.codex/skills/*/ |
| gemini | .gemini/skills/*/ | ~/.gemini/skills/*/ |
| agents | .agents/skills/*/ | ~/.config/agents/skills/*/ AND ~/.agents/skills/*/ |
对于 target_agents 中的每个 Agent:
用户级:
- 根据 Agent ID 确定用户级路径(见上表)
- 在路径中查找技能目录
- 对于找到的每个技能目录,记录其路径和用于扫描的 Agent ID
- 如果未找到该 Agent 的技能,报告 "No user-level skills found for {agent}"
项目级:
- 根据 Agent ID 确定项目级路径(见上表)
- 在路径中查找技能目录
- 对于找到的每个技能目录,记录其路径和用于扫描的 Agent ID
- 如果未找到该 Agent 的技能,报告 "No project-level skills found for {agent}"
第 4 步:筛选目标
如果设置了 --all 标志:完全跳过此步骤,扫描所有目标。
自身排除(自动适用于所有目标类型)
<skill base directory> 是本技能被调用时,运行框架报告为“此技能的基础目录”的目录。不要硬编码绝对路径。
- 比较前先规范化:对两侧都去掉末尾的
/,并展开开头的~ - 解析路径:运行
ls -ld <dir>。如果输出显示-> <target>,则当<target>是绝对路径时,解析后的路径为<target>;否则,将<target>与包含<dir>的目录拼接并规范化。不会解析祖先路径组件。如果命令失败,则该路径没有解析后的形式 - 自身目标:收集到的目标——插件安装记录的
installPath、项目级插件目录或技能目录——如果其路径等于<skill base directory>,或者其中一方是另一方以/为边界的前缀,则该目标就是此扫描器自身。对照两次路径:先比较收集到的路径与报告的路径,再比较双方解析后的路径 - 跳过每个自身目标。如果其中任何一个是插件安装记录,也跳过共享该记录插件 ID 的所有其他记录。将每次跳过报告为路径匹配,并计入 Trusted 列
- 当
<skill base directory>不可用时:跳过名为security-scanner的插件和技能,并将跳过情况报告为名称匹配 - 当
<skill base directory>可用时,任何并非此扫描器的security-scanner插件或技能都要照常扫描;安装在主机其他位置的此扫描器的另一个副本就是此类目标
插件:
可信来源:
- 如果市场位于
trusted_marketplaces中 → 跳过 - 如果插件 ID(
<plugin>@<marketplace>)位于trusted_plugins中 → 跳过 - 将跳过的插件报告为“Trusted (skipped)”
技能:
可信来源:
- 如果技能名称位于
trusted_skills中 → 跳过(适用于任何 Agent) - 将跳过的技能报告为“Trusted (skipped)”
第 5 步:分析每个插件
对于每个非可信插件:
-
读取插件元数据(
.claude-plugin/plugin.json、README.md),了解其声明的用途 -
读取所有可执行内容:
skills/*/SKILL.md- 技能定义和指令agents/*.md- Agent 系统提示词(如果存在).claude-plugin/plugin.json的hooks字段和hooks/hooks.json- Hook 定义,以及它们调用的每个脚本(如果存在)commands/*.md- 命令定义(如果存在).mcp.json- MCP 服务配置(如果存在)
-
分析是否存在恶意意图(包括代码和自然语言)
第 5.5 步:分析每个技能
对于每个非可信技能:
-
读取技能元数据(
SKILL.mdfrontmatter),了解其声明的用途 -
读取技能目录中的所有文件:
SKILL.md- 技能主要指令(必需)- 目录中的所有其他文件
-
分析是否存在恶意意图(包括代码和自然语言)
第 6 步:威胁检测
代码层面的威胁
查找危险的命令模式:
- 远程代码执行:
curl|sh、wget|bash、base64 -d|sh - 语言运行时 RCE:
python -c、perl -e、ruby -e、node -e、osascript、powershell - 反向 Shell:
nc -e、netcat、socat、mkfifo - 系统破坏:
rm -rf /、dd if= - 凭据访问:
~/.ssh/、/etc/passwd、keychain - 数据外泄:
sshpass、向外部服务执行scp、rsync - 临时文件执行:
chmod +x /tmp/*、mktemp+ 执行 - 混淆:解码
base64/xxd/hexdump后执行 - 软件包安装副作用:使用
postinstall或setup.py的npm install/pip install - 持久化:
crontab、launchctl - 权限提升:
sudo、doas
自然语言威胁
阅读系统提示词、指令和文档,检查是否存在:
- 数据外泄指令:指令要求读取敏感文件(SSH 密钥、凭据、API 密钥、私人数据)并将其发送到外部
- 隐藏的恶意操作:指令要求执行有害操作,同时表面上看起来是在提供帮助
- 欺骗性指令:指令与插件宣称的用途相矛盾
- 绕过安全机制:指令要求忽略安全警告或绕过限制
- 欺骗用户:指令要求向用户隐瞒操作或提供虚假信息
- 隐藏日志/跟踪记录:指令要求删除日志、清除历史记录或隐藏操作证据
- 过度申请权限:指令要求访问无关资源
权限分析
检查权限是否与插件用途相符:
- “翻译插件”需要
Bash(*)吗?可疑。 - “git 助手”需要
Bash(git *)吗?合理。 - “文件整理工具”需要访问
~/.ssh/吗?可疑。
第 7 步:生成报告
使用 report_language 设置中指定的语言生成报告。
对于本地扫描(默认、--user、--project、--all)
日语(ja)— 默认:
# セキュリティ分析レポート
## 概要
| エージェント | 種別 | 検出 | 信頼済 | スキャン | 悪意あり | 要注意 | 安全 |
|-------------|------|------|--------|----------|----------|--------|------|
| claude | プラグイン | N | N | N | N | N | N |
| claude | スキル | N | N | N | N | N | N |
注: `target_agents` に設定されたエージェントのみ表示。プラグインは常に `claude` 配下。
## 信頼済み(スキップ)
- plugin-name@marketplace(信頼済みマーケットプレイス)
- plugin-name@marketplace(自己除外: パス一致)
- skill-name (claude)(自己除外: 名前一致)
- skill-name (claude) - 信頼済みスキル
## 検出結果
### プラグイン (claude)
#### [プラグイン名]
**種別:** プラグイン
**目的:** [README/plugin.json から]
**判定:** 安全 / 要注意 / 悪意あり
**検出された問題:**
- [問題の説明、ファイル、懸念される理由]
### スキル
#### [スキル名] (claude)
**エージェント:** claude
**種別:** スキル
**場所:** ~/.claude/skills/skill-name/ または .claude/skills/skill-name/
**目的:** [SKILL.md の description から]
**判定:** 安全 / 要注意 / 悪意あり
**検出された問題:**
- [問題の説明と懸念される理由]
---
## 推奨事項
問題のある項目について:
- [ ] 安全 - 使用可
- [ ] 要確認 - [具体的な懸念点]
- [ ] 使用禁止 - [悪意のあるコンテンツを検出]
英语(en):
# Security Analysis Report
## Summary
| Agent | Type | Found | Trusted | Scanned | Malicious | Suspicious | Safe |
|-------|------|-------|---------|---------|-----------|------------|------|
| claude | Plugins | N | N | N | N | N | N |
| claude | Skills | N | N | N | N | N | N |
Note: Only rows for configured `target_agents` are shown. Plugins are always under `claude`.
## Trusted (Skipped)
- plugin-name@marketplace (trusted marketplace)
- plugin-name@marketplace (self-exclusion: path match)
- skill-name (claude) (self-exclusion: name match)
- skill-name (claude) - trusted skill
## Findings
### Plugins (claude)
#### [Plugin Name]
**Type:** Plugin
**Purpose:** [from README/plugin.json]
**Verdict:** Safe / Suspicious / Malicious
**Issues found:**
- [Description of issue, file, and why it's concerning]
### Skills
#### [Skill Name] (claude)
**Agent:** claude
**Type:** Skill
**Location:** ~/.claude/skills/skill-name/ or .claude/skills/skill-name/
**Purpose:** [from SKILL.md description]
**Verdict:** Safe / Suspicious / Malicious
**Issues found:**
- [Description of issue and why it's concerning]
对于 GitHub URL 扫描(--url)
使用与本地扫描相同的报告格式,并添加以下标题:
日语(ja):
- URL:{元のURL}
- 种类:插件 / 技能 / 单个文件
英语(en):
- URL:{original URL}
- 类型:插件 / 技能 / 单个文件
分析指南
- 结合上下文判断:检查
rm -rf模式的安全插件,与包含rm -rf命令的插件并不相同 - 检查用途是否一致:代码/指令是否符合插件宣称的用途?
- 信任但要验证:阅读实际内容,不要只匹配模式
- 不确定时,将其标记为可疑
- 解释发现的问题:始终说明标记某项内容的原因