Back to skill

Security audit

OpenClaw Token Usage

Security checks for vulnerabilities and agentic risk

Overview

The skill is a transparent local OpenClaw token-usage reporter, with manageable cautions around transcript privacy and CSV exports.

Install only if you are comfortable letting the skill read local OpenClaw transcript metadata across agents. Use --agents, --providers, --models, and explicit date ranges to narrow scope, confirm the timezone, and treat CSV exports as sensitive unless the transcript source is trusted or formula-prefixed cells are sanitized before opening in a spreadsheet.

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/report_openclaw_token_usage.py:328
Finding

Spreadsheet Formula Injection in CSV Exports

Content
View full analysis
list[Path]: out_dir.mkdir(parents=True, exist_ok=True) written: list[Path] = [] def write_csv(path: Path, header: list[str], rows: list[list[object]]) -> None: with path.open('w', encoding='utf-8', newline='') as f: writer = csv.writer(f) writer.writerow(header) writer.writerows(rows) written.append(path) summary = data['summary'] write_csv( out_dir / 'summary.csv', ['timezone', 'start', 'end', 'input', 'output', 'cacheRead', 'cacheWrite', 'totalTokens', 'messages'], [[ data['assumption_timezone'], data['range_local']['start'], data['range_local']['end'], summary['input'], summary['output'], summary['cacheRead'], summary['cacheWrite'], summary['totalTokens'], summary['messages'] ]], ) rows = [] for day, agents in data['by_day_agent'].items(): for agent, m in agents.items(): rows.append([day, agent, m['input'], m['output'], m['cacheRead'], m['cacheWrite'], m['totalTokens'], m['messages']]) write_csv(out_dir / 'by_day_agent.csv', ['day', 'agent', 'input', 'output', 'cacheRead', 'cacheWrite', 'totalTokens', 'messages'], rows) rows = [] for agent, m in data['by_agent'].items(): rows.append([agent, m['input'], m['output'], m['cacheRead'], m['cacheWrite'], m['totalTokens'], m['messages']]) write_csv(out_dir / 'by_agent.csv', ['agent', 'input', 'output', 'cacheRead', 'cacheWrite', 'totalTokens', 'messages'], rows) rows = [] for model, m in data['by_model'].items(): rows.append([model, m['input'], m['output'], m['cacheRead'], m['cacheWrite'], m['totalTokens'], m['messages']]) write ...[truncated 3827 chars]
Remediation
View remediation
object: if not isinstance(value, str): return value probe = value.lstrip(' \t\r\n') if probe.startswith(FORMULA_PREFIXES): return "'" + value return value def write_csv(path: Path, header: list[str], rows: list[list[object]]) -> None: safe_header = [spreadsheet_safe(value) for value in header] safe_rows = [ [spreadsheet_safe(value) for value in row] for row in rows ] with path.open('w', encoding='utf-8', newline='') as f: writer = csv.writer(f) writer.writerow(safe_header) writer.writerows(safe_rows) ``` Add regression tests for: - Each dangerous prefix: `=`, `+`, `-`, and `@` - Dangerous prefixes preceded by spaces, tabs, or carriage returns - Formula-like agent names, providers, models, session keys, and filenames - Ordinary text and numeric metrics to ensure they remain unchanged - CSV files opened in the spreadsheet applications supported by the project Documentation should also warn users that previously generated CSV files may contain ...[truncated 120 chars]
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • 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 (4)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill instructs the agent to read local transcript files and optionally write JSON, CSV, or Markdown outputs, but it declares no explicit tool scope such as permissions or allowed-tools. That creates an authorization gap where an orchestrator may permit broader file access than the skill actually needs, increasing the chance of unintended reads or writes involving sensitive local data.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest description says to use the skill when the user asks 'how many tokens were consumed in OpenClaw' or 'wants usage broken down by day, agent, provider, model, session, rankings, CSV exports, or markdown reports.' This is broad natural-language activation guidance without clear boundaries or negative examples, which can cause unintended invocation for generic reporting requests.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This Python file contains multiple user-facing messages in Chinese, including fatal error text, CLI help strings, and console summaries. Because the skill forces a specific language for interaction without any user opt-in or documented regional justification, it conflicts with the natural-language policy requirement to avoid fixed language constraints.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The workflow instructs the skill to use 'UTC+8' unless the user asks otherwise. This sets a locale-related default on the user's behalf rather than first confirming or offering a choice, which can conflict with language/locale policy expectations.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.