Back to skill

Security audit

history-persona-video

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a real media-generation workflow, but it bundles a broad RunningHub client that can run many paid AI workflows, upload local media, and handle API keys in risky ways.

Install only if you intend to grant a broad RunningHub media client access, not just a narrow historical-video recipe. Use your own limited RunningHub API key, monitor paid balance usage, avoid sending private media unless you are comfortable uploading it to RunningHub, and do not use voice cloning without clear consent from the voice owner. The publisher should narrow the bundled capabilities and improve API-key storage and transmission before this is treated as low risk.

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

T09 · Insecure Skill Coding Practices

Warning
Location
skills/runninghub/scripts/runninghub_app.py:143
Finding

API Key Disclosure Through URL Query Parameters and Process Arguments

Content
View full analysis
subprocess.CompletedProcess: cmd = ["curl", "-s", "-S", "--fail-with-body", "--max-time", str(timeout), url] return subprocess.run(cmd, capture_output=True, text=True) ``` ```python def get_node_info(api_key: str, webapp_id: str) -> list[dict]: url = f"{API_HOST}{NODE_INFO_PATH}?apiKey={api_key}&webappId={webapp_id}" result = curl_get(url) ``` ### Technical Analysis The `get_node_info` function embeds the complete RunningHub API key in a GET query parameter. The resulting URL is then supplied to `curl` as a command-line argument. Secrets placed in URLs can be exposed through: - Local process listings while `curl` is running. - HTTP server, reverse-proxy, gateway, or monitoring logs. - Diagnostic and error-reporting systems that record request URLs. - Shell or process auditing facilities. - Network observability systems that retain URL paths and query strings. HTTPS protects the request while it is transported, but it does not prevent disclosure through local process inspection or endpoint-side logging. The behavior is unnecessary because the same project already uses authorization headers for other API operations. ### Attack Path 1. A user or Agent invokes `runninghub_app.py --info` or `runninghub_app.py --run`. 2. The script resolves the API key from the command line, environment, or OpenClaw configuration. 3. `get_node_info` inserts the key into the URL as `?apiKey=`. 4. `curl_get` passes the full URL in the `curl` process argument list. 5. A local user with process-inspection access, or an operator with access to HTTP infrastructure logs, captures the URL. 6. The captured key is reused to invoke paid RunningHub API operations unde ...[truncated 484 chars]
Remediation
View remediation
subprocess.CompletedProcess: cmd = [ "curl", "-s", "-S", "--fail-with-body", "--max-time", str(timeout), "-H", f"Authorization: Bearer {api_key}", url, ] return subprocess.run(cmd, capture_output=True, text=True) ``` 3. If the endpoint does not support headers, use a protected POST body rather than a GET query string. 4. Prefer a Python HTTP library or protected curl configuration/input file so credentials do not appear in process arguments. 5. Redact query strings and authorization values from application, proxy, and diagnostic logs. 6. Rotate API keys that may previously have been exposed through this code. 7. Add automated tests that reject request URLs containing parameter names such as `apiKey`, `token`, or `secret`. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
skills/runninghub/references/api-key-setup.md:32
Finding

Unsafe API Key Persistence and Command Construction in Setup Instructions

