Back to skill

Security audit

Agent Token Usage

Security checks for vulnerabilities and agentic risk

Overview

The skill's token reporting purpose is coherent, but the optional UI installer makes persistent and broad local UI changes that users should review first.

Install the CLI portion only if you just need token summaries. Before running apply-ui.sh, review that it will patch discovered OpenClaw Control UI installs, add a macOS LaunchAgent that refreshes every 5 minutes, and uninstall by removing the UI data directory. Avoid the UI patch in environments where local agent names or generated data files could be influenced by untrusted users until the HTML rendering is escaped or rebuilt with DOM text APIs.

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/token-usage-button.iife.js:104
Finding

Stored DOM XSS Through Unescaped Agent Names

Content
View full analysis
{ const pct = Math.round(((a.total || 0) / max) * 100); const bar = ``; return ` ${a.agent}${bar} ${a.calls || 0} ${fmt(a.input)} ${fmt(a.output)} ${fmt(a.cacheRead)} ${fmt(a.cacheWrite)} ${fmt(a.total)} ${fmt(a.billable)} `; }).join(""); ``` The generated markup is subsequently assigned to `innerHTML`: ```javascript const resp = await fetch(DATA_URL + "?t=" + Date.now(), { cache: "no-cache" }); if (!resp.ok) throw new Error("HTTP " + resp.status + " — " + DATA_URL); const data = await resp.json(); body.innerHTML = render(data); ``` ### Technical Analysis The `a.agent` value is not a trusted constant. The Python aggregator derives it from a directory name beneath `~/.openclaw/agents` and includes it directly in the generated JSON: ```python agent = path.split(os.sep + "agents" + os.sep)[1].split(os.sep)[0] ``` The browser payload interpolates this value into an HTML template without escaping and assigns the result to `body.innerHTML`. Consequently, markup contained in an agent directory name or in a tampered `agent-token-usage.json` file is interpreted as HTML rather than displayed as text. A malicious value can inject arbitrary elements into the token-usage modal. Depending on the Control UI Content Security Policy and browser enforcement, an event-handler or equivalent browser-compatible payload may execute JavaScript. Even where CSP blocks script execution, arbitrary HTML injection remains possible and can be used for UI spoofing, misleading link ...[truncated 2318 chars]
Remediation
View remediation
`, `"`, and `'`. A maintained sanitizer may be used only when intentional HTML support is required. 6. **Apply a restrictive Control UI CSP** that disallows inline script, inline event handlers, `javascript:` navigation, and unauthorized network destinations. CSP should be treated as defense in depth rather than the primary fix. 7. **Protect the generated data file.** Ensure it is writable only by the intended user or service and served only through the authenticated Control UI. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (28)

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · remove-ui.sh (reported line 6)May include surrounding context.

sh
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LABEL="com.symbolstar.openclaw.token-usage-refresh"
PLIST="$HOME/Library/LaunchAgents/$LABEL.plist"
[[ -f "$PLIST" ]] && { launchctl unload "$PLIST" 2>/dev/null || true; rm -f "$PLIST"; echo "✓ launchd removed"; }

ROOTS=()
if command -v npm >/dev/null 2>&1; then

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · apply-ui.sh (reported line 77)May include surrounding context.

sh
ORIG="${BAK%.tk.bak}"
      [[ "$ORIG" == *.tk-*.js ]] && ORIG_BASE="${ORIG%.tk-*}.js" || ORIG_BASE="$ORIG"
      mv "$BAK" "$ORIG_BASE"
      [[ "$ORIG" != "$ORIG_BASE" && -f "$ORIG" ]] && rm -f "$ORIG"
      echo "✓ restored $ORIG_BASE"
    done
    [[ -f "$INDEX.tk.bak" ]] && { mv "$INDEX.tk.bak" "$INDEX"; echo "✓ restored $INDEX"; }

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · remove-ui.sh (reported line 29)May include surrounding context.

