Back to skill

Security audit

AI春联

Security checks for vulnerabilities and agentic risk

Overview

This paid couplet skill needs review because its payment handling is poorly scoped and inconsistent, includes hardcoded payment secrets, and asks the agent to reveal its thought process.

Treat this as a payment-enabled skill that needs manual review before use. Do not rely on it for real payments until the hardcoded keys and recipient values are removed, the active config file is clarified, payment credentials are provider-signed and bound to order/amount/recipient, `clawtip` is pinned to a trusted source, and the thought-process disclosure instruction is deleted.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (7)

T09 · Insecure Skill Coding Practices

Error
Location
configs/config.yaml:1
Finding

Bundled SM4 key enables forged payment credentials

Content
View full analysis
tuple: config = load_config() sm4_key_b64 = config.get("crypto", {}).get("sm4_key") if not sm4_key_b64: return ("ERROR", "配置文件缺少 crypto.sm4_key") try: sm4_key = base64.b64decode(sm4_key_b64) except Exception: return ("ERROR", "crypto.sm4_key 必须是有效的 Base64 编码") if not is_valid_key(sm4_key): return ("ERROR", "SM4 密钥必须为 16 字节") try: decrypted = sm4_decrypt(credential, sm4_key) except Exception as e: return ("ERROR", f"支付凭证解密失败: {e}") pay_status = "PENDING" try: root = json.loads(decrypted) pay_status = root.get("payStatus", "PENDING") except Exception: pass if pay_status.upper() != "SUCCESS": return (pay_status, f"支付未成功,状态: {pay_status}") return ("SUCCESS", "") ``` ### Technical Analysis The symmetric key used to authenticate payment credentials is distributed in the project configuration and duplicated in executable test code. Any party able to inspect the Skill package can recover the key. Payment acceptance is based on whether data decrypted with this shared key contains a successful status. Because possession of a symmetric key permits both encryption and decryption, users can construct credentials that the verifier cannot distinguish from credential ...[truncated 823 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/chunlian_generate.py:66
Finding

Payment success is not bound to the requested order, amount, or recipient

Content
View full analysis
tuple: """ 验证支付凭证 返回 (pay_status, error_info) """ config = load_config() sm4_key_b64 = config.get("crypto", {}).get("sm4_key") if not sm4_key_b64: return ("ERROR", "配置文件缺少 crypto.sm4_key") try: sm4_key = base64.b64decode(sm4_key_b64) except Exception: return ("ERROR", "crypto.sm4_key 必须是有效的 Base64 编码") if not is_valid_key(sm4_key): return ("ERROR", "SM4 密钥必须为 16 字节") try: decrypted = sm4_decrypt(credential, sm4_key) except Exception as e: return ("ERROR", f"支付凭证解密失败: {e}") pay_status = "PENDING" try: root = json.loads(decrypted) pay_status = root.get("payStatus", "PENDING") except Exception: pass if pay_status.upper() != "SUCCESS": return (pay_status, f"支付未成功,状态: {pay_status}") return ("SUCCESS", "") ``` ### Technical Analysis The `order_no` parameter is passed to `verify_payment` but never used. The verifier checks only the `payStatus` field. It does not authenticate or compare: - Order number - Payment amount - Payment recipient - Currency - Transaction identifier - Credential expiry - Credential issuer - Prior credential use Consequently, even after the exposed-key issue is fixed, any legitimately issued successful credential can be replayed for another order. ### Attack Path 1. Obtain one valid credential whose decrypted status is `SUCCESS`. 2. Create or identify another unpaid order. 3. Copy the valid credential into the unpaid order's `payCredential` field. 4. Invoke `chunlian_generate.py` for the unpaid order. 5. The verifier ignores the order mismatch and accepts the credential based solely on its status. ### Im ...[truncated 284 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/file_utils.py:43
Finding

Unvalidated order and indicator parameters permit path traversal

