Back to skill

Security audit

model-inventory

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed local AI-CLI inventory scanner that checks auth/config signals and writes a local cache, with no evidence of secret exfiltration or destructive behavior.

Install this only if you are comfortable with a skill checking which AI CLIs are on your machine, whether their auth/config files or API-key environment variables exist, running small model probes unless you request a quick scan, and saving the resulting local inventory under ~/.claude/model-inventory.json for other skills to use.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (12)

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The script probes sensitive authentication state by checking API key environment variables and the presence/content of local credential files across multiple vendors. Although it does not print secret values, it still inspects private user state without an explicit consent gate or narrow scoping, creating a privacy/security boundary issue if invoked automatically by another agent.

Missing User Warnings

Low
Confidence
82% confidence
Finding
The script executes several local AI CLIs and commands such as '--version', 'login status', and 'ollama list' without a runtime warning. Running local binaries discovered on PATH can have side effects, invoke plugins/hooks, or expose metadata unexpectedly, especially when the scan is triggered automatically by another skill.

Agent Config Directory Access

High
Category
Agent Snooping
Content
claude)   cfg_model "$HOME/.claude/settings.json" "~/.claude/settings.json" && return ;;
    codex)
      if [ -f "$HOME/.codex/config.toml" ]; then
        m=$(grep -E '^[[:space:]]*model[[:space:]]*=' "$HOME/.codex/config.toml" 2>/dev/null | head -n 1 | sed -e 's/.*=[[:space:]]*//' -e 's/^"//' -e 's/"[[:space:]]*$//')
        if [ -n "$m" ]; then printf '%s|model= in ~/.codex/config.toml' "$m"; return; fi
      fi ;;
  esac
Confidence
70% confidence
Finding
This duplicate finding refers to the same ~/.codex/config.toml parsing operation already identified. It is not a separate exploit path, but reinforces that the skill reads agent config data beyond mere installation detection.

Agent Config Directory Access

High
Category
Agent Snooping
Content
case $1 in
    opencode) cfg_model "$HOME/.config/opencode/opencode.json" "~/.config/opencode/opencode.json" && return ;;
    qwen)     cfg_model "$HOME/.qwen/settings.json" "~/.qwen/settings.json" && return ;;
    gemini)   cfg_model "$HOME/.gemini/settings.json" "~/.gemini/settings.json" && return ;;
    copilot)  cfg_model "$HOME/.copilot/config.json" "~/.copilot/config.json" && return ;;
    claude)   cfg_model "$HOME/.claude/settings.json" "~/.claude/settings.json" && return ;;
    codex)
Confidence
60% confidence
Finding
This duplicate finding flags the same ~/.gemini/settings.json access as above. It is a real but moderate privacy issue rather than a separate distinct vulnerability.

Agent Config Directory Access

High
Category
Agent Snooping
Content
case $1 in
    opencode) cfg_model "$HOME/.config/opencode/opencode.json" "~/.config/opencode/opencode.json" && return ;;
    qwen)     cfg_model "$HOME/.qwen/settings.json" "~/.qwen/settings.json" && return ;;
    gemini)   cfg_model "$HOME/.gemini/settings.json" "~/.gemini/settings.json" && return ;;
    copilot)  cfg_model "$HOME/.copilot/config.json" "~/.copilot/config.json" && return ;;
    claude)   cfg_model "$HOME/.claude/settings.json" "~/.claude/settings.json" && return ;;
    codex)
Confidence
60% confidence
Finding
This duplicate finding flags the same ~/.gemini/settings.json access as above. It is a real but moderate privacy issue rather than a separate distinct vulnerability.

Agent Config Directory Access

High
Category
Agent Snooping
Content
qwen)     cfg_model "$HOME/.qwen/settings.json" "~/.qwen/settings.json" && return ;;
    gemini)   cfg_model "$HOME/.gemini/settings.json" "~/.gemini/settings.json" && return ;;
    copilot)  cfg_model "$HOME/.copilot/config.json" "~/.copilot/config.json" && return ;;
    claude)   cfg_model "$HOME/.claude/settings.json" "~/.claude/settings.json" && return ;;
    codex)
      if [ -f "$HOME/.codex/config.toml" ]; then
        m=$(grep -E '^[[:space:]]*model[[:space:]]*=' "$HOME/.codex/config.toml" 2>/dev/null | head -n 1 | sed -e 's/.*=[[:space:]]*//' -e 's/^"//' -e 's/"[[:space:]]*$//')
Confidence
60% confidence
Finding
This is a duplicate report for the same ~/.claude/settings.json access. The underlying issue is real but should be consolidated as a single privacy-sensitive config read.

Agent Config Directory Access

High
Category
Agent Snooping
Content
qwen)     cfg_model "$HOME/.qwen/settings.json" "~/.qwen/settings.json" && return ;;
    gemini)   cfg_model "$HOME/.gemini/settings.json" "~/.gemini/settings.json" && return ;;
    copilot)  cfg_model "$HOME/.copilot/config.json" "~/.copilot/config.json" && return ;;
    claude)   cfg_model "$HOME/.claude/settings.json" "~/.claude/settings.json" && return ;;
    codex)
      if [ -f "$HOME/.codex/config.toml" ]; then
        m=$(grep -E '^[[:space:]]*model[[:space:]]*=' "$HOME/.codex/config.toml" 2>/dev/null | head -n 1 | sed -e 's/.*=[[:space:]]*//' -e 's/^"//' -e 's/"[[:space:]]*$//')
