Back to skill

Security audit

Yufluent Clawhub Publish Yufluentcn Comp Track

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly coherent as a cloud competitor-analysis client, but it can upload arbitrary local file contents and send the API key to an unvalidated endpoint.

Install only if you are comfortable sending competitor and first-party listing text to Yufluent's cloud service. Do not pass sensitive local paths such as .env, SSH keys, cloud credentials, or private configs as --competitor or --our-listing. Leave TOKENAPI_BASE_URL unset unless you intentionally use a trusted endpoint, because the skill will send TOKENAPI_KEY and payload data to that destination.

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
scripts/cloud_cli.py:12
Finding

Unrestricted Local File Content Can Be Uploaded to the Cloud API

Content
View full analysis

Vulnerability Details

File Location: scripts/cloud_cli.py:12-20; data is subsequently transmitted at scripts/run.py:39-48
Vulnerability Type: Unrestricted file read followed by network transmission
Risk Level: Medium

Vulnerable Code

python
def read_text_arg(value: str) -> str:
    """CLI parameter: treat an existing path as a file; otherwise use it as text."""
    raw = (value or "").strip()
    if not raw:
        return ""
    path = Path(raw)
    if path.is_file():
        return path.read_text(encoding="utf-8")
    return raw

The resulting file contents are placed directly into the cloud request:

python
payload: dict = {
    "platform": args.platform,
    "lang": args.lang,
    "our_product": args.our_product.strip(),
    "competitor": read_text_arg(args.competitor),
}
if args.our_listing:
    payload["our_listing"] = read_text_arg(args.our_listing)

try:
    data = run_skill(SKILL_API_ID, payload, timeout=180.0)

Technical Analysis

The documented functionality permits competitor and first-party listing text to be loaded from .txt files. However, read_text_arg() accepts any readable regular file recognized by Path.is_file(). It does not enforce an approved workspace, file extension, content type, maximum size, symlink policy, or sensitive-path denylist.

Because run.py places the returned text into the cloud API payload, any UTF-8-readable file accessible to the invoking process can be uploaded. Potential targets include .env files, source configuration, API credentials, cloud configuration, agent configuration, and private keys stored in text-compatible formats.

This behavior exceeds the minimum file privileges required for listing analysis because the Skill only needs access to explicitly selected listing documents, not unrestricted process-readable files.

Attack Path

  1. An attacker supplies content that influences an Agent or ...[truncated 1026 chars]
Remediation
View remediation

Remediation Suggestions

  1. Separate literal text and file input into distinct arguments, such as --competitor-text and --competitor-file, so a text value cannot be silently reinterpreted as a path.
  2. Restrict file access to an explicitly configured workspace:
    python
    workspace = Path(os.environ["SKILL_WORKSPACE"]).resolve()
    candidate = Path(value).resolve(strict=True)
    candidate.relative_to(workspace)
    
  3. Reject symlinks or validate the final resolved target before reading it.
  4. Permit only expected extensions such as .txt and validate that the content is plain text.
  5. Enforce a conservative maximum file size before reading or uploading.
  6. Deny known sensitive names and locations, including .env, .ssh, cloud credential directories, and agent configuration files.
  7. Require explicit user confirmation that identifies the resolved path and remote destination before uploading local file contents.
  8. Document that selected listing content is transmitted to the cloud service.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/yufluent_api.py:232
Finding

Bearer Credential and Listing Data Can Be Sent to an Arbitrary or Insecure Endpoint

Content
View full analysis

Vulnerability Details

File Location: scripts/yufluent_api.py:19-23, 55-63, 140-150, and 232-235
Vulnerability Type: Unvalidated network destination and potentially plaintext sensitive-data transmission
Risk Level: Medium

Vulnerable Code

python
def normalize_api_root(base_url: str) -> str:
    base = (base_url or "").strip().rstrip("/")
    if not base:
        base = "http://localhost:8080/v1"
    if base.endswith("/v1"):
        return base
    return f"{base}/v1"
