Back to skill

Security audit

Token Usage Tracker

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent token-usage tracker, but its local state file handling can overwrite files through a predictable path and symbolic links in an untrusted working directory.

Review this skill before installing if you expect to run it in shared, downloaded, or otherwise untrusted project directories. It appears to track only token usage locally and does not use the network or credentials, but its default state file is written in the current directory; avoid running state-changing commands where another user could plant or replace .usage-tracker.json, and back up the file before using reset.

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

Warning
Location
scripts/usage-tracker.mjs:129
Finding

Predictable State File Allows Symbolic-Link File Overwrite

Content
View full analysis

Vulnerability Details

File Location: scripts/usage-tracker.mjs, lines 129–130, 318–321, and 327–339
Vulnerability Type: Unsafe file handling and symbolic-link following
Risk Level: Medium

Vulnerable Code:

javascript
// Lines 129–130
this.storagePath = config.storagePath || './.usage-tracker.json';
this._load();
javascript
// Lines 318–321
if (fs.existsSync(this.storagePath)) {
  const data = JSON.parse(fs.readFileSync(this.storagePath, 'utf-8'));
  this.turns = data.turns || [];
javascript
// Lines 327–339
_save() {
  try {
    const data = {
      turns: this.turns,
      totalInputTokens: this.totalInputTokens,
      totalOutputTokens: this.totalOutputTokens,
      totalCacheCreation: this.totalCacheCreation,
      totalCacheRead: this.totalCacheRead,
      turnCount: this.turnCount,
      savedAt: new Date().toISOString()
    };
    fs.writeFileSync(this.storagePath, JSON.stringify(data, null, 2), 'utf-8');

Technical Analysis

The tracker uses the predictable relative path ./.usage-tracker.json, resolved against the process's current working directory. Before reading or writing this path, the implementation does not verify whether it is a regular file, reject symbolic links, validate ownership, or use a no-follow file-opening option.

Node.js fs.writeFileSync() follows an existing symbolic link and truncates the link target before writing the serialized tracker state. Therefore, an attacker who can create or replace .usage-tracker.json in a directory from which another user runs the tool can redirect the write to another file writable by the victim process.

The _load() method silently ignores loading failures. As a result, pointing the state path at a non-JSON target does not reliably stop exploitation: construction can continue, and a later state-changing operation such as record() or reset() invokes _save() and overwrites th ...[truncated 1643 chars]

Remediation
View remediation

Remediation Suggestions

  1. Store state in a dedicated per-user application-data directory rather than the current working directory. Ensure that the directory is owned by the invoking user and is not writable by untrusted users.
  2. Use fs.lstatSync() or its asynchronous equivalent to reject an existing symbolic link and require an existing destination to be a regular file.
  3. Open files with O_NOFOLLOW where supported so the operating system rejects symbolic-link traversal. Do not rely exclusively on a check followed by a separate write, because that introduces a time-of-check/time-of-use race.
  4. Create state files with restrictive permissions such as 0600.
  5. Write updates to a securely created temporary file in the same trusted directory, flush and close it, and atomically rename it over the destination.
  6. Validate a caller-provided storagePath: resolve it to an absolute path, constrain it to an approved directory where appropriate, and verify ownership and parent-directory permissions.
  7. Report state-loading errors instead of silently ignoring them, particularly when the path is not a regular file or fails integrity validation.
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (5)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This markdown file contains natural-language instructions, trigger phrases, and usage documentation entirely in Chinese, but it does not state that the skill is region-specific or provide an opt-in language choice. That can violate language/locale policy expectations by forcing a specific language on users who may not understand it.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The reset command immediately overwrites stored statistics without any confirmation, backup, or undo path. This can cause accidental loss of budgeting/history data and makes it easy for a mistaken or scripted invocation to destroy records the user may rely on for cost tracking.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The tracker silently persists per-conversation usage history to ./.usage-tracker.json, but the skill description only mentions tracking/statistics/budget control and does not disclose durable local storage. Even though the stored fields are token counts rather than raw prompts, persistent conversation metadata can still reveal activity patterns and exceed user expectations for ephemeral accounting.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
71% confidence
Finding

The manifest frames the skill as responding to requests like 'token统计' and '消耗了多少' by tracking and reporting usage. The code additionally supports wiping all accumulated statistics and exporting full historical data, which are broader data-management operations not reflected in the description.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script presents its help text and operational messages in Chinese, effectively forcing a specific language for user interaction. There is no indication of locale selection, fallback language, or user opt-in for this language constraint.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.