Back to skill

Security audit

ai-video-creator-assistant

Security checks for vulnerabilities and agentic risk

Overview

The skill is broadly coherent as a paid video-assistance workflow, but its payment authorization and encrypted order metadata handling are weak enough to require review before installation.

Review this skill carefully before installing, especially if you rely on its payment gate. It stores local order files under the OpenClaw skills orders directory and its current payment verification can be forged by editing those files. It also may store payment metadata in plaintext when SM4 encryption is not configured or fails. Do not provide video API keys unless you trust the publisher and understand that the skill mainly guides use of third-party video APIs rather than shipping a full video-generation backend.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/service.py:35
Finding

Payment Authorization Can Be Forged Through Local Order-File Modification

Content
View full analysis
bool: credential = order_data.get("payCredential") if not credential: return False ts = order_data.get("credentialTimestamp") if ts and time.time() - ts > CREDENTIAL_TTL: return False return True if __name__ == "__main__": parser = argparse.ArgumentParser(description="Verify payment and authorize video creation service") parser.add_argument("order_no", help="Order number from Phase 1") args = parser.parse_args(); indicator = compute_indicator(SLUG) try: order_data = _load_order(indicator, args.order_no) except Exception as e: print("PAY_STATUS: ERROR"); print(f"ERROR_INFO: Order file read failed: {e}"); sys.exit(1) if not is_credential_valid(order_data): print("PAY_STATUS: ERROR") print("ERROR_INFO: No valid payment credential found. Complete payment via clawtip first.") sys.exit(1) pay_status = order_data.get("payStatus", "SUCCESS") print(f"PAY_STATUS: {pay_status}") if pay_status != "SUCCESS": print(f"ERROR_INFO: Payment status is '{pay_status}', cannot proceed"); sys.exit(1) ``` ### Technical Analysis Payment authorization is based entirely on fields loaded from a JSON file located in the current user's home directory. That file is writable by the same user who invokes the service. The `is_credential_valid` function only verifies that `payCredential` contains a truthy value. It does not verify a digital signature, message authentication code, trusted issuer, order number, amount, recipient, or skill identifier. The timestamp check is also optional. If `credentialTimestamp` is absent, credential expiration is not enforced. In addition, `payStatus` defaults to `SUCCESS` when it is missing, cau ...[truncated 1249 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/create_order.py:148
Finding

Encryption Failure Silently Stores Payment Metadata in Plaintext

Content
View full analysis
dict: """ Create order file with payment metadata only. No user question, video content, API keys, or personal data is stored. """ pay_to = os.environ.get("CLAWTIP_PAY_TO", "") sm4_key = os.environ.get("CLAWTIP_SM4_KEY", "") if not pay_to: print("WARNING: CLAWTIP_PAY_TO environment variable not set") if not sm4_key: print("WARNING: CLAWTIP_SM4_KEY environment variable not set") order_no = generate_order_no() encrypt_payload = json.dumps({ "orderNo": order_no, "amount": str(AMOUNT), "payTo": pay_to, }, ensure_ascii=False) encrypted_data = encrypt_payload if sm4_key: try: if len(sm4_key) == 32 and all(c in "0123456789abcdefABCDEF" for c in sm4_key): encrypted_data = _sm4_encrypt_hex(sm4_key, encrypt_payload) else: import base64 encrypted_data = _sm4_encrypt_hex(base64.b64decode(sm4_key).hex(), encrypt_payload) except Exception as e: print(f"WARNING: SM4 encryption failed: {e}") # Only essential order metadata is persisted. No user-provided content is stored. order_data = { "payTo": pay_to, "amount": AMOUNT, "order_no": order_no, "encrypted_data": encrypted_data, "slug": SLUG, "description": DESCRIPTION, "resource_url": RESOURCE_URL, } ``` ### Technical Analysis The variable named `encrypted_data` is initialized with the plaintext JSON payload before any encryption is attempted. If `CLAWTIP_SM4_KEY` is absent, the encryption block is skipped and the plaintext is persisted. If the key is malformed or encryption otherwise fails, the except ...[truncated 1385 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/create_order.py:105
Finding

Payment Metadata Uses Unauthenticated SM4-ECB Encryption

Content
View full analysis
4I", pt)) for i in range(32): tmp = x[i + 1] ^ x[i + 2] ^ x[i + 3] ^ rk[i] x.append(x[i] ^ _t(tmp)) return struct.pack(">4I", x[35], x[34], x[33], x[32]) def _sm4_encrypt_ecb(key, data): if len(key) != 16: raise ValueError("SM4 key must be 16 bytes") pad = 16 - (len(data) % 16) data = data + bytes([pad] * pad) rk = _key_expand(key) out = b"" for i in range(0, len(data), 16): out += _enc_block(data[i:i + 16], rk) return out def _sm4_encrypt_hex(key_hex, plain): return _sm4_encrypt_ecb(bytes.fromhex(key_hex), plain.encode("utf-8")).hex() ``` ### Technical Analysis The code implements SM4 in Electronic Codebook mode. ECB encrypts each block independently and deterministically, so identical plaintext blocks under the same key produce identical ciphertext blocks. It does not use a nonce or initialization vector. More importantly, ECB does not provide message integrity or authenticity. An attacker with write access to stored ciphertext can alter, remove, reorder, or substitute ciphertext blocks without the encryption layer detecting that modification. Padding alone does not authenticate the message. Payment-related metadata should use authenticated encryption so that both unauthorized disclosure and unauthorized modification are addressed. Whether a modified ciphertext is ultimately accepted depends on the behavior of the external `clawtip` consumer, which is outside the reviewed project, but this implementation itself provides no tamper detection. ### Attack Path 1. Obtain access to one or more locally stored order files. 2. Compare ciphertext blocks across orders encrypted under the same static key to identify repeate ...[truncated 1039 chars]
Remediation
View remediation
Vulnerability Patterns
  • Rogue AgentSelf-Modification, Session Persistence
  • 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
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (6)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description focuses on AI-assisted short video generation functionality, including user-selected video parameters and use of external video APIs. However, this code chunk is solely an order creation/payment metadata script. Its primary behavior is payment processing support: reading payment configuration from environment variables, generating an order number, encrypting a payment payload, and saving order data locally. While the description does mention a one-time payment of ¥16.90, it does not accurately represent that this code specifically implements payment order creation and local persistence rather than video creation behavior. This is a material description-behavior mismatch for the supplied code chunk.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The header comment claims only encrypted payment fields are persisted, but the code falls back to storing the raw JSON payload in encrypted_data when CLAWTIP_SM4_KEY is unset or encryption fails. That means payment metadata such as orderNo, amount, and payTo may be written in plaintext despite documentation asserting otherwise, creating a confidentiality and trust issue.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest describes an AI-assisted short video creation skill, but this script’s primary behavior is creating and persisting local payment order metadata for clawtip processing. Payment handling may be part of the product lifecycle, but it is a distinct operational capability not disclosed in the stated skill description.

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 · scripts/create_order.py (reported line 132)May include surrounding context.

python
def create_order_file(indicator: str) -> dict:
    """
    Create order file with payment metadata only.
    No user question, video content, API keys, or personal data is stored.
    """
    pay_to = os.environ.get("CLAWTIP_PAY_TO", "")

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The script tells the user to consult "SKILL.md > API 配置指引," which hard-codes a Chinese-language section reference in user-facing instructions. This can violate language/locale policy when no user opt-in or alternative language path is offered.

Content

No source excerpt is available for this finding.