Back to skill

Security audit

weixia

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent Weixia community API client, but it can send a saved account API key and wallet/message actions to an arbitrary endpoint chosen by an environment variable.

Review this carefully before installing. Use it only if you trust the Weixia service and your execution environment, do not set WEIXIA_API_BASE to an untrusted URL, and be especially cautious with wallet transfer or withdrawal commands. Prefer a version that pins dependencies and validates the API host before sending the saved API key.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/weixia.py:18
Finding

Configurable API Endpoint Can Exfiltrate the Stored API Key

Content
View full analysis

Vulnerability Details

File Location: scripts/weixia.py:18, 42-55; scripts/weixia.sh:11, 106-108
Vulnerability Type: Unvalidated credential destination
Risk Level: High

Vulnerable Code

python
# API address
API_BASE = os.getenv("WEIXIA_API_BASE", "https://api.weixia.chat")

def get_api_key() -> Optional[str]:
    """Get the saved API key."""
    if API_KEY_FILE.exists():
        return API_KEY_FILE.read_text().strip()
    return None

def _headers() -> dict:
    """Build request headers."""
    api_key = get_api_key()
    if api_key:
        return {"Authorization": api_key, "Content-Type": "application/json"}
    return {"Content-Type": "application/json"}
bash
API_BASE="${WEIXIA_API_BASE:-https://api.weixia.chat}"

export WEIXIA_API_BASE
"$PYTHON" "$PYTHON_SCRIPT" "$@"

Technical Analysis

The remote service origin is accepted directly from the inherited WEIXIA_API_BASE environment variable without validating its scheme, hostname, port, or embedded credentials. Authenticated operations use _headers(), which reads the API key from ~/.weixia/.api_key and adds it to the Authorization header.

Consequently, a process or execution environment that controls this variable can redirect authenticated requests to an attacker-controlled server. The implementation also does not require HTTPS, so it can be directed to a plaintext HTTP endpoint.

Attack Path

  1. An attacker influences the Skill's environment, wrapper, shell profile, CI configuration, or invocation and sets WEIXIA_API_BASE to an attacker-controlled URL.
  2. The user runs an authenticated operation such as me, balance, transfer, or withdraw.
  3. _headers() reads the stored API key from ~/.weixia/.api_key.
  4. The client sends the API key in the Authorization header to the configured endpoint.
  5. The attacker captures the key and submits authenticated requests to the legitimate W ...[truncated 591 chars]
Remediation
View remediation

Remediation Suggestions

  • Require https for every endpoint that may receive credentials.
  • Parse the URL and reject embedded credentials, fragments, unexpected ports, malformed hostnames, and non-HTTPS schemes.
  • Restrict credential-bearing requests to an explicit allowlist such as api.weixia.chat.
  • If custom endpoints are required for development, require explicit user approval before transmitting a stored key to a non-default origin.
  • Maintain credentials per origin rather than applying one stored key to every configured endpoint.
  • Consider ignoring inherited endpoint overrides for wallet and account-management commands unless a secure configuration file explicitly enables them.
  • Add automated tests confirming that credentials are never sent to HTTP or unapproved origins.

T08 · Insecure Dependencies

Warning
Location
scripts/weixia.sh:62
Finding

Automatic Installation of Unpinned Third-Party Dependencies

Content
View full analysis

Vulnerability Details

File Location: scripts/weixia.sh:62-72; package.json:31-33
Vulnerability Type: Unpinned dependency installation from an ambient package index
Risk Level: Medium

Vulnerable Code

bash
# Install Python dependencies
install_deps() {
    local py="$1"
    log_info "Installing Python dependencies..."
    "$py" -m pip install -q httpx 2>/dev/null || {
        log_warn "pip installation failed; trying ensurepip..."
        "$py" -m ensurepip --upgrade 2>/dev/null
        "$py" -m pip install -q httpx
    }
    log_info "Dependency installation complete"
}
json
"dependencies": {
  "httpx": ">=0.24.0"
}

Technical Analysis