Content
View full analysis
`. If valid, save it: ```bash python3 -c " import json, pathlib p = pathlib.Path.home() / '.openclaw' / 'openclaw.json' p.parent.mkdir(exist_ok=True) cfg = json.loads(p.read_text()) if p.exists() else {} cfg.setdefault('skills', {}).setdefault('entries', {}).setdefault('runninghub', {})['apiKey'] = 'THE_KEY' p.write_text(json.dumps(cfg, indent=2)) " ``` Replace `THE_KEY` with **your own** key. ``` ### Technical Analysis The setup procedure has three credential-handling weaknesses: 1. It instructs the Agent to verify the secret through `--api-key `. This places the key in the Python process argument list, where it can be observed by process-monitoring or auditing tools. 2. It instructs the Agent to replace `THE_KEY` directly inside a `python3 -c` source string. A value containing quote characters or Python syntax can alter the generated program. Exploitation depends on whether such a value passes the preceding validation and on how literally the Agent performs the substitution, but the construction is inherently unsafe. 3. It writes the plaintext key with `Path.write_text()` without explicitly enforcing owner-only permissions. The effective permissions therefore depend on the existing file mode and process umask. Storing a service credential locally is necessary for the declared functionality, but exposing it through process arguments and failing to require restrictive file permissions exceed the minimum credential-handling risk needed for that functionality. ### Attack Path #### Local credential-disclosure path 1. The user supplies a RunningHub API key. 2. The Agent invokes the documente ...[truncated 1516 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (52)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The ability to browse AI applications, inspect node metadata, upload arbitrary files, execute arbitrary workflows, download outputs, and check account status is materially more powerful than the user-facing description suggests. In a skill context, this kind of under-disclosed capability can enable covert exfiltration of workspace files to third-party services or abuse of the user's API-backed account under the guise of normal media generation.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The ability to browse AI applications, inspect node metadata, upload arbitrary files, execute arbitrary workflows, download outputs, and check account status is materially more powerful than the user-facing description suggests. In a skill context, this kind of under-disclosed capability can enable covert exfiltration of workspace files to third-party services or abuse of the user's API-backed account under the guise of normal media generation.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The ability to browse AI applications, inspect node metadata, upload arbitrary files, execute arbitrary workflows, download outputs, and check account status is materially more powerful than the user-facing description suggests. In a skill context, this kind of under-disclosed capability can enable covert exfiltration of workspace files to third-party services or abuse of the user's API-backed account under the guise of normal media generation.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The manifest exposes an extremely broad, general-purpose media capability surface that far exceeds the stated 'historical persona vertical-video' workflow. That overbreadth violates least privilege and enables an agent or downstream prompt flow to invoke unrelated image, video, world-generation, translation, cloning, and editing operations, increasing the chance of policy bypass, unexpected data sharing, and misuse.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

3D/world-generation capabilities are unrelated to the described vertical-video workflow and materially expand what the skill can do with supplied prompts and media. This unnecessary capability breadth increases misuse potential, including transformation of user media into unrelated artifacts, broader third-party transmission, and evasion of user expectations about how their content will be processed.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

Voice cloning is a consent-sensitive biometric capability and is not justified by the declared workflow. In a historical-persona restoration skill, it could be repurposed to impersonate real people, fabricate endorsements, or synthesize deceptive speech using uploaded audio without clear user awareness or authorization boundaries.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Listing voice-cloning functionality without an explicit warning about consent, impersonation risk, and biometric sensitivity is dangerous. In this skill context, users may reasonably expect stylized historical narration, not that uploaded voice samples can be converted into reusable synthetic identity assets, making the omission more serious.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The instruction says the menu must appear whenever the user wants 'ANY image generation,' which is an extremely broad activation condition and does not clearly bound when the skill should or should not take over. This can overlap with many ordinary image-related requests and lacks negative examples or tighter scope constraints.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script advertises and implements a universal client for hundreds of RunningHub endpoints across image, video, audio, 3D, and text tasks, while the declared skill purpose is only historical-persona short-video production. This scope mismatch materially increases attack surface, enables unrelated data flows and capabilities, and makes it easier for a seemingly narrow skill to be repurposed into a general exfiltration or content-generation bridge to third-party services.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The usage instruction tells the user to invoke the skill with Chinese-only phrases ("对 AI 说" followed by Chinese trigger examples), and the rest of the README is also written exclusively in Chinese. There is no indication that other languages are supported or that the Chinese-only constraint is a necessary region-specific requirement, which creates a natural-language locale policy concern.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
78% confidence
Finding

The skill explicitly relies on shell execution, file reads/writes, environment-provided API credentials, and external tooling, yet it declares no tool restrictions or permission boundaries. That creates unnecessary authority for a content-production workflow and increases the chance an agent could use those capabilities in unintended ways, especially because the skill also references a general-purpose RunningHub script rather than a narrowly constrained helper.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The instructions prescribe '大气中文字体' and a fixed Chinese disclaimer, implying the skill is designed to produce Chinese-language assets by default. Because the file does not offer a language or locale choice or explain that this constraint is region-specific, it constitutes a natural-language locale policy issue.

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 · runninghub-skill-v2.zip!/scripts/runninghub.py (reported line 143)May include surrounding context.

python
"message": "No API key configured",
        "steps": [
            "1. Register/login at https://www.runninghub.cn",
            "2. Create API Key at https://www.runninghub.cn/enterprise-api/sharedApi",
            "3. Recharge wallet at https://www.runninghub.cn/vip-rights/4",
            "4. Send the key in chat or add to ~/.openclaw/openclaw.json: skills.entries.runninghub.apiKey",
        ],

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · runninghub-skill-v2.zip!/scripts/runninghub.py (reported line 165)May include surrounding context.

