Back to skill

Security audit

Claw Friends

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its character/photo purpose, but it gives an agent sensitive API, billing, credential, and workspace-moving powers with insufficient safeguards.

Install only after reviewing the TuQu service-key and workspace risks. Use least-privileged disposable service keys, do not store keys in character workspaces, avoid recharge/payment flows unless directly requested, and treat /shift and delete operations as actions that should require explicit confirmation and trusted paths/IDs.

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

T09 · Insecure Skill Coding Practices

Error
Location
tuqu-photo-api/scripts/tuqu_request.py:118
Finding

Service credentials can be transmitted to arbitrary attacker-controlled hosts

Content
View full analysis
str: parsed = urllib.parse.urlparse(path) if parsed.scheme and parsed.netloc: return parsed.path or "/" return path.split("?", 1)[0] def match_endpoint_rule(path: str) -> tuple[str, str, str, str]: lookup_path = normalize_path(path) for rule in ENDPOINT_RULES: prefix = rule[0] if lookup_path == prefix or lookup_path.startswith(prefix + "/"): return rule raise ValueError( "This path is not covered by the helper. Pass --base-url and --auth-mode explicitly." ) ``` ```python def build_url(base_url: str, path: str, query_items: list[tuple[str, str]]) -> str: if path.startswith("http://") or path.startswith("https://"): base = path else: base = urllib.parse.urljoin(base_url.rstrip("/") + "/", path.lstrip("/")) if not query_items: return base separator = "&" if urllib.parse.urlparse(base).query else "?" return base + separator + urllib.parse.urlencode(query_items) ``` ```python auth_mode = args.auth_mode if auth_mode == "auto": auth_mode = detect_auth_mode(args.path) body = prepare_body(auth_mode, body, args.service_key) base_url = args.base_url or detect_base_url(args.path) headers = { "Accept": "application/json", } if auth_mode == "api-key": if not args.service_key: raise ValueError("Missing service key. Pass --service-key for this endpoint.") headers["x-api-key"] = args.service_key if auth_mode == "service-key": service_key = resolve_service_key(args.service_key, body, query_items) if not service_key: raise ValueError( "Missing service key. Pass --service-key, pass --query " "servic ...[truncated 2558 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
tuqu-photo-api/scripts/tuqu_request.py:151
Finding

Service keys are exposed through process arguments and URL query parameters

Content
View full analysis
str | None: if explicit_service_key: return explicit_service_key if isinstance(body, dict): for key in ("serviceKey", "userKey"): value = body.get(key) if isinstance(value, str) and value: return value for key in ("serviceKey", "userKey"): query_value = resolve_query_value(query_items, key) if query_value: return query_value return None ``` ```python def build_url(base_url: str, path: str, query_items: list[tuple[str, str]]) -> str: if path.startswith("http://") or path.startswith("https://"): base = path else: base = urllib.parse.urljoin(base_url.rstrip("/") + "/", path.lstrip("/")) if not query_items: return base separator = "&" if urllib.parse.urlparse(base).query else "?" return base + separator + urllib.parse.urlencode(query_items) ``` ```python if auth_mode == "service-key": service_key = resolve_service_key(args.service_key, body, query_items) if not service_key: raise ValueError( "Missing service key. Pass --service-key, pass --query " "serviceKey=..., or provide serviceKey in the JSON body." ) header ...[truncated 2217 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
openclaw-character-creator/references/agents_template.md:112
Finding

Generated runtime instructions expect plaintext service-key storage in persona workspaces

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
openclaw-character-creator/scripts/shift_role.py:94
Finding

Unvalidated role paths permit destructive movement of arbitrary user-accessible directories

Content
View full analysis
{workspace_path}") return for role in data["roles"]: if role["name"] == name: print(f"Warning: role '{name}' already exists at {role['workspacePath']}") print("Overwriting with new workspace path.") role["workspacePath"] = workspace_path save_roles(data) return data["roles"].append({"name": name, "workspacePath": workspace_path}) save_roles(data) print(f"Registered: {name} -> {workspace_path}") ``` Workspace state is also trusted without path validation: ```python def read_workspace_state(workspace_path): state_file = os.path.join(workspace_path, ".openclaw", "workspace-state.json") if os.path.exists(state_file): with open(state_file, "r", encoding="utf-8") as f: return json.load(f) return None ``` The active workspace is moved to an unvalidated state-controlled location: ```python if state and "originalWorkspacePath" in state: original_path = state["originalWorkspacePath"] if not original_path: for role in roles: if role["workspacePath"] == ACTIVE_WORKSPACE and role["name"] != target_name: safe_name = role["name"].lower().replace(" ", "-") original_path = os.path.join(OPENCLAW_DIR, f"workspace-{safe_name}-saved") break if not original_path: print("Error: ...[truncated 3500 chars]
Remediation
View remediation
-` naming pattern. 3. Verify containment using path-aware operations rather than string-prefix checks. 4. Reject symbolic links for source directories, destination directories, registry files, and workspace-state files. 5. Require a trusted workspace marker and validate its schema, ownership, and expected character identifier before moving a directory. 6. Reject `originalWorkspacePath` values outside the approved OpenClaw workspace root. 7. Validate `ROLES.json` structure and reject malformed or duplicate entries instead of trusting them. 8. Use transactional switching: - Prevalidate all sources and destinations. - Write registry updates atomically through a temporary file and rename. - Roll back filesystem moves if any later operation fails. 9. Prompt for explicit confirmation before moving a path that does not match a registered and validated workspace. 10. Add tests for path traversal, relative paths, symlinked paths, crafted state files, arbitrary directories, and partial-operation rollback. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (55)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill is described as enabling character selfies/photos, but the observed behavior includes generic API testing, auth validation, request construction, and error-handling infrastructure. While not inherently malicious, hidden authentication and request tooling broadens the operational surface and may enable actions beyond what the user expects from the description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill is described as enabling character selfies/photos, but the observed behavior includes generic API testing, auth validation, request construction, and error-handling infrastructure. While not inherently malicious, hidden authentication and request tooling broadens the operational surface and may enable actions beyond what the user expects from the description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill is described as enabling character selfies/photos, but the observed behavior includes generic API testing, auth validation, request construction, and error-handling infrastructure. While not inherently malicious, hidden authentication and request tooling broadens the operational surface and may enable actions beyond what the user expects from the description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill is described as enabling character selfies/photos, but the observed behavior includes generic API testing, auth validation, request construction, and error-handling infrastructure. While not inherently malicious, hidden authentication and request tooling broadens the operational surface and may enable actions beyond what the user expects from the description.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The documented recharge flows (/api/v1/recharge/wechat and /api/v1/recharge/stripe) are materially unrelated to a selfie/photo character skill and introduce direct payment initiation capability. In this context, an agent or downstream user could be induced to trigger financial actions with a provided service key, making the mismatch between stated purpose and actual capability especially dangerous.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
82% confidence
Finding

The skill exposes a destructive DELETE operation for /api/characters/<character-id> without documenting confirmation, ownership validation, or guardrails around user-provided identifiers. If the agent accepts an untrusted or ambiguous character ID, it could delete stored character assets or identities, causing irreversible data loss or cross-tenant harm depending on backend authorization.

Content

Scanner excerpt · tuqu-photo-api/SKILL.md (reported line 220)May include surrounding context.

python3 scripts/tuqu_request.py PUT /api/characters/
--service-key
--body-file payloads/update-character.json python3 scripts/tuqu_request.py DELETE /api/characters/
--service-key

text

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
81% confidence
Finding

The skill similarly exposes DELETE /api/history/<history-id> with no stated confirmation or parameter validation requirements. An agent using arbitrary or attacker-supplied history IDs could remove records unexpectedly, undermining auditability and causing unwanted loss of user data.

Content

Scanner excerpt · tuqu-photo-api/SKILL.md (reported line 245)May include surrounding context.

python3 scripts/tuqu_request.py POST /api/history
--service-key
--body-file payloads/history-item.json python3 scripts/tuqu_request.py DELETE /api/history/ --service-key python3 scripts/tuqu_request.py POST /api/billing/balance --service-key

text

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
86% confidence
Finding

An agent with access to this endpoint could delete characters by supplying an arbitrary id, making it susceptible to parameter abuse if the agent is over-permissioned or if IDs are inferred from prior listings. In this skill context, persistent character assets are central to functionality, so destructive API calls are more dangerous because they can silently remove user-created identities and disrupt downstream generation flows.

Content

Scanner excerpt · tuqu-photo-api/references/endpoints.md (reported line 335)May include surrounding context.

md
- `GET /api/characters?id=...`: fetch one character
- `POST /api/characters`: create a character
- `PUT /api/characters`: update a character
- `DELETE /api/characters?id=...`: delete a character

Auth:

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
86% confidence
Finding

The history delete endpoint can be abused by an agent to remove records by ID, especially if the agent can first list recent history items. In this skill, generation history may be needed for auditing, user recall, or cleanup workflows, so unauthorized or accidental deletion undermines integrity and traceability.

Content

Scanner excerpt · tuqu-photo-api/references/endpoints.md (reported line 371)May include surrounding context.

md
- `GET /api/history`: return up to 50 recent history items
- `POST /api/history`: add a history item
- `DELETE /api/history?id=...`: delete a history item

Auth:

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

Recharge and payment checkout flows are not justified by a skill whose stated purpose is creating characters and taking photos. In an agent setting, documenting these endpoints can cause the assistant to initiate billable transactions or present payment artifacts outside user expectations, which is especially risky because the workflow also normalizes how to create live WeChat and Stripe payment sessions.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Including recharge, balance, and payment capabilities is unjustified for a skill whose declared purpose is creating characters and taking photos. In an agent setting, this creates a privilege mismatch: the tool can perform financially sensitive actions unrelated to user intent, enabling misuse if prompts, tool calls, or credentials are manipulated.

Content

No source excerpt is available for this finding.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · tuqu-photo-api/scripts/tuqu_request.py (reported line 129)May include surrounding context.

python
for rule in ENDPOINT_RULES:
        prefix = rule[0]
        if lookup_path == prefix or lookup_path.startswith(prefix + "/"):
            return rule
    raise ValueError(
        "This path is not covered by the helper. Pass --base-url and --auth-mode explicitly."
    )

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

The skill is explicitly described as creating and managing personas with generated files and workspace scaffolding, indicating persistent state across sessions. Session persistence is not inherently malicious, but in an agent-skill context it can retain prompts, persona configuration, or other user-generated state in ways that affect future runs and may expose sensitive context if not clearly disclosed and scoped.

Content

Scanner excerpt · README.md (reported line 23)May include surrounding context.

md
### openclaw-character-creator

Create and manage OpenClaw AI character personas. Supports both **well-known public figures** and **fictional/original characters**, generating a full 6-file persona model with workspace scaffolding.

- Generates 3 auxiliary files (research layer) + 3 main files (runtime layer)
- Creates workspace directory with full scaffolding

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding

The skill advertises file and likely network-affecting behavior via linked subskills and declared config paths, but it does not declare any explicit tool scope or permissions boundary. In an agent ecosystem, missing scope metadata can cause overbroad execution authority and makes it harder for users or policy layers to understand what the skill may access.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
76% confidence
Finding

The skill declares persistent storage paths for role metadata and workspace state, which means data and operational context survive across sessions. Persistent state is security-relevant because it can be tampered with, can preserve unsafe configuration, and may influence later agent behavior in ways the user does not immediately see.

Content

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

md
---
name: openclaw-friends-skill
description: 为龙虾创建角色(世界知名人物或虚拟人物),并让角色支持自拍和拍照。Create a character for OpenClaw (either a world-famous figure or a fictional character), and enable the character to take selfies and photos.
config_paths:
  - ~/.openclaw/ROLES.json
  - ~/.openclaw/workspace

Session Persistence

Medium
Category
Rogue Agent
Confidence
86% confidence
Finding

The skill is designed to create and manage persistent character state across ~/.openclaw/ROLES.json and workspace directories. Persistent session state is not inherently malicious, but it is security-relevant because it changes future agent behavior and can preserve user-associated data beyond the current interaction.

Content

Scanner excerpt · openclaw-character-creator/SKILL.md (reported line 3)May include surrounding context.

md
---
name: openclaw-character-creator
description: Create and manage OpenClaw AI character personas. Use when the user wants to create a new character (创建角色, 创建clone, 新建人物), switch the active character (/shift), or manage their character roster. Handles both well-known public figures and fictional/original characters, generating the full 6-file persona model and workspace scaffolding.
config_paths:
  - ~/.openclaw/ROLES.json
  - ~/.openclaw/workspace

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

Registering the new role in ROLES.json creates durable state that affects later sessions and may influence workspace selection and agent behavior. In this context the persistence is intentional, but it is still a real security-sensitive capability because it modifies global configuration outside the immediate task response.

Content

Scanner excerpt · openclaw-character-creator/SKILL.md (reported line 188)May include surrounding context.

| PERSONA_RULES.md | Personality rules, value hierarchy, MBTI-informed behavior, boundary rules |

text

Write the filled-in result to `$WORKSPACE_PATH/AGENTS.md`.

### Step 8: Register in ROLES.json

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill metadata says it creates personas and enables photos, but the body also performs global role registration and active workspace switching via ROLES.json and ~/.openclaw/workspace. That mismatch can mislead users or higher-level policy systems about the real scope of filesystem state changes, increasing the risk of unintended persistent modifications.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
82% confidence
Finding

The skill directs the agent to obtain and save a public profile image without guidance on consent, copyright, provenance, or verification. This can lead to storing misattributed, manipulated, or privacy-sensitive images and creates legal and trust risks for downstream use.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The template instructs the agent to delete BOOTSTRAP.md automatically after reading it, without requiring user confirmation or a clear safety exception. This is dangerous because it authorizes irreversible file destruction during initialization, and a malicious or mistaken bootstrap flow could cause loss of setup data or erase evidence needed for auditing and recovery.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.