Back to skill

Security audit

token-stats-skill

Security checks for vulnerabilities and agentic risk

Overview

The skill is transparent about local token analytics, but it relies on an opaque external binary that can read broad private AI session data and can install a persistent recorder.

Install only if you trust the token-stats publisher and are comfortable letting a closed-source local binary read AI session stores across the selected agents. Prefer running a narrow agent selector first, review the exact data directories, avoid the LaunchAgent unless you want recurring background collection, and lock down or periodically delete snapshot and log directories if enabled.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (2)

T08 · Insecure Dependencies

Warning
Location
references/token-recording.md:3
Finding
Opaque Third-Party Binary Is Granted Access to Local AI Session Data<![CDATA[ ## Vulnerability Details **File Location**: `references/token-recording.md:3-23` and `references/token-recording.md:61-70` **Vulnerability Type**: Supply-chain trust risk involving a closed-source executable **Risk Level**: Medium ### Vulnerable Code ```markdown ## Public Release And Installation Use [baijian/token-stats](https://github.com/baijian/token-stats) for public documentation and [release binaries](https://github.com/baijian/token-stats/releases/latest). Verified baseline: v0.0.2 on 2026-09-09, binary commit `c17d30954d39`. This distribution repository contains no CLI implementation; do not try to build its automatic GitHub source archives. v0.0.2 has no self-update command or built-in scheduler. Its release notes and binary help supersede the stale v0.0.1 coverage in the public README. Choose `token-stats_<tag>_<os>_<arch>.tar.gz` for `darwin_arm64`, `darwin_amd64`, `linux_amd64`, `linux_arm64`, or `windows_amd64`. Download `checksums.txt` alongside the archive and verify the matching entry before extracting. For macOS Apple Silicon v0.0.2: ```bash rg ' token-stats_v0.0.2_darwin_arm64.tar.gz$' checksums.txt | shasum -a 256 -c - tar -xzf token-stats_v0.0.2_darwin_arm64.tar.gz mkdir -p "$HOME/.local/bin" install -m 0755 token-stats_v0.0.2_darwin_arm64/token-stats "$HOME/.local/bin/token-stats" export PATH="$HOME/.local/bin:$PATH" token-stats version --output json ``` Run extraction only after checksum verification succeeds. On Linux use `sha256sum -c -`; on Windows extract the matching archive and run `token-stats.exe`. Match the archive name and checksum to the selected release and platform. Use an absolute binary path for schedulers when possible. ``` The installed executable is then expected to access the following locations: ```markdown Default scanned locations: - Codex: `~/.codex/sessions` and `~/.codex/archived_sessions`. - Claude Code: `~/.claude/projects`. - OpenClaw: `~/.openclaw/agents/*/sessions`. - Hermes Agent: `~/.her ...[truncated 2670 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Publish the complete CLI source code and provide reproducible build instructions. 2. Pin supported installations to an exact release version instead of directing users to an unpinned latest-release endpoint. 3. Include independently reviewed SHA-256 values in the audited Skill package rather than relying only on a checksum downloaded from the same release origin. 4. Sign release artifacts and verify signatures or trusted build-provenance attestations before installation. 5. Document the publisher identity and release-signing trust root. 6. Require explicit user confirmation before granting the binary access to each local agent data source. 7. Prefer an allowlist of source paths and minimize access to only the sources requested by the user. 8. Use an absolute, verified executable path for scheduled execution. 9. Revalidate the executable hash before creating or updating a persistent scheduler. 10. Consider sandboxing the collector and denying network access if network connectivity is not required for local collection. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/record-token-usage.sh:43
Finding
Sensitive Snapshot and Log Files Are Created Without Enforced Private Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/record-token-usage.sh:43-48` and `scripts/install-launchd-token-recorder.sh:132-135` **Vulnerability Type**: Insecure permissions for locally stored sensitive metadata **Risk Level**: Medium ### Vulnerable Code The recording wrapper creates a directory and redirects JSON output without setting a restrictive `umask` or file mode: ```sh if [ -n "${AI_TOKEN_RUN_DIR:-}" ]; then mkdir -p "$AI_TOKEN_RUN_DIR" stamp="$(date +%Y%m%dT%H%M%S%z)" output_file="$AI_TOKEN_RUN_DIR/${agent}-${day}-${stamp}.json" "$bin" "$@" > "$output_file" cat "$output_file" ``` The LaunchAgent installer likewise creates snapshot and log directories without explicitly restricting their permissions: ```sh launch_agents_dir="$HOME/Library/LaunchAgents" log_dir="$HOME/Library/Logs/ai-token-ayalysis" plist_path="$launch_agents_dir/$label.plist" mkdir -p "$launch_agents_dir" "$log_dir" "$run_dir" ``` The reference confirms that reports can contain sensitive local metadata: ```markdown Daily reports add `day`, `storagePath`, and `sessions` with session ID, path, cwd, model, usage, and event count. ``` It also acknowledges that the CLI's permission guarantees do not cover these shell-created files: ```markdown Keep snapshots and operational logs private too; the CLI's daily-file permission guarantees do not automatically apply to shell redirects. ``` ### Technical Analysis File permissions created by `mkdir` and shell redirection are determined by the process's inherited `umask`. Neither script establishes a restrictive `umask`. Under a common `022` umask: - Newly created directories can receive mode `0755`. - Files created by shell redirection can receive mode `0644`. As a result, per-run JSON snapshots may be readable by other local users. LaunchAgent standard-output and standard-error logs may similarly inherit permissive permissions when launchd creates or opens them. The snapshots can include session identif ...[truncated 1650 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Set a restrictive process mask near the beginning of both shell scripts: ```sh umask 077 ``` 2. Explicitly create sensitive directories with owner-only permissions: ```sh mkdir -p -m 0700 "$AI_TOKEN_RUN_DIR" chmod 0700 "$AI_TOKEN_RUN_DIR" ``` 3. Create snapshot files securely and enforce mode `0600`. For example: ```sh umask 077 output_file="$AI_TOKEN_RUN_DIR/${agent}-${day}-${stamp}.json" : > "$output_file" chmod 0600 "$output_file" "$bin" "$@" > "$output_file" ``` 4. Apply mode `0700` to the snapshot and log directories created by the installer. 5. Pre-create LaunchAgent output files with mode `0600` before loading the task. 6. Restrict the generated plist to the owner where compatible with launchd requirements. 7. Validate that configured output directories are owned by the current user and are not symbolic links before writing. 8. Avoid retaining per-run snapshots unless the user explicitly requires them. 9. Add retention or rotation controls so sensitive operational logs and snapshots do not accumulate indefinitely. 10. Minimize session paths and identifiers in recurring outputs where they are not required for analysis. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (15)

Description-Behavior Mismatch

Medium
Confidence
89% confidence
Finding
The skill is framed as local token analysis, but it explicitly instructs the agent to download and install an external binary when the tool is missing or outdated. That introduces a supply-chain and remote-code-execution risk that exceeds passive analysis, especially because the distributed CLI is described as closed-source and only protected by checksum verification of the artifact, not by source review.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
This section enables persistent scheduler installation via launchd or cron-style workflows, which modifies system behavior beyond one-time analysis. Persistence increases the blast radius of any mistake or misuse, because the skill can cause repeated execution and ongoing collection from local logs over time.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
The macOS LaunchAgent installer is a system-configuration capability that creates persistence and recurring execution. In the context of a token-analytics skill, that is more dangerous because it is not merely reading data; it installs an always-on mechanism that could be abused to repeatedly access sensitive local usage records or mask broader automation under a benign description.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The script creates a LaunchAgent plist in ~/Library/LaunchAgents and immediately loads and starts it with launchctl, establishing recurring background execution at login and every StartInterval seconds. While this appears to be the stated purpose of a token recorder installer, silently creating persistence without an explicit interactive warning or separate confirmation is security-relevant because users may not realize they are installing a continuously running local collector.

Session Persistence

Medium
Category
Rogue Agent
Content
launch_agents_dir="$HOME/Library/LaunchAgents"
log_dir="$HOME/Library/Logs/ai-token-ayalysis"
plist_path="$launch_agents_dir/$label.plist"

mkdir -p "$launch_agents_dir" "$log_dir" "$run_dir"
Confidence
89% confidence
Finding
This line defines a plist path under ~/Library/LaunchAgents, which is a standard macOS user persistence location. In context, the script is preparing to install a recurring per-user background job; that is intentional functionality, but it is still persistence and should be treated as a real security-sensitive behavior rather than a false positive.

Session Persistence

Medium
Category
Rogue Agent
Content
launch_agents_dir="$HOME/Library/LaunchAgents"
log_dir="$HOME/Library/Logs/ai-token-ayalysis"
plist_path="$launch_agents_dir/$label.plist"

mkdir -p "$launch_agents_dir" "$log_dir" "$run_dir"
Confidence
89% confidence
Finding
This line defines a plist path under ~/Library/LaunchAgents, which is a standard macOS user persistence location. In context, the script is preparing to install a recurring per-user background job; that is intentional functionality, but it is still persistence and should be treated as a real security-sensitive behavior rather than a false positive.

Session Persistence

Medium
Category
Rogue Agent
Content
escaped_stdout=$(xml_escape "$log_dir/stdout.log")
escaped_stderr=$(xml_escape "$log_dir/stderr.log")

cat > "$plist_path" <<PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
Confidence
88% confidence
Finding
At this point the script starts writing the launchd plist contents, which is the concrete mechanism for session persistence. Although the skill's purpose includes periodic local collection, persistence increases the attack surface because a modified or replaced recorder script would be re-executed automatically under the user context.

Session Persistence

Medium
Category
Rogue Agent
Content
escaped_stdout=$(xml_escape "$log_dir/stdout.log")
escaped_stderr=$(xml_escape "$log_dir/stderr.log")

cat > "$plist_path" <<PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
Confidence
88% confidence
Finding
At this point the script starts writing the launchd plist contents, which is the concrete mechanism for session persistence. Although the skill's purpose includes periodic local collection, persistence increases the attack surface because a modified or replaced recorder script would be re-executed automatically under the user context.

Session Persistence

Medium
Category
Rogue Agent
Content
cat > "$plist_path" <<PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
Confidence
86% confidence
Finding
The plist XML begins here, confirming creation of a launchd configuration file for automatic execution. This is expected behavior for a scheduler installer, but it is still a true persistence mechanism that could surprise users or be abused if surrounding files or environment variables are tampered with.

Session Persistence

Medium
Category
Rogue Agent
Content
cat > "$plist_path" <<PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
Confidence
86% confidence
Finding
The plist XML begins here, confirming creation of a launchd configuration file for automatic execution. This is expected behavior for a scheduler installer, but it is still a true persistence mechanism that could surprise users or be abused if surrounding files or environment variables are tampered with.

Session Persistence

Medium
Category
Rogue Agent
Content
cat > "$plist_path" <<PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>$escaped_label</string>
Confidence
84% confidence
Finding
This section continues the creation of the LaunchAgent definition, embedding values that will control a recurring user-level job. The behavior is not inherently malicious in this skill, but the security concern is valid because it establishes auto-start execution that persists across sessions.

Session Persistence

Medium
Category
Rogue Agent
Content
<key>StandardErrorPath</key>
  <string>$escaped_stderr</string>
</dict>
</plist>
PLIST

uid=$(id -u)
Confidence
83% confidence
Finding
This marks completion of the plist contents used for persistent launchd execution. The risk remains that once such persistence exists, later compromise or unintended modification of the referenced script or environment can cause repeated execution without further user action.

Session Persistence

Medium
Category
Rogue Agent
Content
<string>$escaped_stderr</string>
</dict>
</plist>
PLIST

uid=$(id -u)
launchctl bootout "gui/$uid" "$plist_path" >/dev/null 2>&1 || true
Confidence
94% confidence
Finding
The script invokes launchctl bootout on any existing job and then proceeds toward reloading the LaunchAgent, actively managing persistent session state. This is a true persistence-related action because it ensures the user's LaunchAgent registration is updated and ready for automatic execution.

Session Persistence

Medium
Category
Rogue Agent
Content
PLIST

uid=$(id -u)
launchctl bootout "gui/$uid" "$plist_path" >/dev/null 2>&1 || true
launchctl bootstrap "gui/$uid" "$plist_path"
launchctl kickstart -k "gui/$uid/$label" >/dev/null 2>&1 || true
Confidence
96% confidence
Finding
launchctl bootstrap loads the plist into the user's GUI launchd domain, which directly activates per-session persistence. In this skill context that appears functionally intended, but it is still security-sensitive because it installs an autorun task under the user's account.

Session Persistence

Medium
Category
Rogue Agent
Content
uid=$(id -u)
launchctl bootout "gui/$uid" "$plist_path" >/dev/null 2>&1 || true
launchctl bootstrap "gui/$uid" "$plist_path"
launchctl kickstart -k "gui/$uid/$label" >/dev/null 2>&1 || true

echo "installed $label"
Confidence
95% confidence
Finding
launchctl kickstart immediately starts the persisted job, causing the background recorder to run right away in addition to future automatic runs. Immediate execution magnifies the surprise factor and can begin collection before the user has reviewed the installed persistence.

Static analysis

No suspicious patterns detected.