Back to skill

Security audit

cc-plugin

Security checks for vulnerabilities and agentic risk

Overview

This is a mostly coherent Claude Code plugin-management skill, but it can delete or overwrite local plugin files and persistently change Claude settings without enough built-in safeguards.

Install only if you are comfortable letting the skill operate on your Claude Code plugin directories and settings. Use --dry-run first, inspect source and marketplace paths carefully, avoid dev-reflect when the target marketplace is the same repository or a worktree of it, and run npm install/build only for plugins you trust. Back up ~/.claude/settings.json and marketplace clones before using workflows that enable plugins, sync hooks, or clean cache directories.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/dev-reflect.sh:45
Finding
Destructive synchronization proceeds without enforcing the documented same-repository guard## Vulnerability Details **File Location**: `scripts/dev-reflect.sh:45-65` **Vulnerability Type**: Missing safety validation before destructive file synchronization **Risk Level**: High ### Technical Analysis The helper derives the destination from the user-supplied marketplace name and then synchronizes component directories using `rsync -a --delete`. It validates only that the source manifest and destination directory exist. It does not resolve symlinks, compare canonical paths, or compare Git common directories before performing the destructive synchronization. ```bash SRC_MP="$SOURCE/.claude-plugin/marketplace.json" CLONE="$HOME/.claude/plugins/marketplaces/$MARKETPLACE" CLONE_MP="$CLONE/.claude-plugin/marketplace.json" [ -f "$SRC_MP" ] || { echo "[dev-reflect] not a marketplace source (no $SRC_MP)" >&2; exit 1; } [ -d "$CLONE" ] || { echo "[dev-reflect] marketplace clone not found: $CLONE" >&2; exit 1; } [ -f "$CLONE_MP" ] || { echo "[dev-reflect] clone has no marketplace.json: $CLONE_MP" >&2; exit 1; } command -v jq >/dev/null || { echo "[dev-reflect] jq required" >&2; exit 1; } run() { if [ "$DRYRUN" = 1 ]; then echo "DRY: $*"; else eval "$*"; fi; } # 1. Sync component dirs HAVE_RSYNC=0; command -v rsync >/dev/null && HAVE_RSYNC=1 for dir in skills agents commands hooks plugins; do [ -d "$SOURCE/$dir" ] || continue if [ "$HAVE_RSYNC" = 1 ]; then run "rsync -a --delete \"$SOURCE/$dir/\" \"$CLONE/$dir/\"" else run "mkdir -p \"$CLONE/$dir\"" run "command cp -r \"$SOURCE/$dir/.\" \"$CLONE/$dir/\"" ``` The associated documentation recognizes this exact hazard in `dev-reflect.md:23-50`: a marketplace path can be a symlink to the source repository or can refer to another worktree of the same repository. It labels the comparison a “HARD STOP,” but the executable helper does not implement that check. Consequently, the prose warning does not protect direct script invocation by the Agent ...[truncated 1745 chars]
Remediation
## Remediation Suggestions 1. Resolve the source and destination with canonical, symlink-aware paths before any write operation, and abort if they are identical. 2. For Git repositories, obtain and canonicalize both the worktree root and common Git directory. Abort when the source and destination share the same repository, including when they are different worktrees. 3. Perform these checks inside `scripts/dev-reflect.sh`; do not rely solely on documentation or the calling Agent. 4. Make dry-run the default and require an explicit flag such as `--apply` or `--confirm-delete` before using `rsync --delete`. 5. Display the canonical source and destination paths and the deletion plan before requesting confirmation. 6. Refuse unsafe destination paths, including an empty path, the home directory, the Claude configuration root, or a destination outside the expected marketplaces directory. 7. Replace the string-based `eval` helper with direct command execution using argument arrays. This preserves argument boundaries and reduces the risk of future command-injection defects. 8. Add regression tests covering direct path equality, symlink aliases, nested paths, separate worktrees sharing a Git common directory, and genuinely independent repositories.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (23)

Ae1

High
Category
analysis-evasion
Content
ailures, installation failures, cache sync, HUD diagnostics | [troubleshoot.md](./troubleshoot.md) |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
ailures, installation failures, cache sync, HUD diagnostics | [troubleshoot.md](./troubleshoot.md) |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Agent Config Directory Access

High
Category
Agent Snooping
Content
| `--enable` | Optional. Enable `<plugin>@<marketplace>` in `settings.json` (backup written) |
| `--dry-run` | Print actions without writing |

