Back to skill

Security audit

庄家异动探测器

Security checks for vulnerabilities and agentic risk

Overview

The skill’s market-data and payment purpose is mostly disclosed, but it ships a hardcoded payment API credential and can send it to an environment-configured endpoint.

Review before installing. The payment feature is disclosed and purpose-aligned, but the publisher should remove and rotate the embedded SkillPay key, actually read SKILLPAY_API_KEY from the environment, restrict SkillPay API hosts to approved HTTPS origins, and update the pinned HTTP dependency.

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

T09 · Insecure Skill Coding Practices

Error
Location
main.py:10
Finding
Hardcoded SkillPay API Credential Can Be Disclosed Through a Configurable Network Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `main.py:10-12`, `main.py:194-199`, and `main.py:217-221` **Vulnerability Type**: Hardcoded secret and credential exfiltration through an attacker-controlled endpoint **Risk Level**: High ### Vulnerable Code ```python SKILLPAY_API_KEY = "sk_8b36c2ca9e774eb0243752f907b086e78c8af866a4088d3e3475113ed446b71" SKILLPAY_API_BASE = os.getenv("SKILLPAY_API_BASE", "https://api.skillpay.me") SKILLPAY_WEB_BASE = os.getenv("SKILLPAY_WEB_BASE", "https://pay.skillpay.me") ``` The credential is transmitted when a charge is created: ```python def create_skillpay_charge(amount: str, currency: str) -> Tuple[str, str]: if not SKILLPAY_API_KEY: raise HTTPException(status_code=400, detail="Missing SKILLPAY_API_KEY") url = f"{SKILLPAY_API_BASE.rstrip('/')}/v1/charges" headers = { "Authorization": f"Bearer {SKILLPAY_API_KEY}", "Content-Type": "application/json", } body = { "amount": amount, "currency": currency, "title": "OpenClaw Skill Payment", "description": "Polymarket Movers x3", } r = requests.post(url, json=body, headers=headers, timeout=20) if r.status_code not in (200, 201): raise HTTPException(status_code=502, detail="SkillPay create charge failed") data = r.json() cid = str(data.get("id") or data.get("charge_id") or "") purl = data.get("payment_url") if not purl and cid: purl = f"{SKILLPAY_WEB_BASE.rstrip('/')}/checkout/{cid}" if not cid or not purl: raise HTTPException(status_code=502, detail="Invalid SkillPay response") return cid, purl ``` It is also transmitted during payment-status queries: ```python def get_skillpay_status(charge_id: str) -> str: if not SKILLPAY_API_KEY: raise HTTPException(status_code=400, detail="Missing SKILLPAY_API_KEY") url = f"{SKILLPAY_API_BASE.rstrip('/')}/v1/charges/{charge_id}" headers = {"Authorization": f"Bearer {SKILLPAY_API_KE ...[truncated 3219 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Immediately revoke and rotate the exposed SkillPay API credential. Treat it as compromised even if the repository was not intended to be public. 2. Remove the credential from source code, repository history, build artifacts, container layers, logs, and distributed packages. 3. Load the key from the required environment variable or a managed secret store: ```python SKILLPAY_API_KEY = os.getenv("SKILLPAY_API_KEY") if not SKILLPAY_API_KEY: raise RuntimeError("SKILLPAY_API_KEY is required") ``` 4. In production, use a fixed SkillPay API origin rather than accepting an arbitrary base URL from the environment. 5. If endpoint configurability is required for controlled testing, validate the parsed URL before sending credentials: - Require HTTPS. - Require an exact approved hostname. - Reject embedded user information, unexpected ports, IP literals, redirects to unapproved hosts, and hostname suffix tricks. 6. Disable automatic redirects for credential-bearing requests or verify every redirect destination before forwarding the Authorization header. 7. Give the replacement credential only the minimum provider-side permissions needed to create and verify charges. 8. Use separate credentials for development, testing, and production, and configure provider-side restrictions where available. 9. Add automated secret scanning to source-control and CI pipelines so commits containing API-key patterns are rejected. 10. Add tests confirming that credential-bearing requests can only be sent to approved SkillPay endpoints. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (10)