sh
ORIG="${BAK%.tk.bak}"
      [[ "$ORIG" == *.tk-*.js ]] && ORIG_BASE="${ORIG%.tk-*}.js" || ORIG_BASE="$ORIG"
      mv "$BAK" "$ORIG_BASE"
      [[ "$ORIG" != "$ORIG_BASE" && -f "$ORIG" ]] && rm -f "$ORIG"
      echo "✓ restored $ORIG_BASE"
    done
    [[ -f "$INDEX.tk.bak" ]] && { mv "$INDEX.tk.bak" "$INDEX"; echo "✓ restored $INDEX"; }

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · remove-ui.sh (reported line 33)May include surrounding context.

sh
ORIG="${BAK%.tk.bak}"
      [[ "$ORIG" == *.tk-*.js ]] && ORIG_BASE="${ORIG%.tk-*}.js" || ORIG_BASE="$ORIG"
      mv "$BAK" "$ORIG_BASE"
      [[ "$ORIG" != "$ORIG_BASE" && -f "$ORIG" ]] && rm -f "$ORIG"
      echo "✓ restored $ORIG_BASE"
    done
    [[ -f "$INDEX.tk.bak" ]] && { mv "$INDEX.tk.bak" "$INDEX"; echo "✓ restored $INDEX"; }

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

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).

Content

Scanner excerpt · remove-ui.sh (reported line 33)May include surrounding context.

sh
echo "✓ restored $ORIG_BASE"
    done
    [[ -f "$INDEX.tk.bak" ]] && { mv "$INDEX.tk.bak" "$INDEX"; echo "✓ restored $INDEX"; }
    [[ -d "$BASE/data" ]] && rm -rf "$BASE/data" && echo "✓ removed $BASE/data"
  done
done

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 3)May include surrounding context.

md
---
name: agent-token-usage
description: Summarize per-agent LLM token consumption for OpenClaw multi-agent setups by parsing `~/.openclaw/agents/*/sessions/<id>.jsonl` session logs (type=message, role=assistant). Ships both a CLI (Python) and an optional 📊 button injected into the Control UI header next to Search. Use when the user asks "今天哪个 agent 用了多少 token / 消耗了多少 token / token 排行 / token 统计 / how much did agent X spend today / which agent burns the most tokens / token usage breakdown / billable token estimate", or asks to install/remove the 📊 token-usage button in Control UI. Returns a ranked table with input / output / cacheRead / cacheWrite / total (and equivalent-billable token estimate). NOT for: dollar cost (use codexbar/model-usage skill), per-message inspection (use sessions_history), or non-OpenClaw runtimes.
---

# agent-token-usage 📊

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script presents itself as an optional UI patch, but on macOS it also installs a persistent LaunchAgent that executes every 5 minutes. That mismatch is security-relevant because it obscures ongoing system modification and background execution beyond a one-time UI change, reducing informed user consent and increasing the chance of unnoticed persistence.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script appends code into an existing OpenClaw bundle, renames assets/index references, creates backup files, writes data files, and may install a recurring LaunchAgent, all without a prompt or strong upfront warning. Silent persistent modification of another application's installation increases integrity and persistence risk, especially in a skill context where users may expect helper automation rather than system-level alteration.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script writes a user LaunchAgent plist and loads it with launchctl, creating recurring execution at login/session scope. Persistent background execution is a sensitive capability and is not necessary for a one-time UI patch unless explicitly justified and consented to, so this is a real security concern even if the apparent purpose is token-usage refresh.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
82% confidence
Finding

This finding appears to be a duplicate lexical match on the plist file path rather than a distinct security issue beyond the broader LaunchAgent persistence. The underlying concern is real, but this specific duplicate hit does not add a separate vulnerability.

Content

Scanner excerpt · apply-ui.sh (reported line 96)May include surrounding context.

sh
if [[ "$OSTYPE" == "darwin"* ]]; then
  LABEL="com.symbolstar.openclaw.token-usage-refresh"
  PLIST="$HOME/Library/LaunchAgents/$LABEL.plist"
  mkdir -p "$HOME/Library/LaunchAgents" "$HOME/.openclaw/logs"
  cat > "$PLIST" <<EOF
