| name | security-scanner |
| description | Scan installed plugins and skills for security risks including malicious code AND malicious natural language instructions. Use /security-scanner to audit before installation. |
| allowed-tools | Read, Glob, Grep, WebFetch, Bash(ls *) |
Security Scanner
Analyzes Claude Code plugins and skills for malicious content using AI semantic analysis.
Usage
/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)
URL Format (--url option)
Supports GitHub URLs:
https://github.com/owner/repo
https://github.com/owner/repo/tree/main/path/to/plugin
Note: Only public repositories are supported. Branch specified in URL is used (defaults to repository's default branch if not specified).
Scan Targets
Plugins (Claude Code only)
Plugins are a Claude Code specific concept. Scan locations are fixed:
- User-level:
~/.claude/plugins/ (shared across all projects)
- Project-level:
.claude/plugins/ (project-specific)
Skills (Multi-agent support)
Skills are scanned based on the target_agents setting in configuration. If not configured, only claude is scanned (backward compatible).
| Agent ID | Project Level | User Level |
|---|
| claude | .claude/skills/ | ~/.claude/skills/ |
| codex | .codex/skills/ | ~/.codex/skills/ |
| gemini | .gemini/skills/ | ~/.gemini/skills/ |
| agents | .agents/skills/ | ~/.config/agents/skills/ AND ~/.agents/skills/ |
Note: For Skills.sh/Amp (agents), the user-level path checks both ~/.config/agents/skills/ and ~/.agents/skills/.
Symlink note: For Skills.sh, the skill body is in .agents/skills/ and other agent directories contain symlinks. Configure target_agents appropriately to avoid redundant scanning (e.g., use only agents instead of all agents).
Configuration
Users can configure target agents and trusted sources in security-scanner.local.md:
- Project-level:
.claude/security-scanner.local.md (takes precedence)
- User-level:
~/.claude/security-scanner.local.md
If both files exist, project-level settings take precedence.
---
# Report language (default: ja)
# Examples: ja, en, zh, ko, fr, de, etc.
report_language: ja
# Target agents to scan (default: claude only)
# Valid values: claude, codex, gemini, agents
target_agents:
- claude
- codex
- gemini
- agents
# Trusted sources (skipped during scanning)
trusted_marketplaces:
- claude-plugins-official # Skip all plugins from this marketplace
- hiropon-plugins
trusted_plugins:
- plugin-dev@claude-plugins-official # Skip specific plugin
- frontend-design@claude-code-plugins
trusted_skills:
- my-skill # Skip specific skill by name (all agents)
---
Report Language
report_language: Language for the security report output
- Any language code is accepted (e.g.,
ja, en, zh, ko, fr, de)
- Default:
ja (Japanese)
Target Agents
target_agents: List of agent IDs to scan skills for
- If not specified or empty, defaults to
["claude"] for backward compatibility
- Valid agent IDs:
claude, codex, gemini, agents
Trusted Sources
Trusted sources are skipped during scanning.
trusted_marketplaces: Skip all plugins from these marketplaces
trusted_plugins: Skip specific plugins (format: plugin-name@marketplace)
trusted_skills: Skip specific skills by name (applies to all agents)
To add/remove settings, edit security-scanner.local.md in .claude/ (project-level) or ~/.claude/ (user-level).
Scanning Process
Step 1: Load Settings
Search for security-scanner.local.md in the following locations:
- Project-level:
.claude/security-scanner.local.md
- User-level:
~/.claude/security-scanner.local.md
Priority rules:
- If both files exist, use project-level settings only (project-level takes precedence)
- If only one file exists, use that file
- If neither file exists, proceed with default settings
From the selected file, extract:
report_language from YAML frontmatter (default: ja)
target_agents list from YAML frontmatter (default: ["claude"])
trusted_marketplaces list from YAML frontmatter
trusted_plugins list from YAML frontmatter
trusted_skills list from YAML frontmatter
Default values (when not specified):
report_language: ja (Japanese)
target_agents: ["claude"] (backward compatible - only scan Claude Code skills)
trusted_marketplaces: []
trusted_plugins: []
trusted_skills: []
Validation:
report_language: Any string value accepted (AI will generate report in that language)
target_agents must contain only valid agent IDs: claude, codex, gemini, agents
- Invalid agent IDs are ignored with a warning
Error handling:
- If file exists but has invalid YAML syntax, warn the user and proceed with default settings (do not fail the scan)
Step 2: Determine Scope
Check arguments to determine what to scan:
Location filters:
- No location flag: Scan both user-level and project-level for all configured agents
--user: Scan only user-level paths for all agents in target_agents (e.g., ~/.claude/, ~/.codex/, etc.)
--project: Scan only project-level paths for all agents in target_agents (e.g., .claude/, .codex/, etc.)
URL detection (highest priority):
- If
--url <url> is provided explicitly → Go to Step 2-URL
- If any argument starts with
https://github.com/ or http://github.com/ → Treat as URL, go to Step 2-URL
- If any argument starts with
https:// or http:// but not github.com → Error: "Unsupported host: {host}. Currently only github.com is supported."
Special modes (if no URL):
--all: Scan everything (skip Step 4 filtering entirely)
Step 2-URL: GitHub URL Scan
If URL is provided (via --url or auto-detected), follow this process instead of Steps 3-4.
Step 2-URL-1: Parse URL
Parse the GitHub URL to extract owner, repo, branch, path, and determine scan type:
URL Patterns:
- Directory:
https://github.com/{owner}/{repo}[/tree/{branch}/{path}]
- Single file:
https://github.com/{owner}/{repo}/blob/{branch}/{path}.md
- Verify host is
github.com
- If not: Error "Unsupported host: {host}. Currently only github.com is supported."
- Extract
owner and repo from path segments
- Determine scan type:
- If URL contains
/blob/ and ends with .md → Single file scan
- Otherwise → Directory scan
- For directory scan:
- If
/tree/{branch}/{path} exists, extract branch and path
- If no
/tree/, set branch to empty (use default) and path to empty string
- For single file scan:
- Extract
branch and file path after /blob/{branch}/
Examples:
https://github.com/hiroro-work/claude-plugins → Directory scan, branch="", path=""
https://github.com/hiroro-work/claude-plugins/tree/main/plugins/ask-claude → Directory scan (plugin), branch="main", path="plugins/ask-claude"
https://github.com/hiroro-work/claude-plugins/tree/main/.claude/skills/my-skill → Directory scan (skill), branch="main", path=".claude/skills/my-skill"
https://github.com/owner/repo/blob/main/skills/my-skill/SKILL.md → Single file scan, branch="main"
Step 2-URL-2: Fetch Content
For Single File Scan:
- Convert
/blob/ URL to raw URL: https://raw.githubusercontent.com/{owner}/{repo}/{branch}/{path}
- Use WebFetch to fetch the file content
- Proceed directly to Step 5 for analysis
For Directory Scan:
- Fetch directory:
https://api.github.com/repos/{owner}/{repo}/contents/{path}?ref={branch}
- If branch is empty, omit
?ref= parameter (uses default branch)
- Use WebFetch with prompt: "Extract the JSON array of files. For each item, return: name, type (file/dir), download_url"
- Determine content type and fetch accordingly:
- If
plugin.json exists: Full plugin scan (fetch all plugin files)
- If
skills/ exists: Skill scan (fetch skill directories)
- If
SKILL.md exists: Single skill directory scan (fetch all files in directory)
- If none of the above: Error "No scannable content found. Expected plugin.json, skills/ directory, or SKILL.md."
- Recursively fetch required directories:
skills/ → fetch subdirectories → fetch SKILL.md files
agents/ → fetch all *.md files (if exists)
hooks/ → fetch all *.md files (if exists)
commands/ → fetch all *.md files (if exists)
Step 2-URL-3: Fetch File Contents
For plugin scan, fetch:
plugin.json, README.md, .mcp.json
skills/*/SKILL.md, agents/*.md, hooks/*.md, commands/*.md
For skill directory scan (skills/ or single skill), fetch:
- All files in the skill directory
Use WebFetch with prompt: "Return the raw file content exactly as-is"
Step 2-URL-4: Error Handling
- 404: Repository or path not found
- 403/401: Private repo (not supported) or rate limit exceeded
- Other errors: Report the error message
After fetching all files, proceed to Step 5 for analysis.
Step 3: Get Scan Targets
Based on scope determined in Step 2 and target_agents from Step 1, collect targets:
For plugins (Claude Code only):
User-level:
- Read
~/.claude/plugins/installed_plugins.json
- Extract plugin name (e.g.,
ask-claude@hiropon-plugins) and installPath
- If file doesn't exist, report "No user-level plugins installed"
Project-level:
- Use Glob to find plugins in
.claude/plugins/*/
- If no plugins found, report "No project-level plugins found"
For skills (based on target_agents):
For each agent in target_agents list, collect skills from the corresponding directories:
Agent path mapping:
| Agent | Project Level | User Level |
|---|
| claude | .claude/skills/*/ | ~/.claude/skills/*/ |
| codex | .codex/skills/*/ | ~/.codex/skills/*/ |
| gemini | .gemini/skills/*/ | ~/.gemini/skills/*/ |
| agents | .agents/skills/*/ | ~/.config/agents/skills/*/ AND ~/.agents/skills/*/ |
For each agent in target_agents:
User-level:
- Determine user-level path(s) based on agent ID (see table above)
- For
agents: Check both ~/.config/agents/skills/*/ and ~/.agents/skills/*/
- Find skill directories in the path
- For each skill directory found, note the path and agent ID for scanning
- If no skills found for this agent, report "No user-level skills found for {agent}"
Project-level:
- Determine project-level path based on agent ID (see table above)
- Find skill directories in the path
- For each skill directory found, note the path and agent ID for scanning
- If no skills found for this agent, report "No project-level skills found for {agent}"
Step 4: Filter Targets