When httpx is unavailable, ordinary Skill execution invokes pip and installs an unconstrained current release. The package metadata similarly specifies only a lower bound. There is no lockfile, exact reviewed version, integrity hash, trusted repository constraint, or isolation requirement.

Pip uses its ambient configuration and index settings. Therefore, package resolution can be affected by a compromised repository, hostile index configuration, dependency compromise, or a malicious future release satisfying the broad version constraint. Python package installation may execute build-backend code, while subsequent import executes package initialization code.

This finding concerns unsafe supply-chain handling; the audited package does not itself demonstrate that the current httpx package is malicious.

Attack Path

  1. httpx is absent from the selected Python environment.
  2. The user invokes scripts/weixia.sh.
  3. The script automatically runs python -m pip install -q httpx.
  4. Pip resolves packages using mutable index content and ambient pip configuration.
  5. A compromised or substituted package is downloaded and installed.
  6. Malicious build code executes during installation, or malicious runtime code execute ...[truncated 575 chars]
Remediation
View remediation

Remediation Suggestions

  • Pin httpx and every transitive dependency to reviewed versions.
  • Use a lockfile or requirements file containing cryptographic hashes, and install with hash verification enabled.
  • Configure an explicit trusted package repository rather than relying on ambient pip index settings.
  • Move dependency installation to a separate, explicit setup step requiring user approval instead of installing packages automatically during normal execution.
  • Install into a dedicated virtual environment to avoid modifying the user's global Python environment.
  • Regularly review and update pinned dependencies through a controlled dependency-update process.
  • Avoid suppressing pip diagnostics needed to identify unexpected indexes, package substitutions, or installation failures.
Vulnerability Patterns
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • 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
Findings (81)

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
93% confidence
Finding

The API base URL is taken directly from the WEIXIA_API_BASE environment variable and used for outbound requests, including registration flows that return and store API keys. If an attacker can influence the environment, they can redirect the client to a malicious server and capture credentials, wallet-related data, messages, and other sensitive operations.

Content

Scanner excerpt · scripts/weixia.py (reported line 83)May include surrounding context.

python
"owner": owner
    }

    response = httpx.post(f"{API_BASE}/api/auth/register", json=data, timeout=30)
    response.raise_for_status()

    result = response.json()

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
98% confidence
Finding

This login request sends the saved API key in the X-API-Key header to whatever host is configured in WEIXIA_API_BASE. A malicious or misconfigured environment can therefore exfiltrate the API key directly to an attacker-controlled endpoint, enabling account takeover and follow-on wallet or messaging abuse.

Content

Scanner excerpt · scripts/weixia.py (reported line 104)May include surrounding context.

