Back to skill

Security audit

openclaw's digital card

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed OpenClaw profile-card generator, but it uses sensitive local profile and memory excerpts, so users should review privacy implications before running it.

Install only if you are comfortable with a card generator reading OpenClaw profile, identity, memory, skills, and session metadata. Before using a cloud model, review USER.md, IDENTITY.md, and MEMORY.md for sensitive content, prefer local or explicitly chosen excerpts when possible, clean up temporary JSON/HTML files, and only use trusted background image URLs or local image paths.

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 (2)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/collect-data.py:331
Finding
Excessive Collection and Cloud Disclosure of Local Identity and Memory Content<![CDATA[ ## Vulnerability Details **File Location**: `scripts/collect-data.py:331-333`; related data-flow instructions at `SKILL.md:121,137-139,252` **Vulnerability Type**: Excessive sensitive-data collection and disclosure **Risk Level**: Medium ### Vulnerable Code ```python return { 'recent_focus_fallback': get_recent_focus_fallback(), 'openclaw_review_fallback': '一个对 AI 有自己想法的人。', 'memory_bullets': get_memory_bullets(), # 以下为 AI 生成 comment/review 的完整素材 'user_md_excerpt': user_md[:2000] if user_md else '', 'identity_md_excerpt': identity_md[:1000] if identity_md else '', 'memory_md_excerpt': memory_md[:2000] if memory_md else '', 'stats_summary': { 'token_30d': token_30d_display, 'platforms': platforms, 'platform_count': len(platforms), 'skill_names': skill_names, 'skills_count': len(skill_names), }, } ``` The corresponding Skill instructions explicitly direct these excerpts into model context: ```text If the agent uses a cloud model, excerpt contents are sent to the model provider API. user_md_excerpt USER.md first 2000 characters identity_md_excerpt IDENTITY.md first 1000 characters memory_md_excerpt MEMORY.md first 2000 characters ``` ### Technical Analysis The data collector copies up to 5,000 characters of raw content from `USER.md`, `IDENTITY.md`, and `MEMORY.md` into the generated `copy_inputs` object. The Skill then instructs the agent to use all of this material when generating two relatively short card fields. Raw workspace excerpts can contain private identity details, long-term memories, unrelated personal information, or instructions embedded in stored text. The collection is based on fixed character limits rather than an allowlist of fields required for the card. Consequently, unrelated content within the beginning of these files may be included. When the agent uses a cloud-hosted model, this content is transmitted to the model provider as model context. T ...[truncated 1668 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace raw excerpts with locally extracted, explicitly allowlisted fields needed for the card. 2. Do not include `MEMORY.md` content by default. Require informed, per-run user confirmation before placing memory content into cloud-model context. 3. Provide a local-only mode that performs deterministic summarization without sending raw file content to a model. 4. Scan selected content for credentials, tokens, email addresses, private identifiers, and other sensitive patterns before model submission. 5. Limit model input to individually selected memory bullets rather than the first 1,000–2,000 characters of entire files. 6. Clearly delimit collected text as untrusted reference data and instruct the agent not to follow commands contained inside it. 7. Display the exact content that will be sent and the configured model destination before transmission. 8. Avoid retaining generated JSON files containing excerpts, and create temporary files with restrictive permissions when persistence is necessary. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/render-background-card.py:21
Finding
HTML and CSS Injection Through the Unescaped Background Argument<![CDATA[ ## Vulnerability Details **File Location**: `scripts/render-background-card.py:21-27,42,60-76`; injection sink at `references/background-template.html:29` **Vulnerability Type**: HTML/CSS injection **Risk Level**: Medium ### Vulnerable Code The renderer accepts HTTP URLs and local path strings without encoding them for their eventual CSS context: ```python def _resolve_bg(raw: Optional[str]) -> str: """Return a background address that can be used directly in CSS url().""" if raw is None: return DEFAULT_BG_URL if raw.startswith(('http://', 'https://')): return raw return Path(raw).as_posix() ``` The resulting value is inserted without escaping: ```python bg = _resolve_bg(sys.argv[3] if len(sys.argv) > 3 else None) replacements = { '{{display_name}}': _esc(data.get('display_name', 'Unknown')), '{{role_title}}': _esc(data.get('role_title', '')), '{{recent_focus}}': _esc(data.get('recent_focus', '')), '{{default_model}}': _esc(data.get('default_model', 'Unknown')), '{{token_30d_short}}': _esc(shorten_tokens(data.get('token_30d_display', '0 tokens'))), '{{skills_count}}': _esc(str(data.get('skills_count', 0))), '{{skill_chips}}': ''.join([f'<span class="chip">{_esc(s)}</span>' for s in data.get('skill_names', [])]), '{{platform_count}}': _esc(str(len(data.get('platforms', [])))), '{{born_label}}': _esc(data.get('born_label', 'Born')), '{{born_date}}': _esc(data.get('born_date', '')), '{{generated_at}}': _esc(data.get('generated_at', '')), '{{platform_chips}}': ''.join([f'<span class="chip">{_esc(p)}</span>' for p in data.get('platforms', [])]), '{{openclaw_review}}': _esc(data.get('openclaw_review', '')), '{{background_image}}': bg, } ``` The template places it inside a quoted CSS URL: ```html background-image: linear-gradient(90deg, rgba(7,10,14,0.72) 0%, rgba(7,10,14,0.44) 34%, rgba(7,10,14,0.10) 60%, rgba(7,10,14,0.08) 100%), linear-gradient(180deg, rgba(7 ...[truncated 2321 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Restrict remote backgrounds to parsed `https` URLs with an explicit hostname allowlist. 2. Resolve local paths and verify that they refer to expected regular image files. 3. Reject control characters and CSS/HTML delimiters, including quotes, parentheses, angle brackets, semicolons, backslashes, and line breaks where they are not valid. 4. Serialize the value with a dedicated CSS string or URL encoder rather than HTML escaping alone. 5. Prefer converting local images to validated `data:` URLs after checking MIME type, extension, and file size. 6. Avoid raw template substitution into executable contexts. Pass validated data through a structured renderer or set the background using a constrained runtime API. 7. Add a restrictive Content Security Policy that disables scripts and limits image/font connections to approved sources. 8. Add regression tests using values containing quotes, closing parentheses, `</style>`, encoded delimiters, and malformed URLs. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (19)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The description frames the skill as a read-only card generator, but the documented behavior includes extracting large excerpts from `USER.md`, `IDENTITY.md`, and `MEMORY.md`, enumerating installed skills, inferring first-run dates from session history, and packaging these into structured outputs for LLM use. This mismatch is dangerous because users may consent to a cosmetic rendering task without realizing the skill performs broader local profiling and may send excerpts to a cloud model via the agent runtime.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
The description frames the skill as a read-only card generator, but the documented behavior includes extracting large excerpts from `USER.md`, `IDENTITY.md`, and `MEMORY.md`, enumerating installed skills, inferring first-run dates from session history, and packaging these into structured outputs for LLM use. This mismatch is dangerous because users may consent to a cosmetic rendering task without realizing the skill performs broader local profiling and may send excerpts to a cloud model via the agent runtime.

Ae1

High
Category
analysis-evasion
Content
数据采集和 HTML 预览(`collect-data.py`、`render-background-card.py`)仅需 Python 3.10+。
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
数据采集和 HTML 预览(`collect-data.py`、`render-background-card.py`)仅需 Python 3.10+。
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
数据采集和 HTML 预览(`collect-data.py`、`render-background-card.py`)仅需 Python 3.10+。
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
数据采集和 HTML 预览(`collect-data.py`、`render-background-card.py`)仅需 Python 3.10+。
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
数据采集和 HTML 预览(`collect-data.py`、`render-background-card.py`)仅需 Python 3.10+。
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Lp3

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding
The skill declares no explicit tool scope even though its documented workflow clearly includes reading sensitive local files and writing temporary JSON/HTML outputs outside the skill directory. Without a restrictive permission declaration, an agent runtime may grant broader-than-necessary file access, increasing the chance of unintended data exposure from `~/.openclaw` workspace and session artifacts.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The primary description text forces a specific language/locale for users without indicating that Chinese is optional or user-selected. Under the policy, language constraints should either be optional or clearly justified as region-specific.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The HTML root element sets lang="zh-CN", which imposes a specific language/locale in a file that otherwise contains English UI text and provides no opt-in or explanation. This matches the policy category for forcing a locale without user choice.

Ssd 3

Medium
Confidence
93% confidence
Finding
These lines define AI-generated fields sourced from USER.md, IDENTITY.md, MEMORY.md, memory bullets, and stats summaries, which creates a direct natural-language exfiltration path from private local documents into rendered output. Because summarization and commentary can restate or infer sensitive facts, the danger is not only verbatim leakage but also derived disclosure of personal profile and behavioral data.

Ssd 3

Medium
Confidence
91% confidence
Finding
The execution flow states that collected local-file material is fed to the AI and then written back into JSON for rendering, formalizing a pipeline that transforms sensitive inputs into visible artifacts. This is risky because the output JSON/HTML/PNG may persist, be shared, or be inspected later, extending the exposure of data drawn from personal files.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The documented flow explicitly reads personal workspace, identity, memory, and session files and passes excerpts into an AI step, but the file shows no user-facing consent, minimization, or warning boundary around that data use. Even in a local-only skill, this creates a privacy vulnerability because sensitive content can be unintentionally surfaced in generated card text or logs beyond what the user expected from 'generate a card'.

Ssd 3

Medium
Confidence
90% confidence
Finding
The dependency summary confirms that personal and memory files are intentional AI source material, reinforcing that the skill is designed to ingest sensitive local context that may be surfaced in generated content. In the context of a personal card generator, this makes disclosure more dangerous because the final artifact is specifically meant for presentation and possible sharing.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
This script embeds natural-language content in Chinese, including a Chinese-only docstring fallback description and later a hard-coded Chinese review string. Because the file provides no user opt-in or locale-selection mechanism, it appears to force a specific language, which matches the language/locale policy violation criteria.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The script goes beyond the stated scope of reading identity info, config, and session statistics by collecting excerpts from USER.md, IDENTITY.md, MEMORY.md, and memory bullet content into copy_inputs for downstream generation. Even if it does not exfiltrate data itself, this broad aggregation increases exposure of sensitive personal context and creates a mismatch between declared behavior and actual data access, which can lead to overcollection and unintended disclosure in rendered outputs or later pipeline stages.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The value '一个对 AI 有自己想法的人。' is emitted as part of output data and is clearly user-facing natural language. Since the script does not provide any language preference handling or opt-in, this constitutes a likely locale policy violation under the stated rules.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The manifest describes the skill as operating in '只读模式' while this script writes a rendered HTML file to the user-supplied output path. Although rendering an HTML preview is within the feature set, the explicit read-only claim creates a semantic mismatch because the code performs filesystem writes.

Intent-Code Divergence

Low
Confidence
76% confidence
Finding
The docstring emphasizes a privacy-limited approach for session parsing, stating that no message body or other sensitive content is extracted. While that is true for this function itself, the overall script later collects sizeable excerpts from USER.md, IDENTITY.md, and MEMORY.md as generation material, which undercuts the file’s privacy-minimizing intent as documented. This creates an intent mismatch at the documentation level within the script.

Static analysis

No suspicious patterns detected.