Back to skill

Security audit

OpenClaw Role Builder

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent role-and-image purpose, but it exposes unsafeguarded credentialed API, billing, deletion, and filesystem-move behavior that needs review before installation.

Review this skill carefully before installing. Use a disposable or tightly scoped TuQu service key, avoid running recharge or deletion flows unless you explicitly requested them, and consider running OpenClaw under an isolated user account because the current scripts do not enforce all documented host and filesystem boundaries.

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)

T09 · Insecure Skill Coding Practices

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

Authenticated requests can exfiltrate credentials and private images to arbitrary hosts

Content
View full analysis
str: _, _, env_name, default_base_url = match_endpoint_rule(path) return os.environ.get(env_name, default_base_url) ``` ```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 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 " "serviceKey=..., or provide serviceKey in the JSON body." ) headers["Authorization"] = f"Bearer {service_key}" data = None if body is not None: headers["Content-Type"] = "application/json" data = json.dumps(body).encode("utf-8") url = build_url(base_url, args.path, query_items) ``` ### Technical An ...[truncated 2458 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
openclaw-character-creator/scripts/register_role.py:26
Finding

Unvalidated role registry paths allow arbitrary directory movement

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}") ``` ```python target_path = target["workspacePath"] if target_path == ACTIVE_WORKSPACE: print(f"'{target_name}' is already the active role.") return ``` ```python if state and "originalWorkspacePath" in state: original_path = state["originalWorkspacePath"] ``` ```python if os.path.exists(original_path): print(f"Error: Cannot save current workspace — path already exists: {original_path}") sys.exit(1) print(f"Saving current workspace -> {original_path}") shutil.move(ACTIVE_WORKSPACE, original_path) write_workspace_state(original_path, {"workspacePath": original_path}) ``` ```python if not os.path.exists(target_path): print(f"Error: Target workspace does not exist: {target_path}") sys.exit(1) print(f"Activating '{target_name}' -> {ACTIVE_WORKSPACE}") shutil.move(target_path, ACTIVE_WORKSPACE) ``` ### Technical Analysis `register_role.py` accepts and persists any supplied `workspace_path`. It d ...[truncated 2149 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

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

Service keys are exposed through command-line arguments

Content
View full analysis
\ --body-file payloads/generate-image.json ``` The suggested shell-variable pattern still exposes the expanded value in the child process argument vector: ```bash SK="sk-..." python3 scripts/tuqu_request.py ... --service-key "$SK" ``` ### Technical Analysis Command-line arguments are not an appropriate channel for reusable secrets. Depending on the operating system and execution environment, process arguments may be captured by: - Process-listing utilities. - Other local processes with sufficient visibility. - Shell history when a literal key is entered. - Process monitoring, endpoint telemetry, or audit systems. - Job runners and wrapper tools that log invoked commands. - Agent execution transcripts. Using a shell variable prevents the literal key from appearing in the typed command only when handled carefully. It does not prevent the shell from expanding the key into the child process's argument vector. The skill also describes the CLI flag as its exclusive credential mechanism, so users cannot choose a safer standard-input or protected credential-provider path. ### Attack Path 1. A user or Agent starts an authenticated TuQu request with `--service-key`. 2. The shell expands the key into the argument vector ...[truncated 954 chars]
Remediation
View remediation
` with a standard-input mechanism, such as `--service-key-stdin`. 2. Prefer reading the credential from an inherited file descriptor or an operating-system credential provider. 3. If environment variables are supported as a compatibility fallback, clearly document their process-environment exposure and avoid printing them. 4. Keep secrets out of URLs and query strings because those are frequently logged by clients, proxies, and servers. 5. Redact credential-like values from exceptions, debug output, telemetry, and subprocess wrappers. 6. Recommend scoped, short-lived, or disposable service keys and provide clear revocation instructions. 7. Retain backward compatibility only temporarily, emit a security warning for argv-based credentials, and remove the insecure option in a subsequent release. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (49)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The skill description emphasizes role building and image generation, but the documented sub-skill scope also includes billing, recharge, account/history, catalog, and low-level request functionality. That mismatch can mislead users and policy engines about the sensitivity of operations, increasing the chance of unintended financial actions or overbroad API use.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
84% confidence
Finding

The skill documents a direct DELETE operation for /api/characters/<character-id> without any stated confirmation, ownership validation, or narrowing conditions. In an agent context, destructive endpoints can be triggered from natural-language requests or parameter confusion, causing unintended deletion of saved character assets and denial of service to the user's workflow.

Content

Scanner excerpt · tuqu-photo-api/SKILL.md (reported line 233)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
83% confidence
Finding

