Back to skill

Security audit

DeepKnow Currency

Security checks for vulnerabilities and agentic risk

Overview

This exchange-rate skill matches its stated purpose, but its payment credential handling is under-scoped enough that users should review it carefully before installing.

Install only if you trust the publisher and the configured InkRate endpoint. Keep the default HTTPS host unless you control the replacement service, avoid shared or world-writable order directories, and treat local order files as sensitive because they can contain payment credentials and personal request details.

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)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/file_utils.py:18
Finding

Path Traversal Through Unsanitized Order Numbers

Content
View full analysis
Path: return openclaw_order_root() / indicator def order_path(indicator: str, order_no: str) -> Path: return order_root(indicator) / f"{order_no}.json" def save_order(indicator: str, order_no: str, payload: dict) -> Path: path = order_path(indicator, order_no) path.parent.mkdir(parents=True, exist_ok=True) path.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8") return path def load_order(indicator: str, order_no: str) -> dict: path = order_path(indicator, order_no) if not path.exists(): raise FileNotFoundError(f"order file not found: {path}") return json.loads(path.read_text(encoding="utf-8")) ``` Remote data reaches the write operation through: ```python body = request_json(f"{resolve_base_url()}/api/skill/create-order", {"question": question}) order_no = body["order_no"] save_order( INDICATOR, order_no, { "skill-id": SLUG, "skill_id": SLUG, "order_no": order_no, "amount": body["amount_fen"], "question": question, "encrypted_data": body["encrypted_data"], "pay_to": body["pay_to"], "description": body["description"], "slug": SLUG, "resource_url": body["resource_url"], }, ) ``` User input reaches the read operation through: ```python order_no = sys.argv[1] try: order = load_order(INDICATOR, order_no) credential = order.get("payCredential") or order.get("credential") if not credential: raise RuntimeError("payment credential not found in order file") payload = request_json( f"{resolve_base_url()}/api/skill/fulfill", ...[truncated 2699 chars]
Remediation
View remediation
str: if not ORDER_NO_PATTERN.fullmatch(order_no): raise ValueError("invalid order number") return order_no ``` 2. Resolve both the root and candidate path, then verify containment: ```python def order_path(indicator: str, order_no: str) -> Path: validate_order_no(order_no) root = order_root(indicator).resolve() candidate = (root / f"{order_no}.json").resolve() if candidate.parent != root: raise ValueError("order path escapes order root") return candidate ``` 3. Reject absolute paths, path separators, `.` and `..` components before any filesystem operation. 4. Validate server-returned `order_no` values before saving them. 5. Apply the same validation to command-line order numbers before loading an order. 6. Use exclusive or atomic file creation where overwriting an existing order is not intended. 7. Add tests covering Unix and Windows traversal forms, including `../`, `..\`, absolute paths, drive prefixes, and encoded separator variants. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/runtime_config.py:50
Finding

Payment Credentials Can Be Sent to Arbitrary Hosts Over Plaintext HTTP

Content
View full analysis
str: normalized = value.strip().rstrip("/") if not normalized: raise ValueError("base_url is empty") parsed = urlparse(normalized) if parsed.scheme not in {"http", "https"} or not parsed.netloc: raise ValueError(f"invalid base_url: {value}") if parsed.path not in {"", "/"} or parsed.params or parsed.query or parsed.fragment: raise ValueError(f"base_url must not include path/query/fragment: {value}") return normalized ``` ```python def resolve_base_url() -> str: env_value = os.getenv("INKRATE_SKILL_BASE_URL", "").strip() config_value = read_base_url_from_config() return normalize_base_url(env_value or config_value or DEFAULT_BASE_URL) ``` The selected endpoint receives the payment credential and original question: ```python payload = request_json( f"{resolve_base_url()}/api/skill/fulfill", { "order_no": order_no, "credential": credential, "question": order.get("question", ""), }, ) ``` ### Technical Analysis The URL validator explicitly accepts both `http` and `https`, even though the fulfillment request contains a payment credential. Plain HTTP provides neither confidentiality nor server authentication, allowing a network-positioned attacker to observe or alter the request. The module defines `SUPPORTED_PUBLIC_BASE_URLS`, but `resolve_base_url()` does not enforce it. An environment variable or local `config.yaml` can redirect credential-bearing requests to any syntactically valid host. Consequently, configuration poisoning or unauthorized modification can turn the fulfillment operation into a credential-exfiltration channel. The transmitted ...[truncated 1477 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/file_utils.py:26
Finding