python
def _auth_headers(api_key: str) -> dict[str, str]:
    return {
        "Authorization": f"Bearer {api_key}",
        "Accept": "application/json",
    }


def _json_headers(api_key: str) -> dict[str, str]:
    return {**_auth_headers(api_key), "Content-Type": "application/json"}
python
def _post_json(
    url: str,
    *,
    api_key: str,
    body: dict[str, Any] | None = None,
    timeout: float,
) -> requests.Response:
    kwargs: dict[str, Any] = {
        "headers": _json_headers(api_key) if body is not None else _auth_headers(api_key),
        "timeout": timeout,
    }
    if body is not None:
        kwargs["json"] = body
    return requests.post(url, **kwargs)
python
root = base_url or os.getenv("TOKENAPI_BASE_URL", "")
url = skill_run_url(root, skill_id)
try:
    resp = _post_json(url, api_key=key, body=payload, timeout=timeout)
except requests.RequestException as exc:
    raise YufluentApiError(f"Request failed: {exc}") from exc

Technical Analysis

TOKENAPI_BASE_URL is accepted without validating its scheme, hostname, port, or trust status. The bearer credential is then attached to a POST request to the resulting URL together with user-supplied competitor and first-party listing content.

HTTPS is not required. The built-in HTTP default is a loopback address and is reasonable for a local service, but the implementation al ...[truncated 1896 chars]

Remediation
View remediation

Remediation Suggestions

  1. Parse the endpoint with urllib.parse.urlsplit() and reject malformed URLs, embedded credentials, fragments, and unsupported schemes.
  2. Require HTTPS for every non-loopback destination.
  3. Permit plaintext HTTP only when the resolved host is an explicit loopback address such as 127.0.0.1, ::1, or a safely validated localhost.
  4. Allowlist the official production API host. If custom hosts are required, require explicit configuration and interactive confirmation.
  5. Do not automatically reuse a production token for custom endpoints. Use endpoint-scoped development credentials instead.
  6. Set an explicit redirect policy. Prefer allow_redirects=False, or validate every redirect destination before resending sensitive data.
  7. Display the normalized destination before transmitting listing content when a nonstandard endpoint is configured.
  8. Document which payload fields and credentials are sent to the remote service.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (20)

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

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The code permits the destination base URL to come from an environment variable and then uses it directly in requests.post. Because the same client also attaches the Bearer API key in the Authorization header, a malicious or compromised environment configuration can redirect requests and credentials to an attacker-controlled endpoint, causing credential exfiltration and data leakage.

Content

Scanner excerpt · scripts/yufluent_api.py (reported line 150)May include surrounding context.

python
}
    if body is not None:
        kwargs["json"] = body
    return requests.post(url, **kwargs)


def _raise_for_status(resp: requests.Response) -> None:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · README.md (reported line 10)May include surrounding context.

powershell
cd skills\yufluentcn-comp-track
pip install -r requirements.txt
copy .env.example .env
# 编辑 TOKENAPI_KEY、TOKENAPI_BASE_URL

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

If the runner accepts arbitrary local file paths and generic payload handling beyond pasted competitor text, the actual behavior exceeds the declared scope of listing comparison. This is risky because a user or downstream agent could be induced to read unrelated local files and send their contents to the cloud harness, turning a comparison skill into a local-data exfiltration path.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

If the runner accepts arbitrary local file paths and generic payload handling beyond pasted competitor text, the actual behavior exceeds the declared scope of listing comparison. This is risky because a user or downstream agent could be induced to read unrelated local files and send their contents to the cloud harness, turning a comparison skill into a local-data exfiltration path.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 28)May include surrounding context.

md
## 快速开始(3 步,60 秒)

1. **注册获取 API 密钥** → https://claw.changzhiai.com/login (新用户即送体验积分,无需绑卡)
2. **设置环境变量**:export TOKENAPI_KEY=*** 或写入 .env 文件
3. **运行**:参照下方 Examples 示例执行 python scripts/run.py ...