Find the marketplace name: `jq -r '.name' ~/.claude/plugins/marketplaces/<dir>/.claude-plugin/marketplace.json`, or check `extraKnownMarketplaces` in `settings.json`.

## What It Does
Confidence
85% confidence
Finding
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.

Agent Config Directory Access

High
Category
Agent Snooping
Content
command cp -r "$SRC/skills/." "$CLONE/skills/"
RALPH=$(jq '.plugins[] | select(.name=="<plugin>")' "$SRC/.claude-plugin/marketplace.json")
jq --argjson r "$RALPH" '.plugins += [$r]' "$CLONE/.claude-plugin/marketplace.json" > /tmp/mp && command cp /tmp/mp "$CLONE/.claude-plugin/marketplace.json"
jq '.enabledPlugins["<plugin>@<marketplace>"] = true' ~/.claude/settings.json > /tmp/s && command cp /tmp/s ~/.claude/settings.json
```

## Relation to Other Topics
Confidence
90% confidence
Finding
This manual fallback directly rewrites `~/.claude/settings.json`, which is a sensitive agent configuration file controlling enabled plugins. Even though the documented purpose is legitimate local testing, modifying agent config can enable unreviewed code, persist risky behavior across sessions, or accidentally corrupt configuration if the jq/copy pipeline fails or is misused.

Agent Config Directory Access

High
Category
Agent Snooping
Content
The HUD pipeline has three layers:

```
~/.claude/settings.json (statusLine.command)
  └─→ ~/.claude/hud/omc-hud.mjs (wrapper, resolves dist source)
        └─→ ~/.claude/plugins/cache/omc/oh-my-claudecode/<version>/dist/hud/index.js (renderer)
```
Confidence
90% confidence
Finding
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.

Agent Config Directory Access

High
Category
Agent Snooping
Content
The HUD pipeline has three layers:

```
~/.claude/settings.json (statusLine.command)
  └─→ ~/.claude/hud/omc-hud.mjs (wrapper, resolves dist source)
        └─→ ~/.claude/plugins/cache/omc/oh-my-claudecode/<version>/dist/hud/index.js (renderer)
```
Confidence
90% confidence
Finding
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.

Agent Config Directory Access

High
Category
Agent Snooping
Content
The HUD pipeline has three layers:

```
~/.claude/settings.json (statusLine.command)
  └─→ ~/.claude/hud/omc-hud.mjs (wrapper, resolves dist source)
        └─→ ~/.claude/plugins/cache/omc/oh-my-claudecode/<version>/dist/hud/index.js (renderer)
```
Confidence
90% confidence
Finding
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.

Agent Config Directory Access

High
Category
Agent Snooping
Content
The HUD pipeline has three layers:

```
~/.claude/settings.json (statusLine.command)
  └─→ ~/.claude/hud/omc-hud.mjs (wrapper, resolves dist source)
        └─→ ~/.claude/plugins/cache/omc/oh-my-claudecode/<version>/dist/hud/index.js (renderer)