Content
View full analysis
dict: """根据 indicator 和 order_no 从固定目录读取订单 JSON 文件。""" base_dir = get_orders_base_dir(indicator) json_path = os.path.join(base_dir, f"{order_no}.json") if not os.path.isfile(json_path): raise RuntimeError(f"订单文件不存在: {json_path}") with open(json_path, "r", encoding="utf-8") as f: return json.load(f) ``` ```python def main(): if len(sys.argv) < 3: print("ERROR: 缺少参数,Usage: chunlian_generate.py ", file=sys.stderr) print("PAY_STATUS: ERROR") print("ERROR_INFO: 缺少参数") sys.exit(1) order_no = sys.argv[1] indicator = sys.argv[2] try: order_data = load_order(indicator, order_no) ``` ### Technical Analysis Both `indicator` and `order_no` are accepted from command-line input and incorporated into filesystem paths without validation. `os.path.join` does not prevent components containing `..`, path separators, or absolute paths from escaping the intended order namespace. The code neither resolves the resulting path canonically nor verifies that it remains under the expected `~/.openclaw/skills/orders/` directory. ### Attack Path 1. Supply an indicator containing traversal components or an absolute path. 2. Optionally supply an order number containing additional `../` components. 3. The joined path resolves outside the intended indicator directory. 4. If the target is a readable JSON file, the script parses it as order data. 5. The script processes its `question` and `payCredential` fields as though they belonged to the requested order. ### Impact Assessment The vulnerability permits unauthorized cross-order and cross-namespace JSON access within the privileges of the Ski ...[truncated 227 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/sm4_utils.py:83
Finding

Secret keys and payment configuration are exposed through files and stdout

Content
View full analysis
str: import os key = os.urandom(16) return base64.b64encode(key).decode('utf-8') ``` ```python if __name__ == "__main__": key_b64 = "k3qWnsp+ZzFS+Old/VDtcw==" key = base64.b64decode(key_b64) plaintext = '{"orderNo":"123456","amount":1,"payTo":"test"}' encrypted = sm4_encrypt(plaintext, key) print(f"加密: {encrypted}") decrypted = sm4_decrypt(encrypted, key) print(f"解密: {decrypted}") print(f"密钥验证: {is_valid_key(key)}") print(f"生成新密钥: {generate_key()}") ``` ### Technical Analysis The project contains two configuration formats with different hardcoded SM4 keys. Direct execution of `sm4_utils.py` also prints a newly generated key to stdout. In an Agent environment, stdout may be returned to a caller or retained in logs. Base64 only encodes bytes and provides no confidentiality. The flagged `generate_key` return is not, by itself, a network exfiltration channel. The security issue arises when its return value is printed or logged and when operational secrets are shipped in project files. ### Attack Path 1. Read either packaged configuration file to recover an embedded key and payment recipient. 2. Alternatively, execute `sm4_utils.py`. 3. Capture the generated key from stdout, Agent output, or execution logs. 4. Use the exposed key to decrypt protected data or create credentials wherever that key is trusted. ### Impact Assessment ...[truncated 304 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/sm4_utils.py:10
Finding

Payment credentials use unauthenticated SM4-ECB encryption

