T09 · Insecure Skill Coding Practices
- Location
SKILL.md:22- Finding
Shell Command Injection Through Unvalidated /meter Arguments
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill broadly matches its spend-tracking purpose, but it makes lasting Claude configuration changes and has unsafe argument and sync handling that users should review before installing.
Install only if you are comfortable with a skill that edits your project Claude settings, adds a Stop hook for ongoing tracking, reads Claude transcript metadata, and stores spend history locally. Use dashboard sync only with the default trusted HTTPS endpoint and a revocable API key, and avoid passing untrusted text as /meter arguments until argument validation is added.
SKILL.md:22Shell Command Injection Through Unvalidated /meter Arguments
meter-sync.sh:34Bearer Credential and Session Metadata Exposure Through an Unvalidated Sync Endpoint
meter-session-end.sh:106Spend History Deletion Through Session ID Regex Injection
The skill claims to track spend via /meter, but it also modifies local configuration, installs hooks for ongoing collection, and parses transcript files under ~/.claude/projects. Automatic persistence and hook registration are materially more invasive than the description suggests and can create lasting monitoring behavior users did not expect.
The skill claims to track spend via /meter, but it also modifies local configuration, installs hooks for ongoing collection, and parses transcript files under ~/.claude/projects. Automatic persistence and hook registration are materially more invasive than the description suggests and can create lasting monitoring behavior users did not expect.
The skill claims to track spend via /meter, but it also modifies local configuration, installs hooks for ongoing collection, and parses transcript files under ~/.claude/projects. Automatic persistence and hook registration are materially more invasive than the description suggests and can create lasting monitoring behavior users did not expect.
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
mv "$SPEND_DIR/spend_dedup.jsonl" "$SPEND_FILE"
fi
cat "$SPEND_DIR/pending_${SESSION_ID}.jsonl" >> "$SPEND_FILE"
rm -f "$SPEND_DIR/pending_${SESSION_ID}.jsonl"
fi
fi
The skill instructs the agent to execute bash, but the manifest declares no explicit tool scope or allowed-tools. That omission weakens least-privilege controls and makes it harder for users and platforms to understand that shell execution is required before invocation.
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.
Install from ClawHub into your project:
clawhub install agent-meter --dir .claude/skills
Then run /meter — it handles everything automatically:
The setup text minimizes the significance of copying hooks and modifying .claude/settings.json by framing it as automatic handling. Downplaying persistent file changes and hook registration reduces informed consent and increases the chance that users enable ongoing data collection unintentionally.
The hosted dashboard sync instructions do not prominently warn that local spend and session metadata will be transmitted off-machine. Without an explicit privacy disclosure, users may expose project names, model usage, timestamps, and other operational metadata to a third party unexpectedly.
The documentation asserts that components have no network calls or secrets access, while the same skill also offers dashboard sync that uses an API key and communicates with a remote service. Even if the statement is narrowly intended for specific scripts, the overall presentation is misleading and can cause unsafe trust decisions.
The script persists session identifiers, project names, model names, token counts, and estimated spend to a local JSONL file under the user's home directory without any notice, consent, retention control, or permission hardening shown in the script. While this appears intended for legitimate metering, the stored metadata can reveal work context and usage patterns, and becomes sensitive if the host is multi-user, backed up externally, or later exfiltrated by other software.
The setup flow provisions a remote account configuration and verifies an API key against a hosted endpoint, establishing authenticated exfiltration capability not implied by the stated local metering purpose. Even if intended for product functionality, this broadens trust boundaries and may surprise users who expect a purely local accounting tool.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
--arg endpoint "$ENDPOINT" \
'{ api_key: $key, agent_name: $name, endpoint: $endpoint }' > "$SYNC_CONFIG"
chmod 600 "$SYNC_CONFIG"
echo ""
echo "Config saved to $SYNC_CONFIG"
echo "Run 'meter-sync.sh' to sync."
The script transmits detailed per-session spend metadata, including project, model, source, purpose, and intent fields, to a remote service. That exceeds the skill description of showing local '/meter' spend summaries and creates a real data exposure risk because operational metadata can reveal sensitive project names, usage patterns, and user intent.
This curl POST sends collected local session data to an external endpoint using a bearer token. External transmission is dangerous here because the payload contains detailed usage telemetry that may include sensitive business context, and the endpoint is user-configurable, increasing the risk of accidental or malicious redirection.
intent: (.intent // null)
}]
}
' | curl -s -w "\n%{http_code}" \
-X POST \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
The script advertised as a spend-summary entry point performs persistent system changes by installing a hook and mutating .claude/settings.json. That creates behavior beyond user-visible reporting, establishes ongoing execution on future Stop events, and can surprise users who invoked what appears to be a read-only utility.
Automatically wiring a Stop hook and editing settings as implicit side effects is unjustified for a command whose description suggests simple summarization. This persistence mechanism broadens the trust boundary because future sessions will execute the installed hook, which could later collect or alter more than the user expected.
The script copies an executable into .claude/hooks and changes permissions without prior warning or confirmation. Silent installation of executable persistence is risky because users may not realize they have granted future execution to code from the skill package.
The script scans local Claude transcript files and derives session metadata and token usage into a persistent spend database without an explicit warning. Even if intended for billing summaries, transcript-derived metadata such as session IDs, project names, timestamps, and model usage can expose sensitive work patterns and should not be harvested silently.
The script silently enumerates local Claude transcript files under ~/.claude/projects and derives per-session metadata into a separate spend log without any notice, consent prompt, or visible disclosure during execution. While it does not exfiltrate data off-host, it processes potentially sensitive usage history and project identifiers, which can surprise users and create a privacy issue in an agent skill whose behavior may be triggered indirectly.
No suspicious patterns detected.