The documented DELETE /api/history/<history-id> call exposes a destructive action with no described safeguards such as confirmation, preview, or scope checks. In an LLM-driven tool flow, this increases the chance of accidental or prompt-induced deletion of generation history, undermining auditability and user data retention.

Content

Scanner excerpt · tuqu-photo-api/SKILL.md (reported line 258)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
80% 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 · 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
80% 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 · 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:

Missing User Warnings

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

This workflow processes face photos to create saved characters without any explicit warning or consent flow for biometric/privacy-sensitive data. Face images are highly sensitive, and using them for persistent character creation raises elevated risks around identity misuse, unauthorized likeness cloning, retention, and regulatory noncompliance.

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

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% confidence
Finding

The README explicitly describes persistent role/persona management and identity-consistent image generation across sessions, implying storage and reuse of character state. In a skill that models public figures and creates consistent images, retained persona state can increase privacy, impersonation, and misuse risks if users do not understand what is persisted or how long it remains available.

Content

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

md
# OpenClaw Role Builder

Build and manage OpenClaw roles — create AI character personas from any public figure or fictional character, then generate identity-consistent selfies, portraits, and group shots where the role's face stays consistent across every image.

## Install

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.

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.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The usage examples under Quick Start are entirely in Chinese, implying the skill is activated and used through a specific language. The README does not state that Chinese is optional, nor does it offer alternative languages or explain a justified region-specific limitation.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
83% confidence
Finding

The README confirms that file writes occur under ~/.openclaw/ and that character names and workspace paths are stored there, which is a form of session persistence. Even without credential storage, persistent metadata about created roles can expose sensitive usage patterns, enable unintended carryover between sessions, or support impersonation workflows if the local store is accessed by other processes or users.

Content

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

md
- **No credential storage:** Service keys are passed exclusively via `--service-key` CLI flag to
  `tuqu_request.py`. The script does not read credentials from environment variables or config
  files. Keys are never written to disk.
- **Write scope:** All file writes are confined to `~/.openclaw/`. No skill writes outside that
  directory. Character data contains only names and workspace paths.
- **Network scope:** All API calls go through `scripts/tuqu_request.py`, which restricts requests
  to `photo.tuqu.ai` and `billing.tuqu.ai`.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill advertises file, network, and likely environment-dependent behavior but does not declare an explicit tool/permission scope. In an agent ecosystem, missing tool scoping weakens policy enforcement and can allow the skill to be invoked with broader capabilities than users or the platform expect.

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 · SKILL.md (reported line 4)May include surrounding context.

md
---
name: openclaw-role-builder
description: >-
  Build and manage OpenClaw roles — create a full AI character role from any
  public figure or fictional character, then generate identity-consistent
  selfies and photos for that role. Use when building roles (创建角色, 创建clone,
  新建人物, build a role), switching the active role (/shift, 切换角色), taking

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The trigger phrases are very broad and overlap with common conversational requests like '发张图' or generic image-generation prompts. In an agent setting, this can cause accidental invocation of a networked, stateful skill when the user did not intend to use it, potentially sending prompts or acting on the active role context unexpectedly.

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 · SKILL.md (reported line 114)May include surrounding context.

md
## Security Boundaries

1. **Write scope:** All file writes are confined to `~/.openclaw/` (the paths listed above). No
   skill in this collection writes outside that directory.
2. **Read scope:** Skills read only their own bundled reference files (under the skill's
   `references/` directory) and character workspace files under `~/.openclaw/`. No arbitrary

Session Persistence

Medium
Category
Rogue Agent
Confidence
84% confidence
Finding

The skill persistently creates character workspaces and stores persona, memory, and relationship files under ~/.openclaw, which introduces durable session state beyond a single interaction. Even though the content is intended and scoped, persistence of identity and user-related data can accumulate sensitive personal or behavioral information and may later be loaded or reused in ways the user did not expect.

Content

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

md
# OpenClaw Character Creator

Create high-consistency AI character personas for OpenClaw. Each character gets a dedicated workspace with 6 persona files, proper tooling, and registration in the global role roster.

## Paths

Session Persistence

Medium
Category
Rogue Agent
Confidence
87% confidence
Finding

Registering the role in ROLES.json and writing AGENTS.md makes the created persona discoverable and reusable across future sessions, which is a concrete persistence mechanism. This can preserve user-associated context and behavioral scaffolding indefinitely, increasing privacy and integrity risk if stale, sensitive, or manipulative persona state is later activated without adequate review.

Content

Scanner excerpt · openclaw-character-creator/SKILL.md (reported line 197)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

Static analysis

No suspicious patterns detected.