Confidence
60% confidence
Finding
This is a duplicate report for the same ~/.claude/settings.json access. The underlying issue is real but should be consolidated as a single privacy-sensitive config read.

Agent Config Directory Access

High
Category
Agent Snooping
Content
copilot)  cfg_model "$HOME/.copilot/config.json" "~/.copilot/config.json" && return ;;
    claude)   cfg_model "$HOME/.claude/settings.json" "~/.claude/settings.json" && return ;;
    codex)
      if [ -f "$HOME/.codex/config.toml" ]; then
        m=$(grep -E '^[[:space:]]*model[[:space:]]*=' "$HOME/.codex/config.toml" 2>/dev/null | head -n 1 | sed -e 's/.*=[[:space:]]*//' -e 's/^"//' -e 's/"[[:space:]]*$//')
        if [ -n "$m" ]; then printf '%s|model= in ~/.codex/config.toml' "$m"; return; fi
      fi ;;
Confidence
74% confidence
Finding
This finding points to the existence check for ~/.codex/config.toml, which is part of the broader config-file inspection flow. The existence check alone is low impact, but in context it supports private config discovery without a user-facing warning.

Agent Config Directory Access

High
Category
Agent Snooping
Content
claude)   cfg_model "$HOME/.claude/settings.json" "~/.claude/settings.json" && return ;;
    codex)
      if [ -f "$HOME/.codex/config.toml" ]; then
        m=$(grep -E '^[[:space:]]*model[[:space:]]*=' "$HOME/.codex/config.toml" 2>/dev/null | head -n 1 | sed -e 's/.*=[[:space:]]*//' -e 's/^"//' -e 's/"[[:space:]]*$//')
        if [ -n "$m" ]; then printf '%s|model= in ~/.codex/config.toml' "$m"; return; fi
      fi ;;
  esac
Confidence
70% confidence
Finding
This duplicate finding refers to the same ~/.codex/config.toml parsing operation already identified. It is not a separate exploit path, but reinforces that the skill reads agent config data beyond mere installation detection.

Credential Access

High
Category
Privilege Escalation
Content
auth_claude() {
  if [ -n "${ANTHROPIC_API_KEY:-}" ]; then printf 'likely-authenticated|env ANTHROPIC_API_KEY is set'; return; fi
  if [ -f "$HOME/.claude/.credentials.json" ]; then printf 'likely-authenticated|~/.claude/.credentials.json exists'; return; fi
  if [ -f "$HOME/.claude.json" ] && grep -q '"oauthAccount"' "$HOME/.claude.json" 2>/dev/null; then
    printf 'likely-authenticated|oauthAccount present in ~/.claude.json'; return
  fi
Confidence
62% confidence
Finding
This is a duplicate of the credential-artifact access finding for ~/.claude/.credentials.json. The issue is real, but it is not a separate vulnerability from the other line-49 report.

Credential Access

High
Category
Privilege Escalation
Content
auth_claude() {
  if [ -n "${ANTHROPIC_API_KEY:-}" ]; then printf 'likely-authenticated|env ANTHROPIC_API_KEY is set'; return; fi
  if [ -f "$HOME/.claude/.credentials.json" ]; then printf 'likely-authenticated|~/.claude/.credentials.json exists'; return; fi
  if [ -f "$HOME/.claude.json" ] && grep -q '"oauthAccount"' "$HOME/.claude.json" 2>/dev/null; then
    printf 'likely-authenticated|oauthAccount present in ~/.claude.json'; return
  fi
Confidence
62% confidence
Finding
This is a duplicate of the credential-artifact access finding for ~/.claude/.credentials.json. The issue is real, but it is not a separate vulnerability from the other line-49 report.

Session Persistence

Medium
Category
Rogue Agent
Content
1. **Tiers 1–2 — run the scan.** Execute `scripts/scan.sh` (bash; runs on Git Bash/macOS/Linux) and show the user the per-CLI result. Zero tokens spent, nothing sent anywhere.
2. **Tier 3 — probe, unless the user said "quick scan".** For each installed CLI, run the probe command from [references/cli-registry.md](references/cli-registry.md) once per seed model (claude: all four aliases; other CLIs: `default` only) and classify by the table there: `verified` / `unavailable` / `blocked-by-auth` / `quota-exhausted` / `unknown`. A login error flips the CLI's `auth.status` to `unauthenticated` and marks all its models `blocked-by-auth` — the "installed but account not active" case, with the error line quoted. A timeout is `unknown`, never `unavailable`. One attempt per model; retry once only after changing one named thing; second failure → record `unknown` with the quoted error and move on. Ollama needs no probe — `ollama list` already verified its models locally.
3. **Build the routing table** per the rules below, from probe results only.
4. **Write `~/.claude/model-inventory.json`** (schema below), then report: a per-CLI table (version, auth status, each model's status with evidence), what was probed vs. assumed, and total probe cost. Zero usable CLIs is a valid outcome — write the inventory anyway so consumers see an honest empty rather than a missing file.

## Routing rules
Confidence
84% confidence
Finding
The skill instructs the agent to persist a machine-specific inventory of installed AI CLIs, authentication state, model availability, local paths, and evidence into ~/.claude/model-inventory.json. Even though it says not to store credential values, this still creates a durable reconnaissance artifact that reveals sensitive environment details and may be consumed by other skills or exposed to other local users/processes if file permissions are weak.

Static analysis

No suspicious patterns detected.