```
Confidence
90% confidence
Finding
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.

Agent Config Directory Access

High
Category
Agent Snooping
Content
| HUD source | `omcHud` config support |
|------------|-------------------------|
| `dist/hud/index.js` in current plugin cache | Verify with `grep -o "omcHud" ~/.claude/plugins/cache/omc/oh-my-claudecode/*/dist/hud/index.js` |
| Source returns 0 hits | HUD version does not consume `omcHud` — use method C (wrapper sed) or upgrade |
| Source returns matches | Method A / B should work after the next session start |
Confidence
85% confidence
Finding
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.

Chaining Abuse

High
Category
Tool Misuse
Content
| .plugins = ([.plugins[] | select(.name as $n | ($names | index($n) | not))] + $src)
  ' "$CLONE_MP" > "$TMP"
  jq empty "$TMP"
  command cp "$TMP" "$CLONE_MP"; rm -f "$TMP"
  echo "[dev-reflect] marketplace.json plugins upserted"
fi
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Chaining Abuse

High
Category
Tool Misuse
Content
| .plugins = ([.plugins[] | select(.name as $n | ($names | index($n) | not))] + $src)
  ' "$CLONE_MP" > "$TMP"
  jq empty "$TMP"
  command cp "$TMP" "$CLONE_MP"; rm -f "$TMP"
  echo "[dev-reflect] marketplace.json plugins upserted"
fi
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Agent Config Directory Access

High
Category
Agent Snooping
Content
# 4. Optional: enable plugin in settings.json
if [ -n "$ENABLE" ]; then
  S="$HOME/.claude/settings.json"
  KEY="$ENABLE@$MARKETPLACE"
  if [ "$DRYRUN" = 1 ]; then
    echo "DRY: enable $KEY in $S (with backup)"
Confidence
90% confidence
Finding
The script writes directly to the user's Claude configuration directory, enabling a plugin entry in ~/.claude/settings.json based on caller-controlled values. Because this skill is specifically for plugin lifecycle management, that access is expected, but it is still sensitive: misuse or untrusted invocation could persistently alter agent behavior by enabling a marketplace plugin.

Agent Config Directory Access

High
Category
Agent Snooping
Content
ls -la ~/.claude | head -3      # confirm symlink target

# 2. Read installLocation from BOTH environments
cat ~/.claude/plugins/known_marketplaces.json | grep installLocation

# 3. Compare: does the path match the current environment?
#    Windows session expects:  "C:\\Users\\<USER>\\.claude\\plugins\\marketplaces\\<name>"
Confidence
85% confidence
Finding
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.

Lp3

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding
The skill advertises operational capabilities around plugin lifecycle management and explicitly references a shell helper script (`scripts/dev-reflect.sh`), but it does not declare any `permissions` or `allowed-tools` scope in the skill manifest. That mismatch can cause the agent to invoke shell actions without an explicit least-privilege boundary, increasing the chance of overbroad command execution against local plugin, cache, or marketplace paths.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This markdown file describes a cleanup skill whose stated behavior includes removing old versions and deleting temp directories, but it does not give a direct user warning about potential data loss or irreversible deletion effects. Although there is a cleanup-only note and a dry-run option, the description lacks a clear caution that real execution performs deletions in user cache paths.

Skill Enumeration

Medium
Category
Agent Snooping
Content
```bash
# OWNERSHIP: resources/ is the source of truth — does this skill own the hook?
ls ~/.claude/skills/<skill>/resources/*.sh 2>/dev/null
# An installed hook with a domain-matching name but no resources/ owner is
# UNMANAGED (cross-check `Skill("hook-kit", "audit")`) — it is NOT this skill's footprint.
```
Confidence
85% confidence
Finding
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
This code overwrites ~/.claude/settings.json after creating a backup, enabling a plugin in the user's configuration. Although the file header documents the behavior, there is no interactive confirmation or immediate user-facing warning at the point of mutation for this safety-relevant config change.

Session Persistence

Medium
Category
Rogue Agent
Content
MARKET=~/.claude/plugins/marketplaces/<marketplace>/plugins/<plugin-name>
CACHE=~/.claude/plugins/cache/<marketplace>/<plugin-name>/<version>

mkdir -p "$CACHE"

# Copy essential directories
for item in .claude-plugin .mcp.json agents CLAUDE.md dist hooks scripts skills; do
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The troubleshooting guidance tells users to run `npm install && npm run build` inside a plugin directory. Those commands execute arbitrary package lifecycle scripts (`preinstall`, `postinstall`, `prepare`, build hooks) defined by the plugin and its dependencies, which creates a code-execution path during troubleshooting without any warning or trust boundary. In a plugin-management skill, this is especially risky because the content normalizes running unreviewed code from marketplace/plugin sources.

File System Enumeration

Medium
Category
Data Exfiltration
Content
```bash
# 1. Check filesystem topology
readlink ~/.claude              # is it a symlink?
ls -la ~/.claude | head -3      # confirm symlink target

# 2. Read installLocation from BOTH environments
cat ~/.claude/plugins/known_marketplaces.json | grep installLocation
Confidence
60% confidence
Finding
Code scans file system directories looking for sensitive files. This could be reconnaissance for credential theft.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
The phrase "Korean-pattern externalization" indicates a language- or locale-specific behavior in the skill ecosystem, but this changelog does not document any user choice, opt-in, or clear regional justification for that constraint. Under the policy, natural-language references that imply forced locale handling can be findings when no opt-in or justification is visible.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The text "CI hangul-check" explicitly describes a Korean-script-specific validation rule. In this file, there is no accompanying explanation that the locale restriction is optional or justified for a region-specific compliance purpose, so it appears to impose a language/locale policy constraint.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
This repeated entry again states "CI hangul-check," which implies repository behavior tied to a specific script/language. Because the file provides no indication of user choice or a justified region-specific requirement, it falls under the language/locale policy concern.

Static analysis

No suspicious patterns detected.