Tainted flow: 'url' from os.getenv (line 231, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Content
]
    for url in candidates:
        try:
            r = requests.get(url, timeout=15)
            if r.status_code != 200:
                continue
            payload = r.json()
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'url' from os.getenv (line 231, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
"title": "OpenClaw Skill Payment",
        "description": "Polymarket Movers x3",
    }
    r = requests.post(url, json=body, headers=headers, timeout=20)
    if r.status_code not in (200, 201):
        raise HTTPException(status_code=502, detail="SkillPay create charge failed")
    data = r.json()
Confidence
98% confidence
Finding
The payment API base URL is taken from an environment variable and used to send an authenticated POST request with the bearer key. If that environment variable is altered in deployment, the service will transmit the embedded SkillPay secret to an attacker-controlled endpoint, causing immediate credential exfiltration and enabling fraudulent charge operations.

Tainted flow: 'url' from os.getenv (line 231, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Content
raise HTTPException(status_code=400, detail="Missing SKILLPAY_API_KEY")
    url = f"{SKILLPAY_API_BASE.rstrip('/')}/v1/charges/{charge_id}"
    headers = {"Authorization": f"Bearer {SKILLPAY_API_KEY}"}
    r = requests.get(url, headers=headers, timeout=20)
    if r.status_code != 200:
        raise HTTPException(status_code=502, detail="SkillPay status query failed")
    data = r.json()
Confidence
98% confidence
Finding
This authenticated GET request also uses a URL derived from an environment-controlled base while attaching the SkillPay bearer token. A compromised deployment configuration can redirect status queries to a malicious host and leak the secret, after which an attacker may impersonate the service against the payment provider.

Possible Typosquatting: 'uvicorn' resembles popular package 'gunicorn'

High
Category
Supply Chain
Confidence
70% confidence
Finding
Package name closely resembles a popular package, suggesting possible typosquatting. Attackers publish malicious packages with similar names to trick developers into installing them.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The natural-language content of the skill is entirely Chinese, and the file does not indicate that the skill is region-specific or that users may choose another language. This can violate a language/locale policy when users are not given an explicit opt-in or alternative.

Context-Inappropriate Capability

Medium
Confidence
87% confidence
Finding
The skill's observable function is market-data retrieval, but it also creates and checks cryptocurrency payment charges before returning results. This hidden coupling increases operational and trust risk because users invoking a simple data skill may trigger financial workflow logic and related third-party data sharing they did not reasonably expect.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The code performs payment-provider interactions without any in-file user-facing disclosure or consent mechanism beyond returning a charge object from the API. In an agent-skill context, that makes the behavior more dangerous because callers may not understand they are engaging a third-party payment system or that identifiers and payment metadata are being transmitted externally.

External Transmission

Medium
Category
Data Exfiltration
Content
"title": "OpenClaw Skill Payment",
        "description": "Polymarket Movers x3",
    }
    r = requests.post(url, json=body, headers=headers, timeout=20)
    if r.status_code not in (200, 201):
        raise HTTPException(status_code=502, detail="SkillPay create charge failed")
    data = r.json()
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Known Vulnerable Dependency: requests==2.31.0 — 6 advisory(ies): CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi); CVE-2026-25645 (Requests has Insecure Temp File Reuse in its extract_zipped_paths() utility func) +3 more

Medium
Category
Supply Chain
Confidence
97% confidence
Finding
The dependency is pinned to requests==2.31.0, and the static analysis indicates multiple published advisories affecting that version. Using a known vulnerable HTTP client library is dangerous because it can expose credentials, weaken TLS/request verification behavior, or introduce unsafe file-handling paths depending on how the application uses requests. In a FastAPI-based skill, outbound HTTP requests are common, which makes this more relevant rather than theoretical.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The manifest description is written entirely in Chinese and indicates the skill's behavior in a way that implies a Chinese-language interaction model. There is no accompanying documentation of user language choice, opt-in, or a clear region-specific justification, which conflicts with the policy against forcing a specific language or locale without user consent.

Static analysis

No suspicious patterns detected.