> 还没注册?前往 https://claw.changzhiai.com/login 免费获取密钥。

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill description is written as a Chinese-only instruction and presents the workflow as pasting competitor copy in Chinese, with no natural-language indication that users may choose another language or locale. Under the policy rule, forcing a specific language without user opt-in is a language/locale policy concern unless clearly documented as region-specific and justified.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill declares executable/networked behavior via OpenClaw metadata (env requirement and pip install) and instructs use of a Python runner, but it does not declare any explicit tool scope such as allowed tools or permissions. That creates unnecessary ambiguity about what the skill may access, making it easier for an agent runtime to grant broader file, env, or network capabilities than users expect.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The trigger list includes broad everyday phrases such as "竞品分析", "跟竞品对比一下", and "competitor analysis" without clear activation boundaries or exclusion conditions. These phrases could match ordinary discussion about competitors rather than an intentional request to invoke this specific skill.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The image helper accepts arbitrary local file paths and also passes through remote http(s) URLs unchanged, despite the skill being described as a text-based competitor listing comparison tool. In a cloud-executed harness, this broad input surface can enable unintended local file ingestion or server-side fetching of attacker-controlled URLs, creating data exposure and SSRF-style risk beyond the stated purpose of the skill.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script sets --lang to default to zh, which imposes a specific language choice unless the user explicitly overrides it. This is a natural-language policy concern because the file does not document a justified region-specific constraint or present language choice as opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

Multiple docstrings and user-facing error messages in this file are presented only in Chinese, which can effectively force a specific language on users. The file does not provide an opt-in language selection mechanism or explain that the skill is intentionally limited to a Chinese-speaking context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The skill sends user-supplied payload data to a remote service for execution, but this file provides no user-facing disclosure that pasted competitor listings or analysis inputs leave the local environment. For a competitor-analysis skill, those inputs may contain sensitive business research, making undisclosed remote transmission materially risky.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The file includes a record_outcome capability that submits additional payloads to /agent/outcomes, which is broader than the stated competitor snapshot analysis purpose. This expands the skill's data egress surface and creates an undisclosed path for transmitting user or execution data to the vendor backend.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

Telemetry/outcome submission is not justified by the skill's declared purpose of competitor copy comparison, so users may provide sensitive competitor content without expecting secondary transmission. In this context, hidden analytics or outcomes logging increases privacy and confidentiality risk even if the endpoint is vendor-operated.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

Outcome-recording requests transmit arbitrary payload data to a remote endpoint without any disclosure in this code path. Because this behavior is auxiliary to the stated skill purpose, it creates an unexpected exfiltration channel for user data, run metadata, or analysis results.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency specification uses a lower-bound only constraint (requests>=2.31.0), which makes builds non-reproducible and allows installation of any future release, including versions with breaking changes or newly introduced security issues. In a cloud-executed skill, this weakens supply-chain control and makes it harder to verify that deployed environments are not pulling vulnerable or unexpected packages.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
requests>=2.31.0

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); 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) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
87% confidence
Finding

The manifest references requests without pinning to a specific version, and requests has multiple historical advisories. Because the installed version is unverifiable from this file alone, there is a realistic risk that the runtime could resolve to a vulnerable release, especially across different environments or future rebuilds.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The natural-language text in the module docstring and function docstrings is written only in Chinese, which imposes a specific language on maintainers or users of the skill without any opt-in or justification visible in this file. The policy requires flagging language or locale constraints when the skill does not explicitly offer a choice or document a valid region-specific reason.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The manifest frames the skill as analyzing pasted competitor copy, but this helper also interprets user input as a filesystem path and reads the file contents. While this may be a convenience feature, local file access is not clearly justified by the stated 'paste competitor text' purpose and expands the skill's capability beyond pure text comparison input handling.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The function reads TOKENAPI_KEY from environment variables, which is a sensitive credential access path. Although the code documents how to set the variable when missing, it does not clearly disclose that the skill will read and use this credential for remote authentication.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.