T09 · Insecure Skill Coding Practices
- Location
main.js:326- Finding
Advertised Budget Enforcement and Alerting Controls Are Not Implemented
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is mostly a local cost ledger, but it overpromises budget blocking and alerts while also documenting scheduled/external reporting in a way users could misunderstand.
Treat this as a manual local spend tracker, not as a guardrail that will stop LLM calls or enforce user quotas. Before installing, verify any cron entry yourself, avoid logging sensitive user identifiers, and do not rely on the documented WhatsApp/Telegram/Discord alerts unless the implementation is fixed and clearly configured.
main.js:326Advertised Budget Enforcement and Alerting Controls Are Not Implemented
main.js:215Unvalidated Numeric Arguments Permit Cost-Ledger and Limit Manipulation
main.js:68Non-Atomic Read-Modify-Write Storage Can Lose Concurrent Usage Records
Skill selects an external model or provider that may use a different account or billing plan than the operator expects. Undisclosed model switches can cause unexpected cost or quota consumption.
# Log an LLM call
llm-cost-guard log --model gpt-4o --input-tokens 1500 --output-tokens 800 --user alice
# Check current spend
llm-cost-guard status
Skill selects an external model or provider that may use a different account or billing plan than the operator expects. Undisclosed model switches can cause unexpected cost or quota consumption.
# Log an LLM call
llm-cost-guard log --model gpt-4o --input-tokens 1500 --output-tokens 800 --user alice
# Check current spend
llm-cost-guard status
Skill selects an external model or provider that may use a different account or billing plan than the operator expects. Undisclosed model switches can cause unexpected cost or quota consumption.
Examples:
llm-cost-guard status
llm-cost-guard log --model gpt-4o --input 1500 --output 800 --user alice
llm-cost-guard report month
llm-cost-guard set-limit daily 5.00
llm-cost-guard reset today
The README makes privacy/security assurances that conflict with other documented behavior: it advertises report delivery via WhatsApp/Telegram/Discord, which necessarily involves external communications. Misleading claims about 'No external services' and 'No telemetry' can cause users to install or configure the skill under false assumptions about data egress and trust boundaries.
The documentation states that all data is stored locally and that there are no external services, yet it also says the skill auto-installs a cron job that sends summaries and alerts externally. This is a security-relevant contradiction because users may not expect persistent scheduled tasks or outbound transmissions after installation.
Automatically installing a cron job modifies the host's scheduled tasks and creates persistent behavior without a clearly stated consent step. Persistence plus automatic external reporting increases the risk of unintended data exposure, operational surprises, and difficulty removing the behavior if users are unaware it was added.
The skill states that it auto-installs a daily cron job to send reports, alert on budget overages, and reset counters, but does not clearly warn that it will modify scheduled tasks or may send spend data to external messaging channels. Silent persistence and automatic outbound reporting are security-relevant behaviors because they change system state and can leak operational metadata without sufficiently informed consent.
The documentation makes a strong privacy/networking claim ('No external services. No telemetry.') while elsewhere advertising outbound alerts via WhatsApp, Telegram, and Discord and scheduled report delivery. This mismatch can mislead users into enabling a skill under false assumptions about data egress and operational behavior, increasing the risk of unintended disclosure of spend, user, or model-usage metadata.
The help text at L312 says set-limit user <key> <USD>, implying limits are tracked per individual user key. However, the implementation at L247-L248 does not read or store the provided user key at all; it only writes one scalar perUserDailyCostLimit, so the documented behavior contradicts the actual code semantics.
The code removes stored entries for either today's data or all historical data and immediately writes the change to disk. Although this command's purpose includes resetting counters, there is no confirmation prompt or stronger user-facing warning before the destructive operation occurs.