<?xml version="1.0" encoding="UTF-8"?>

Session Persistence

Medium
Category
Rogue Agent
Confidence
82% confidence
Finding

This finding appears to be a duplicate lexical match on the plist file path rather than a distinct security issue beyond the broader LaunchAgent persistence. The underlying concern is real, but this specific duplicate hit does not add a separate vulnerability.

Content

Scanner excerpt · apply-ui.sh (reported line 96)May include surrounding context.

sh
if [[ "$OSTYPE" == "darwin"* ]]; then
  LABEL="com.symbolstar.openclaw.token-usage-refresh"
  PLIST="$HOME/Library/LaunchAgents/$LABEL.plist"
  mkdir -p "$HOME/Library/LaunchAgents" "$HOME/.openclaw/logs"
  cat > "$PLIST" <<EOF
<?xml version="1.0" encoding="UTF-8"?>

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

Writing the plist contents to disk defines a recurring job specification for launchd. This is a concrete persistence mechanism and should be treated as a real security-relevant behavior because it causes future execution outside the original invocation flow.

Content

Scanner excerpt · apply-ui.sh (reported line 98)May include surrounding context.

sh
LABEL="com.symbolstar.openclaw.token-usage-refresh"
  PLIST="$HOME/Library/LaunchAgents/$LABEL.plist"
  mkdir -p "$HOME/Library/LaunchAgents" "$HOME/.openclaw/logs"
  cat > "$PLIST" <<EOF
<?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">

Session Persistence

Medium
Category
Rogue Agent
Confidence
78% confidence
Finding

This repeated match again points to the plist content section and does not represent a separate vulnerability from the same persistence mechanism. It is a true signal but duplicative.

Content

Scanner excerpt · apply-ui.sh (reported line 100)May include surrounding context.

sh
mkdir -p "$HOME/Library/LaunchAgents" "$HOME/.openclaw/logs"
  cat > "$PLIST" <<EOF
<?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>$LABEL</string>

Session Persistence

Medium
Category
Rogue Agent
Confidence
78% confidence
Finding

This repeated match again points to the plist content section and does not represent a separate vulnerability from the same persistence mechanism. It is a true signal but duplicative.

Content

Scanner excerpt · apply-ui.sh (reported line 100)May include surrounding context.

sh
mkdir -p "$HOME/Library/LaunchAgents" "$HOME/.openclaw/logs"
  cat > "$PLIST" <<EOF
<?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>$LABEL</string>

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

The ProgramArguments entry specifies execution of /bin/bash with the refresh script, which is the operative part of the persistent autorun job. This is dangerous because it schedules repeated script execution in the background, increasing the blast radius of any present or future issues in refresh-data.sh.

Content

Scanner excerpt · apply-ui.sh (reported line 101)May include surrounding context.

sh
cat > "$PLIST" <<EOF
<?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>$LABEL</string>
  <key>ProgramArguments</key>

Session Persistence

Medium
Category
Rogue Agent
Confidence
77% confidence
Finding

This match falls on the end of the plist block and is not a distinct vulnerability beyond the already identified LaunchAgent persistence. It is best understood as duplicate evidence of the same issue.

Content

Scanner excerpt · apply-ui.sh (reported line 111)May include surrounding context.

sh
<key>StandardOutPath</key><string>$HOME/.openclaw/logs/token-usage-refresh.log</string>
  <key>StandardErrorPath</key><string>$HOME/.openclaw/logs/token-usage-refresh.err.log</string>
</dict>
</plist>
EOF
  launchctl unload "$PLIST" 2>/dev/null || true
  launchctl load "$PLIST" && green "✓ launchd job installed (refreshes every 5min): $LABEL"

Session Persistence

Medium
Category
Rogue Agent
Confidence
79% confidence
Finding

This is another duplicate hit adjacent to launchctl usage and plist handling, not a separate vulnerability. The substantive concern remains user-session persistence via LaunchAgent installation.

Content

Scanner excerpt · apply-ui.sh (reported line 113)May include surrounding context.