python
"--max-time", str(timeout), "-d", f"@{tmp_path}"]
        for k, v in headers.items():
            cmd += ["-H", f"{k}: {v}"]
        return subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8", errors="replace")
    finally:
        os.unlink(tmp_path)

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 · runninghub-skill-v2.zip!/scripts/runninghub.py (reported line 233)May include surrounding context.

python
"message": "No API key configured",
            "steps": [
                "1. Register/login at https://www.runninghub.cn",
                "2. Create API Key at https://www.runninghub.cn/enterprise-api/sharedApi",
                "3. Recharge wallet at https://www.runninghub.cn/vip-rights/4",
                "4. Send the key in chat or add to ~/.openclaw/openclaw.json: skills.entries.runninghub.apiKey",
            ],

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · runninghub-skill-v2.zip!/scripts/runninghub.py (reported line 365)May include surrounding context.

python
cmd = ["curl", "-s", "-S", "--fail-with-body", "-X", "POST", url,
           "-H", f"Authorization: Bearer {api_key}",
           "-F", f"file=@{file_path}", "--max-time", "120"]
    result = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8", errors="replace")
    if result.returncode != 0:
        print(f"Upload failed: {result.stderr}", file=sys.stderr)
        sys.exit(1)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · runninghub-skill-v2.zip!/scripts/runninghub.py (reported line 472)May include surrounding context.

python
cmd = ["curl", "-s", "-S", "--fail-with-body", "-X", "POST", url,
           "-H", f"Authorization: Bearer {api_key}",
           "-F", f"file=@{file_path}", "--max-time", "120"]
    result = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8", errors="replace")
    if result.returncode != 0:
        print(f"Upload failed: {result.stderr}", file=sys.stderr)
        sys.exit(1)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · runninghub-skill-v2.zip!/scripts/runninghub_app.py (reported line 44)May include surrounding context.

python
def curl_get(url: str, timeout: int = 30) -> subprocess.CompletedProcess:
    cmd = ["curl", "-s", "-S", "--fail-with-body", "--max-time", str(timeout), url]
    return subprocess.run(cmd, capture_output=True, text=True)


def curl_post_json(url: str, payload: dict, timeout: int = 60) -> subprocess.CompletedProcess:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · runninghub-skill-v2.zip!/scripts/runninghub_app.py (reported line 59)May include surrounding context.

python
def curl_get(url: str, timeout: int = 30) -> subprocess.CompletedProcess:
    cmd = ["curl", "-s", "-S", "--fail-with-body", "--max-time", str(timeout), url]
    return subprocess.run(cmd, capture_output=True, text=True)


def curl_post_json(url: str, payload: dict, timeout: int = 60) -> subprocess.CompletedProcess:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · runninghub-skill-v2.zip!/scripts/runninghub_app.py (reported line 73)May include surrounding context.

python
def curl_get(url: str, timeout: int = 30) -> subprocess.CompletedProcess:
    cmd = ["curl", "-s", "-S", "--fail-with-body", "--max-time", str(timeout), url]
    return subprocess.run(cmd, capture_output=True, text=True)


def curl_post_json(url: str, payload: dict, timeout: int = 60) -> subprocess.CompletedProcess:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · runninghub-skill-v2.zip!/scripts/runninghub_app.py (reported line 127)May include surrounding context.

python
"-H", f"Authorization: {api_key}",
            "-d", f"@{tmp_path}",
        ]
        result = subprocess.run(cmd, capture_output=True, text=True)
    finally:
        os.unlink(tmp_path)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · runninghub-skill-v2.zip!/scripts/runninghub_app.py (reported line 252)May include surrounding context.

python
"-H", f"Authorization: {api_key}",
            "-d", f"@{tmp_path}",
        ]
        result = subprocess.run(cmd, capture_output=True, text=True)
    finally:
        os.unlink(tmp_path)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · runninghub-skill-v2.zip!/scripts/runninghub_app.py (reported line 321)May include surrounding context.

python
"-H", f"Authorization: {api_key}",
            "-d", f"@{tmp_path}",
        ]
        result = subprocess.run(cmd, capture_output=True, text=True)
    finally:
        os.unlink(tmp_path)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The persona section states that all responses must follow a fixed style and explicitly says 'Speak Chinese,' which forces a specific language for all interactions. This is a natural-language policy issue because the file does not offer user opt-in or a language choice, nor does it justify a Chinese-only constraint as region-specific.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest mentions materials, dubbing, cards, composition, and validation, but this catalog also includes lyrics generation, song generation, BGM generation, cover generation, stem separation, song recognition, and song understanding. Those are standalone music-production and analysis features that go well beyond a focused short-video creation pipeline.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.