Sensitive Order and Payment Data Stored Without Explicit Access Controls

Content
View full analysis
Path: path = order_path(indicator, order_no) path.parent.mkdir(parents=True, exist_ok=True) path.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8") return path ``` ### Technical Analysis The code creates order directories and files using default operating-system permissions modified only by the process umask. It does not explicitly require owner-only permissions. The initial order record contains the original question and payment metadata. The documented payment integration later writes `payCredential` into the same order file. Questions for alert services may include email addresses or other personal data. On a system with a permissive umask or shared order root, these files may be readable by other local users. Existing directories or files may also retain unsafe permissions because the code never verifies or corrects their ownership and mode. ### Attack Path 1. The Skill runs in a multi-user environment with a permissive umask, or `OPENCLAW_ORDER_ROOT` points to a shared location. 2. `save_order()` creates an order directory and JSON file without specifying restrictive permissions. 3. The payment integration writes a payment credential into that order file. 4. Another local user with filesystem access reads the file and obtains the stored order data, personal information, and payment credential. ### Impact Assessment The affected privileges are limited to local accounts that can access the created path under inherited filesystem permissions. Exposed data may include: - Payment credentials. - Order numbers and payment metadata. - Encrypted payment-related fields. - Service questions and parameters. - Email addresses or other personal information sup ...[truncated 218 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill is presented as an FX quote/payment skill, but its release workflow instructs running a cleanup script that scans the project tree and deletes __pycache__ and .pyc artifacts. While not inherently malicious, this is behavior outside the user-facing finance/payment purpose and can normalize broader filesystem operations under a misleading description. In a skill with payment and credential-related permissions, undocumented local file operations increase trust and review risk.

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.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill's entire operational documentation and user-facing instructions are presented only in Chinese, with no indication that users may choose another language or locale. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Several user-visible error messages are hard-coded in Chinese, and the script provides no option to select another language or locale. This is a natural-language policy concern because the skill forces a specific language without user opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The error messages at L43 and L49 use Chinese text, which imposes a specific language on users. The file does not provide any user opt-in, fallback, or documentation that this skill is intentionally limited to a Chinese-speaking or region-specific context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

All user-visible status and error messages are hardcoded in Chinese, which imposes a specific language on users without opt-in or configurability. The policy explicitly calls out language or locale constraints as violations unless the user is given a choice or the restriction is clearly justified.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The code sends an order number, payment credential, and user question to a remote endpoint without any in-code consent gate, masking, or minimization. Because this skill explicitly involves real JD clawtip payment flows, the transmitted credential is highly sensitive; if the base URL is misconfigured, intercepted, or points to an untrusted service, it could enable unauthorized fulfillment attempts or expose payment-related data.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

该文件的自然语言说明整体仅以中文提供,未见提供其他语言版本、语言切换说明或用户选择机制。按照语言/地区政策检查标准,这构成了默认强制单一语言而未取得用户选择的情形。

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

This code constructs a query string from user-supplied inputs and sends it over the network via request_json, but there is no confirmation prompt, warning message, or explanatory comment indicating that the data will be sent to an external service. For a code file, network transmission of user data is in scope for missing-warning checks when no disclosure is present.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

This code creates directories and writes JSON data to disk, but there is no confirmation prompt, logging, comment, or docstring disclosing that user data will be persisted under a local order path. For a code file, silent file writes are in scope when they lack any visible warning, especially since the storage location may be influenced by an environment variable.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The script makes an outbound HTTP request to a base URL and uses a user-provided currency selection to determine which quote is retrieved, but the code does not display any notice that it contacts an external service. For a code file, outbound network activity that transmits user or system context should have some visible disclosure unless it is clearly communicated elsewhere.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.