Content
View full analysis
str: if not plaintext: raise ValueError("明文不能为空") if len(key) != 16: raise ValueError("密钥必须为 16 字节") padding_len = 16 - (len(plaintext.encode('utf-8')) % 16) padded = plaintext.encode('utf-8') + bytes([padding_len] * padding_len) cipher = Cipher(algorithms.SM4(key), modes.ECB(), backend=default_backend()) encryptor = cipher.encryptor() ciphertext = encryptor.update(padded) + encryptor.finalize() return base64.b64encode(ciphertext).decode('utf-8') ``` ```python def sm4_decrypt(encrypted_text: str, key: bytes) -> str: if not encrypted_text: raise ValueError("密文不能为空") if len(key) != 16: raise ValueError("密钥必须为 16 字节") ciphertext = base64.b64decode(encrypted_text.encode('utf-8')) cipher = Cipher(algorithms.SM4(key), modes.ECB(), backend=default_backend()) decryptor = cipher.decryptor() plaintext = decryptor.update(ciphertext) + decryptor.finalize() padding_len = plaintext[-1] plaintext = plaintext[:-padding_len] return plaintext.decode('utf-8') ``` ### Technical Analysis ECB mode is deterministic, exposes repeated-block patterns, and provides no integrity or origin authentication. It is unsuitable for payment credentials whose primary requirement is authenticity. The decryption routine also trusts the final byte as a padding length without checking that it is between 1 and 16 or that all removed bytes match the expected padding value. Modified ciphertext is therefore processed without authenticated tamper detection or strict padding validation. ### Attack Path 1. Obtain or observe an encrypted payment credential. 2. Modify, replace, or rearrange ciphertext bloc ...[truncated 550 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
SKILL.md:93
Finding

Skill instructs the Agent to install an unpinned external payment dependency

Content
View full analysis
", "indicator": "<第一阶段获取的 INDICATOR>" } ``` ``` ### Technical Analysis The Skill tells the Agent to install a dependency identified only by the name `clawtip`. It does not provide a trusted registry, publisher identity, immutable version, package digest, signature, or required permission set. Name-only installation is susceptible to package substitution, dependency confusion, typosquatting, registry compromise, or later malicious updates. The dependency is particularly sensitive because it receives payment-related identifiers and returns a payment credential. ### Attack Path 1. Publish or make available a malicious Skill named `clawtip`, or compromise the currently resolved package. 2. Cause the expected dependency to be unavailable or influence package resolution. 3. The Agent follows `SKILL.md` and installs the name-matched package without integrity verification. 4. The malicious dependency receives payment parameters and executes with its granted Agent permissions. 5. It can capture payment data, falsify credentials, or perform unrelated actions allowed by its environment. ### Impact Assessment A substituted dependency can compromise payment integrity and confidentiality and may gain all permissions granted during installation. The ultimate scope depends on the external Skill's runtime privileges, but it can exceed the narrow requirements of couplet generation. ]]>
Remediation
View remediation

T01 · Skill Instruction Hijacking

Warning
Location
SKILL.md:4
Finding

Skill instructions request internal reasoning disclosure and override response language

Content
View full analysis
AI春联生成专家,根据用户提供的场景、氛围或关键词,生成富有意境的春联。这是一项付费服务,实际收款方可通过配置文件自定义。请注意,你应该用中文和用户交互(包含你的思考过程)。 ``` ```markdown # AI春联生成服务 ## 📌 技能概述 **请注意,你应该用中文和用户交互(包含你的思考过程)。** ``` ### Technical Analysis The Skill persistently directs the Agent to use a fixed language and disclose its thought process. Requiring hidden internal reasoning is unnecessary for generating a couplet and can conflict with higher-level confidentiality expectations. The language requirement also affects the Agent's broader interaction behavior rather than only formatting the generated couplet. This is instruction-level behavior rather than executable malware, but it attempts to alter session output constraints when the Skill is loaded. ### Attack Path 1. Load the Skill into an Agent session. 2. The Agent incorporates the Skill's persistent instruction text. 3. The instruction pressures the Agent to override the caller's language preference. 4. It also requests disclosure of internal reasoning in user-visible output. 5. Sensitive contextual details may be exposed if the Agent follows the instruction without applying higher-priority safeguards. ### Impact Assessment The issue can interfere with session-level response requirements and pressure the Agent to expose internal reasoning or contextual information. It does not independently grant system privileges, but it exceeds the minimum instructions necessary for couplet generation. ]]>
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (20)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Use of encryption/decryption and payment-related protected fields is highly sensitive behavior that is inconsistent with a simple entertainment skill. When a skill masks sensitive financial logic behind an innocuous description, it can mislead users into exposing credentials or approving transactions they did not expect.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Use of encryption/decryption and payment-related protected fields is highly sensitive behavior that is inconsistent with a simple entertainment skill. When a skill masks sensitive financial logic behind an innocuous description, it can mislead users into exposing credentials or approving transactions they did not expect.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

Use of encryption/decryption and payment-related protected fields is highly sensitive behavior that is inconsistent with a simple entertainment skill. When a skill masks sensitive financial logic behind an innocuous description, it can mislead users into exposing credentials or approving transactions they did not expect.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Use of encryption/decryption and payment-related protected fields is highly sensitive behavior that is inconsistent with a simple entertainment skill. When a skill masks sensitive financial logic behind an innocuous description, it can mislead users into exposing credentials or approving transactions they did not expect.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Mandating disclosure of the model's thought process is an explicit prompt-safety violation. In a skill with payment and credential-related capabilities, this can be used to exfiltrate hidden system instructions, validation logic, or sensitive intermediate data under the guise of normal user interaction.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