python
if not api_key:
        raise ValueError("未找到 API Key,请先注册")

    response = httpx.post(
        f"{API_BASE}/api/auth/login",
        headers={"X-API-Key": api_key},
        timeout=30

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.get (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

Authenticated profile requests use headers derived from the locally stored API key and send them to the environment-controlled API base. If the base URL is attacker-controlled, the credential and returned account data can be harvested.

Content

Scanner excerpt · scripts/weixia.py (reported line 115)May include surrounding context.

python
def get_me() -> Dict[str, Any]:
    """获取当前 Agent 信息"""
    response = httpx.get(f"{API_BASE}/api/auth/me", headers=_headers(), timeout=30)
    response.raise_for_status()
    return response.json()

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.put (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

Profile update operations send authenticated data to a host chosen by an environment variable. This can leak credentials and user-supplied profile content, and can trick the user into believing changes were made to the legitimate service when they were sent elsewhere.

Content

Scanner excerpt · scripts/weixia.py (reported line 135)May include surrounding context.

python
if personality:
        data["personality"] = personality

    response = httpx.put(f"{API_BASE}/api/agents/me", json=data, headers=_headers(), timeout=30)
    response.raise_for_status()
    return response.json()

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/weixia.py (reported line 146)May include surrounding context.

python
if skill:
        params["skill"] = skill

    response = httpx.get(f"{API_BASE}/api/agents", params=params, timeout=30)
    response.raise_for_status()
    return response.json()

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/weixia.py (reported line 153)May include surrounding context.

python
def get_agent(agent_id: str) -> Dict[str, Any]:
    """获取 Agent 详情"""
    response = httpx.get(f"{API_BASE}/api/agents/{agent_id}", timeout=30)
    response.raise_for_status()
    return response.json()

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/weixia.py (reported line 160)May include surrounding context.

python
def is_agent_online(agent_id: str) -> Dict:
    """检查 Agent 是否在线"""
    response = httpx.get(f"{API_BASE}/api/agents/{agent_id}/online", timeout=30)
    response.raise_for_status()
    return response.json()

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

Creating a post uses authenticated headers built from the stored API key and sends user content to the environment-controlled API base. A malicious base can capture credentials and submitted content while impersonating the legitimate service.

Content

Scanner excerpt · scripts/weixia.py (reported line 188)May include surrounding context.

python
"tags": tags or []
    }

    response = httpx.post(f"{API_BASE}/api/posts", json=data, headers=_headers(), timeout=30)
    response.raise_for_status()
    return response.json()

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/weixia.py (reported line 201)May include surrounding context.

python
if tag:
        params["tag"] = tag

    response = httpx.get(f"{API_BASE}/api/posts", params=params, timeout=30)
    response.raise_for_status()
    return response.json()

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/weixia.py (reported line 208)May include surrounding context.

python
def get_post(post_id: str) -> Dict[str, Any]:
    """获取帖子详情"""
    response = httpx.get(f"{API_BASE}/api/posts/{post_id}", timeout=30)
    response.raise_for_status()
    return response.json()

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

Liking a post sends authenticated headers to the host indicated by WEIXIA_API_BASE. An attacker who can control that environment value can collect the API key and induce unauthorized account actions.

Content

Scanner excerpt · scripts/weixia.py (reported line 215)May include surrounding context.

python
def like_post(post_id: str) -> Dict:
    """点赞帖子"""
    response = httpx.post(f"{API_BASE}/api/posts/{post_id}/like", headers=_headers(), timeout=30)
    response.raise_for_status()
    return response.json()

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

Comment submission transmits both the stored credential and user-generated content to the configured API base. If redirected to a malicious host, this leaks the API key and private or sensitive text content.

Content

Scanner excerpt · scripts/weixia.py (reported line 222)May include surrounding context.

python
def comment_post(post_id: str, content: str) -> Dict:
    """评论帖子"""
    response = httpx.post(
        f"{API_BASE}/api/posts/{post_id}/comment",
        json={"content": content},
        headers=_headers(),

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/weixia.py (reported line 234)May include surrounding context.

python
def list_comments(post_id: str, limit: int = 20, offset: int = 0) -> List[Dict]:
    """获取帖子评论列表"""
    response = httpx.get(
        f"{API_BASE}/api/posts/{post_id}/comments",
        params={"limit": limit, "offset": offset},
        timeout=30

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

Task creation uses authenticated headers and sends potentially sensitive task details to a host chosen by an environment variable. This can leak credentials and business-sensitive content to an attacker-controlled endpoint.

Content

Scanner excerpt · scripts/weixia.py (reported line 271)May include surrounding context.

python
if deadline:
        data["deadline"] = deadline

    response = httpx.post(f"{API_BASE}/api/tasks", json=data, headers=_headers(), timeout=30)
    response.raise_for_status()
    return response.json()

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/weixia.py (reported line 282)May include surrounding context.

python
if skill:
        params["skill"] = skill

    response = httpx.get(f"{API_BASE}/api/tasks", params=params, timeout=30)
    response.raise_for_status()
    return response.json()

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/weixia.py (reported line 289)May include surrounding context.

python
def get_task(task_id: str) -> Dict[str, Any]:
    """获取需求详情"""
    response = httpx.get(f"{API_BASE}/api/tasks/{task_id}", timeout=30)
    response.raise_for_status()
    return response.json()

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.get (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

Recommended tasks are fetched with authenticated headers, so a malicious WEIXIA_API_BASE can harvest the API key and observe personalized account data. This is more sensitive than public listing endpoints because it is tied to the user's identity and auth context.

Content

Scanner excerpt · scripts/weixia.py (reported line 296)May include surrounding context.

python
def recommend_tasks(limit: int = 10) -> List[Dict]:
    """获取推荐给我的需求"""
    response = httpx.get(
        f"{API_BASE}/api/tasks/recommend",
        params={"limit": limit},
        headers=_headers(),

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

Applying for a task sends credentials to the environment-selected host and performs a state-changing action. An attacker controlling the base URL can steal the API key and falsely acknowledge or manipulate workflow actions.

Content

Scanner excerpt · scripts/weixia.py (reported line 308)May include surrounding context.

python
def apply_task(task_id: str) -> Dict:
    """申请接单"""
    response = httpx.post(
        f"{API_BASE}/api/tasks/{task_id}/apply",
        headers=_headers(),
        timeout=30

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

Task assignment is an authenticated operation that can be redirected to an attacker-controlled server through WEIXIA_API_BASE. This can expose credentials and trick operators into believing assignments were made in the real platform.

Content

Scanner excerpt · scripts/weixia.py (reported line 319)May include surrounding context.

python
def assign_task(task_id: str, assignee_id: str) -> Dict:
    """指派任务(发布者操作)"""
    response = httpx.post(
        f"{API_BASE}/api/tasks/{task_id}/assign",
        json={"assignee_id": assignee_id},
        headers=_headers(),

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

Completing a task is a sensitive state-changing API call made to an environment-controlled origin with authentication headers. A hostile endpoint can capture the API key and spoof task-completion responses.

Content

Scanner excerpt · scripts/weixia.py (reported line 331)May include surrounding context.

python
def complete_task(task_id: str) -> Dict:
    """完成任务(发布者确认)"""
    response = httpx.post(
        f"{API_BASE}/api/tasks/{task_id}/complete",
        headers=_headers(),
        timeout=30

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

Task cancellation is another authenticated mutating request subject to endpoint redirection through WEIXIA_API_BASE. This enables credential exfiltration and operational deception if the host is malicious.

Content

Scanner excerpt · scripts/weixia.py (reported line 342)May include surrounding context.

python
def cancel_task(task_id: str) -> Dict:
    """取消任务(发布者操作)"""
    response = httpx.post(
        f"{API_BASE}/api/tasks/{task_id}/cancel",
        headers=_headers(),
        timeout=30

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

Activity creation sends authenticated data to a host controlled by environment configuration. If hijacked, it leaks credentials and submitted event details, and may mislead the user about successful creation on the real service.

Content

Scanner excerpt · scripts/weixia.py (reported line 385)May include surrounding context.

python
if tags:
        data["tags"] = tags

    response = httpx.post(f"{API_BASE}/api/activities", json=data, headers=_headers(), timeout=30)
    response.raise_for_status()
    return response.json()

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/weixia.py (reported line 398)May include surrounding context.

python
if tag:
        params["tag"] = tag

    response = httpx.get(f"{API_BASE}/api/activities", params=params, timeout=30)
    response.raise_for_status()
    return response.json()

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/weixia.py (reported line 405)May include surrounding context.

python
def get_activity(activity_id: str) -> Dict[str, Any]:
    """获取活动详情"""
    response = httpx.get(f"{API_BASE}/api/activities/{activity_id}", timeout=30)
    response.raise_for_status()
    return response.json()

Tainted flow: 'API_BASE' from os.getenv (line 18, credential/environment) → httpx.put (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

Updating an activity is an authenticated state-changing request to an environment-controlled host. This can leak the API key and any submitted event metadata, while spoofing success or failure.

Content

Scanner excerpt · scripts/weixia.py (reported line 430)May include surrounding context.

python
if tags is not None:
        data["tags"] = tags

    response = httpx.put(f"{API_BASE}/api/activities/{activity_id}", json=data, headers=_headers(), timeout=30)
    response.raise_for_status()
    return response.json()

Static analysis

No suspicious patterns detected.