Back to skill

Security audit

clawlens

Security checks for vulnerabilities and agentic risk

Overview

Clawlens is a coherent usage-report skill, but it reads private OpenClaw history and stored provider credentials and sends transcript-derived content to external LLMs with weak runtime controls.

Install only if you are comfortable sending selected OpenClaw conversation history, including possible tool-output excerpts, to the chosen LLM provider. Prefer running with a clearly chosen provider, a short --days window, and Markdown output; avoid HTML reports for untrusted session content, and review OpenClaw provider configuration before using auto-detect.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (3)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/clawlens.py:828
Finding

External Transmission of Sensitive Conversation Records Without Local Redaction

Content
View full analysis
list[dict]: """Read a JSONL file, skip malformed lines.""" entries: list[dict] = [] try: with open(filepath, "r", encoding="utf-8") as f: for line_num, line in enumerate(f, 1): line = line.strip() if not line: continue try: entries.append(json.loads(line)) except json.JSONDecodeError: log(f" Skipping malformed line {line_num} in {filepath.name}") ``` ```python def collect_sessions(agent_id: str, days: int, max_sessions: int) -> list[SessionMeta]: """Stage 1: Scan session files and extract metadata.""" base_dir = Path.home() / ".openclaw" / "agents" / agent_id / "sessions" ``` ```python async def llm_call(prompt: str, model: str, max_tokens: int = 4096, retries: int = 3) -> str: """Make an LLM call via litellm with retry.""" kwargs: dict[str, Any] = dict( model=model, messages=[{"role": "user", "content": prompt}], max_tokens=max_tokens, temperature=0.3, ) if _model_api_base: kwargs["api_base"] = _model_api_base if _model_api_key: kwargs["api_key"] = _model_api_key for attempt in range(retries + 1): try: response = await litellm.acompletion(**kwargs) ``` ```python prompt = FACET_EXTRACTION_PROMPT.replace("{transcript}", transcript) try: raw = await llm_call(prompt, model, max_tokens=2048) ``` ### Technical Analysis The skill reads OpenClaw session JSONL files and constructs transcript text containing user messages, assistant messages, tool calls, and excerpts fro ...[truncated 1923 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/clawlens.py:287
Finding

Configuration-Controlled API Endpoint Can Receive OpenClaw Credentials and Transcripts

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/clawlens.py:2064
Finding

Unsanitized LLM-Generated Markdown Enables Active Content in HTML Reports

Content
View full analysis
str: """Convert a Markdown string to HTML. Falls back to
text
 if markdown lib unavailable."""
    try:
        import markdown
        md = markdown.Markdown(extensions=["tables", "fenced_code"])
        result = md.convert(md_text)
        md.reset()
        return result
    except ImportError:
        # Fallback: wrap in 
text
 with basic escaping
        return f"
text
{_esc(md_text)}
" ``` ```python # Build section HTML sections_html = [] for i, dim in enumerate(sections, 1): sid = section_ids.get(dim, dim) heading = section_keys_to_labels.get(dim, dim) md_content = dimension_outputs.get(dim, "") content_html = _md_to_html(md_content) # Insert data visuals before LLM prose for relevant sections visuals = "" if dim == "usage_overview": time_charts = "" if hour_chart or weekday_chart: if hour_chart and weekday_chart: time_charts = f'
{hour_chart}{weekday_chart}
' else: time_charts = hour_chart or weekday_chart visuals = stat_cards + model_tags + time_charts elif dim == "task_classification": visuals = task_bars elif dim == "friction_analysis": visuals = friction_split elif dim == "channel_analysis": visuals = channel_bars sections_html.append( f'
' f'

0{i}{_esc(heading)}

' f'{visuals}' f'
{content_html}
' f'
' ) ``` ```python # Glance section glance_html = "" if at_a_glance: glance_content = _md_to_h ...[truncated 2516 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (17)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The description frames the skill as a personal retrospective tool, but the documented behavior includes reading authentication-related files and sending conversation-derived content to an external LLM provider. That mismatch can mislead users into granting access without realizing that sensitive local data and transcript content may be exfiltrated to third parties.

Content

No source excerpt is available for this finding.

External Model or Provider Selection

High
Category
Excessive Agency
Confidence
96% confidence
Finding

The skill allows user-selected external model/providers and documents sending transcript summaries and session-derived content to those providers. Provider selection expands the data-exfiltration surface and trust boundary, and different providers may have different retention, logging, or jurisdictional risks.

Content

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

md
python3 scripts/clawlens.py --lang en --days 7

# Manually specify model (DeepSeek)
DEEPSEEK_API_KEY=sk-xxx python3 scripts/clawlens.py --model deepseek/deepseek-chat

# OpenAI, English, last 7 days
OPENAI_API_KEY=sk-xxx python3 scripts/clawlens.py --model openai/gpt-4o --lang en --days 7

External Model or Provider Selection

High
Category
Excessive Agency
Confidence
96% confidence
Finding

The HTML-report example reinforces that the skill can package analyzed content and use a selected third-party provider for generation, again extending sensitive data exposure beyond the local environment. The vulnerability is not the example itself but the underlying capability to send user-derived content to arbitrary external LLM services.

Content

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

ANTHROPIC_API_KEY=sk-xxx python3 scripts/clawlens.py --model anthropic/claude-sonnet-4-20250514 --verbose -o /tmp/clawlens-report.md

HTML report (dark-themed, self-contained)

DEEPSEEK_API_KEY=sk-xxx python3 scripts/clawlens.py --model deepseek/deepseek-chat --format html -o /tmp/clawlens-report.html

text

## Output

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code reads API credentials from local OpenClaw auth profiles and uses them to contact external LLM providers. Accessing secrets and enabling outbound transmission is a major capability expansion over a local retrospective-analysis tool, and it can expose sensitive conversation data to third parties without clear informed consent.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The tool forwards full conversation transcripts, including user text, assistant content, tool calls, and tool results, to an external LLM in plain prompts across multiple pipeline stages. Because transcripts may contain private personal data, credentials, internal file contents, or service responses, this is a significant data exfiltration and privacy risk.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The manifest suggests retrospective analysis of local conversation history, but the implementation sends transcript content to an external LLM for analysis. This is a substantive undisclosed data flow involving potentially sensitive user messages, assistant replies, and tool interactions.

Content

No source excerpt is available for this finding.

External Model or Provider Selection

High
Category
Excessive Agency
Confidence
90% confidence
Finding

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.

Content

Scanner excerpt · scripts/clawlens.py (reported line 2328)May include surrounding context.

python
epilog="""Examples:
  python3 clawlens.py --verbose                          # auto-detect model from OpenClaw config
  python3 clawlens.py --lang en --days 7                 # auto-detect, English, last 7 days
  DEEPSEEK_API_KEY=sk-xxx python3 clawlens.py --model deepseek/deepseek-chat
  OPENAI_API_KEY=sk-xxx python3 clawlens.py --model openai/gpt-4o --lang en --days 7
  ANTHROPIC_API_KEY=sk-xxx python3 clawlens.py --model anthropic/claude-sonnet-4-20250514 --verbose -o report.md
  DEEPSEEK_API_KEY=sk-xxx python3 clawlens.py --model deepseek/deepseek-chat --format html -o report.html

External Model or Provider Selection

High
Category
Excessive Agency
Confidence
90% confidence
Finding

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.

Content

Scanner excerpt · scripts/clawlens.py (reported line 2331)May include surrounding context.

python
DEEPSEEK_API_KEY=sk-xxx python3 clawlens.py --model deepseek/deepseek-chat
  OPENAI_API_KEY=sk-xxx python3 clawlens.py --model openai/gpt-4o --lang en --days 7
  ANTHROPIC_API_KEY=sk-xxx python3 clawlens.py --model anthropic/claude-sonnet-4-20250514 --verbose -o report.md
  DEEPSEEK_API_KEY=sk-xxx python3 clawlens.py --model deepseek/deepseek-chat --format html -o report.html
""",
    )
    parser.add_argument("--agent-id", default="main", help="Agent ID (default: main)")

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill declares powerful capabilities in metadata (file reads/writes and external API use) but does not define any explicit tool scope or permission boundary. This increases the chance of over-broad execution and weak user understanding of what the skill can access, especially because it reads session history, skills directories, config, and auth-profile files.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The trigger phrases are broad enough to match ordinary conversation, which can cause accidental invocation of a skill that reads private history and transmits analysis data externally. In this context, ambiguous activation is more dangerous because the skill handles sensitive conversation logs and may auto-select a model/provider.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The instructions say the agent "must ask the user" using a fixed Chinese prompt, which imposes a language choice regardless of user preference. This is a natural-language policy concern because the skill does not offer opt-in or an alternate localized prompt for users who are not Chinese speakers.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The sample report structure is defined with Chinese headings and content labels, which establishes a default output locale. Because the file does not present this as optional or region-specific, it can conflict with a policy requiring language choice rather than forcing a locale.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

When transcripts are long, the tool chunks and uploads them for summarization without any specific disclosure. Chunking does not reduce the privacy risk; it still transfers sensitive content externally and may increase exposure by making multiple requests.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Report generation uses aggregated session data and previously extracted content derived from transcripts, but there is no user-facing warning that conversation contents are sent to an external LLM. This creates a transparency and consent failure around sensitive data handling.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill claims to analyze conversation history, but it also inventories globally installed skills from ~/.openclaw/skills. That expands data collection beyond the stated purpose and can reveal unrelated local environment information, violating least-privilege and user expectations.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The CLI sets --lang default to zh, so the tool will produce Chinese output unless the user overrides it. Because the default forces a specific language rather than asking or inferring user preference with opt-in, it can violate language/locale choice expectations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script accesses local auth-profiles.json to retrieve API keys or OAuth tokens without clearly notifying the user. Even if used only for intended API calls, silent secret access is risky because it broadens trust requirements and may surprise users reviewing a skill described as analytics/reporting.

Content

No source excerpt is available for this finding.