sh
</dict>
</plist>
EOF
  launchctl unload "$PLIST" 2>/dev/null || true
  launchctl load "$PLIST" && green "✓ launchd job installed (refreshes every 5min): $LABEL"
fi

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% confidence
Finding

This duplicate match references the same launchctl/plist activation line and does not indicate a separate additional vulnerability. It should be merged with the primary RA2 finding at this location.

Content

Scanner excerpt · apply-ui.sh (reported line 114)May include surrounding context.

sh
</plist>
EOF
  launchctl unload "$PLIST" 2>/dev/null || true
  launchctl load "$PLIST" && green "✓ launchd job installed (refreshes every 5min): $LABEL"
fi

dim "  Refresh your Control UI tab. 📊 button appears next to Search."

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% confidence
Finding

This duplicate match references the same launchctl/plist activation line and does not indicate a separate additional vulnerability. It should be merged with the primary RA2 finding at this location.

Content

Scanner excerpt · apply-ui.sh (reported line 114)May include surrounding context.

sh
</plist>
EOF
  launchctl unload "$PLIST" 2>/dev/null || true
  launchctl load "$PLIST" && green "✓ launchd job installed (refreshes every 5min): $LABEL"
fi

dim "  Refresh your Control UI tab. 📊 button appears next to Search."

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% confidence
Finding

This duplicate match references the same launchctl/plist activation line and does not indicate a separate additional vulnerability. It should be merged with the primary RA2 finding at this location.

Content

Scanner excerpt · apply-ui.sh (reported line 114)May include surrounding context.

sh
</plist>
EOF
  launchctl unload "$PLIST" 2>/dev/null || true
  launchctl load "$PLIST" && green "✓ launchd job installed (refreshes every 5min): $LABEL"
fi

dim "  Refresh your Control UI tab. 📊 button appears next to Search."

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · remove-ui.sh (reported line 5)May include surrounding context.

sh
set -euo pipefail
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LABEL="com.symbolstar.openclaw.token-usage-refresh"
PLIST="$HOME/Library/LaunchAgents/$LABEL.plist"
[[ -f "$PLIST" ]] && { launchctl unload "$PLIST" 2>/dev/null || true; rm -f "$PLIST"; echo "✓ launchd removed"; }

ROOTS=()

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · remove-ui.sh (reported line 6)May include surrounding context.

sh
set -euo pipefail
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LABEL="com.symbolstar.openclaw.token-usage-refresh"
PLIST="$HOME/Library/LaunchAgents/$LABEL.plist"
[[ -f "$PLIST" ]] && { launchctl unload "$PLIST" 2>/dev/null || true; rm -f "$PLIST"; echo "✓ launchd removed"; }

ROOTS=()

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · remove-ui.sh (reported line 5)May include surrounding context.

sh
set -euo pipefail
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LABEL="com.symbolstar.openclaw.token-usage-refresh"
PLIST="$HOME/Library/LaunchAgents/$LABEL.plist"
[[ -f "$PLIST" ]] && { launchctl unload "$PLIST" 2>/dev/null || true; rm -f "$PLIST"; echo "✓ launchd removed"; }

ROOTS=()

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The script recursively deletes "$BASE/data" with rm -rf, which is a destructive operation affecting user/system files. While it prints a message after deletion, there is no prior warning, confirmation, or explanatory comment/docstring disclosing that this directory will be removed.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/token-usage-button.iife.js (reported line 114)May include surrounding context.

js
return `
      <h2>📊 Agent Token Usage <span style="font-weight:400;font-size:12px;color:var(--text-2,#888)">— ${date}</span></h2>
      <div class="milly-tk-meta">Last updated: ${updated} · ${agents.length} agents · ~bill weights: cacheRead ×0.1, cacheWrite ×1.25</div>
      ${agents.length === 0
        ? `<div class="milly-tk-empty">No usage records found for ${date}.<br>Run the scheduler or check <code>~/.openclaw/agents/*/sessions/*.trajectory.jsonl</code></div>`
        : `<table>