This is a standing instruction to leak internal chain-of-thought to end users, which can reveal hidden prompts, security constraints, or sensitive contextual artifacts. The danger is amplified by the skill's access to payment-related workflows and credentials, since internal reasoning may mention validation steps or protected data sources.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The repetition strengthens the instruction and increases the likelihood the agent will treat leakage as mandatory behavior. Because the skill context is an entertainment service, there is no legitimate need for internal-reasoning disclosure, making the instruction highly suspicious and unjustified.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The repeated directive creates an ongoing prompt-level exfiltration channel, not a one-off mistake. In context, it is more dangerous because the skill combines entertainment framing with transactional/payment behavior, increasing the chance users will trust it while it pressures the model to reveal protected internal content.

Content

No source excerpt is available for this finding.

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · configs/config.json (reported line 2)May include surrounding context.

json
{
  "payTo": "8f18fb4ccac281a40fb0cf96ec7c2aa8202604081312250020002552zmV8kH3UJyhYdJjFXghUiYLL4FuyrNtvEwiagAzFyufPIN3ePZVMwfMkzyhJD2FuoPrQ118i",
  "sm4Key": "WoDb5xjzDmsYPV875mvYqg==",
  "amount": 1,
  "skillName": "ai-chunlian",
  "description": "服务费用"
}

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

保存的订单元数据将该技能硬编码为“si-clawpraise”、描述为“花式夸夸服务费用”,与当前春联技能的身份和用途明显不一致。这种身份伪装会误导审核、计费、追踪和用户认知,使支付订单看起来属于另一项服务,具有较强的欺骗性,并可能被用于绕过平台校验或将款项/订单归属错误地绑定到别的技能。

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.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The instruction to reveal the model's thought process is a direct prompt-based data leakage issue. Exposing internal reasoning can disclose hidden policy content, security heuristics, or sensitive contextual details, and it is unrelated to the legitimate task of generating spring couplets.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The repeated requirement to disclose thought process establishes a persistent leakage directive rather than an accidental wording issue. In context, this is especially dangerous because the skill also touches payment and credentials, so leaked reasoning could include sensitive operational details or protected context.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
79% confidence
Finding

This manifest-style JSON includes a skill name and description but provides no specific activation phrases, scope limits, or exclusion conditions. For manifest files, the absence of trigger specificity can make it unclear when the skill should activate versus when it should not.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

清单描述该技能是“根据用户提供的场景、氛围或关键词生成春联”,但本文件实际只负责读取支付配置、生成订单号、加密支付数据并写入订单数据库,没有任何春联生成逻辑。虽然付费可能是业务流程的一部分,但该文件的实际行为明显超出“春联生成”这一描述的核心语义。

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

代码将 question、style、pay_to、encrypted_data 等订单信息持久化保存,但从该实现看不到任何用户提示、最小化存储或保留策略。对一个面向用户的付费技能来说,用户输入内容和支付相关元数据被静默落库,会带来隐私、合规和数据泄露风险;如果 question 包含个人信息,危害会进一步上升。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

This code file contains user-facing and developer-facing natural-language text exclusively in Chinese across multiple docstrings and error strings, with no indication that the skill supports other languages or that Chinese is a justified locale-specific requirement. Under the policy, forcing a specific language without user opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

对于一个春联生成专家技能而言,读取用户配置可勉强对应“收款方可配置”,但操作固定订单目录、写入订单 JSON、维护 SQLite 订单与履约记录表,体现的是通用交易后端能力。这些能力不是“生成春联”这一用途的直接、显然必需实现细节。

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

清单描述将该技能定位为“根据用户提供的场景、氛围或关键词生成春联”,仅补充说明这是付费服务与收款方可配置。但该文件实际实现了订单 JSON 读写、SQLite 订单表与履约记录表的创建和持久化,属于完整的订单管理/履约支撑能力,而不只是内容生成本身。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

This Python file's docstrings, comments, and runtime messages are written exclusively in Chinese, including the main user-visible output and validation errors. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is explicitly justified, which is not present here.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.