Back to skill

Security audit

weixia

Security checks across malware telemetry and agentic risk

Overview

This is a disclosed Weixia community integration that can post, message, manage tasks, and use an in-app wallet through its API.

Install only if you want your agent to participate in Weixia. Protect ~/.weixia/.api_key, leave WEIXIA_API_BASE at the official endpoint unless you trust the alternative service, and require explicit confirmation before wallet transfers, withdrawals, address binding, public posts, task cancellation, or activity cancellation.

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

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

Critical
Category
Data Flow
Content
"owner": owner
    }

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

    result = response.json()
Confidence
96% confidence
Finding
`API_BASE` is fully controlled by the `WEIXIA_API_BASE` environment variable and is used to construct outbound URLs for registration and other authenticated requests. In this skill, that means an attacker who can influence the runtime environment can redirect traffic, including registration data and later credentials, to an attacker-controlled server, effectively causing credential/API-key exfiltration and unsafe wallet/task actions against the wrong endpoint.

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

Critical
Category
Data Flow
Content
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
Confidence
99% confidence
Finding
The login flow sends the saved API key in the `X-API-Key` header to whatever host is specified by `WEIXIA_API_BASE`. If an attacker can set that environment variable, they can capture the API key directly and then impersonate the agent, access private messages, and perform wallet operations.

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

Critical
Category
Data Flow
Content
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()
Confidence
98% confidence
Finding
Authenticated requests use `_headers()` and will transmit the stored API key in the `Authorization` header to the configured base URL. If the environment changes `API_BASE` to an attacker-controlled host, the key and account metadata can be disclosed and the user may unknowingly interact with a rogue backend.

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

Critical
Category
Data Flow
Content
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()
Confidence
98% confidence
Finding
This update endpoint sends authenticated profile modifications to a host derived from an untrusted environment variable. In the context of this skill, redirecting such state-changing requests can both leak credentials and cause users to believe they updated their real account while talking to a malicious service.

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

Critical
Category
Data Flow
Content
"tags": tags or []
    }

    response = httpx.post(f"{API_BASE}/api/posts", json=data, headers=_headers(), timeout=30)
    response.raise_for_status()
    return response.json()
Confidence
98% confidence
Finding
Creating a post sends authenticated content and the saved API key to a host controlled by `API_BASE`. Because this skill includes messaging, task, and wallet capabilities under one credential, exfiltration of that key is materially dangerous and enables broad account abuse.

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

Critical
Category
Data Flow
Content
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()
Confidence
98% confidence
Finding
This authenticated like action will send credentials to whatever host `API_BASE` points to. Redirecting the base URL can therefore leak the API key and trick the user into performing signed actions against a malicious backend.

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

Critical
Category
Data Flow
Content
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(),
Confidence
98% confidence
Finding
Comment submission combines user content with authentication headers and sends both to a host determined by the environment. In this community skill, compromise of the API key affects not just comments but the broader account, making endpoint substitution materially dangerous.

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

Critical
Category
Data Flow
Content
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()
Confidence
98% confidence
Finding
Task creation is an authenticated, state-changing request sent to a configurable origin. A malicious `API_BASE` could capture credentials and task metadata, and users might unknowingly interact with a fake service while believing they are posting on the real platform.

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

Critical
Category
Data Flow
Content
def recommend_tasks(limit: int = 10) -> List[Dict]:
    """获取推荐给我的需求"""
    response = httpx.get(
        f"{API_BASE}/api/tasks/recommend",
        params={"limit": limit},
        headers=_headers(),
Confidence
98% confidence
Finding
Recommended tasks are fetched with authentication headers, so a malicious `API_BASE` can receive the stored API key and user-specific data. Since the same credentials are reused for sensitive community and wallet features, endpoint redirection has meaningful account impact.

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

Critical
Category
Data Flow
Content
def apply_task(task_id: str) -> Dict:
    """申请接单"""
    response = httpx.post(
        f"{API_BASE}/api/tasks/{task_id}/apply",
        headers=_headers(),
        timeout=30
Confidence
98% confidence
Finding
Applying for a task is an authenticated state-changing operation sent to the environment-derived base URL. An attacker controlling that URL can harvest credentials and induce user actions against a rogue backend, undermining trust in the platform integration.

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

Critical
Category
Data Flow
Content
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(),
Confidence
98% confidence
Finding
This assignment endpoint sends authenticated privileged actions to a host selected by `WEIXIA_API_BASE`. If redirected, the API key is exposed and the user can be tricked into issuing management operations to an attacker-controlled service.

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

Critical
Category
Data Flow
Content
def complete_task(task_id: str) -> Dict:
    """完成任务(发布者确认)"""
    response = httpx.post(
        f"{API_BASE}/api/tasks/{task_id}/complete",
        headers=_headers(),
        timeout=30
Confidence
98% confidence
Finding
Task completion is a privileged authenticated action using the untrusted base URL. In this skill context, API-key theft can cascade into messaging and wallet abuse, so redirectable authenticated requests are dangerous.

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

Critical
Category
Data Flow
Content
def cancel_task(task_id: str) -> Dict:
    """取消任务(发布者操作)"""
    response = httpx.post(
        f"{API_BASE}/api/tasks/{task_id}/cancel",
        headers=_headers(),
        timeout=30
Confidence
98% confidence
Finding
Task cancellation is another authenticated state-changing request vulnerable to endpoint substitution through `API_BASE`. This can leak credentials and mislead the user about the real state of their tasks on the legitimate service.

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

Critical
Category
Data Flow
Content
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()
Confidence
98% confidence
Finding
Creating an activity sends authenticated data to a base URL taken from the environment without validation. A malicious override can capture the API key and any submitted content while presenting itself as the platform backend.

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

Critical
Category
Data Flow
Content
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()
Confidence
98% confidence
Finding
Updating an activity is an authenticated state-changing request that trusts `API_BASE` from the environment. That enables credential leakage and deceptive interactions with a rogue service if the runtime configuration is manipulated.

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

Critical
Category
Data Flow
Content
def publish_activity(activity_id: str) -> Dict:
    """发布活动(draft → published,仅组织者可操作)"""
    response = httpx.post(f"{API_BASE}/api/activities/{activity_id}/publish", headers=_headers(), timeout=30)
    response.raise_for_status()
    return response.json()
Confidence
98% confidence
Finding
Publishing an activity sends an authenticated privileged action to a host derived from an untrusted environment variable. In a skill that also exposes wallet features, compromise of the shared credential has broad consequences.

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

Critical
Category
Data Flow
Content
Returns:
        签到信息
    """
    response = httpx.post(
        f"{API_BASE}/api/activities/{activity_id}/checkin",
        json={"tag": tag},
        headers=_headers(),
Confidence
98% confidence
Finding
The check-in endpoint includes authentication headers and is reachable via the environment-controlled base URL. An attacker can capture credentials or spoof event interactions by redirecting this traffic to a malicious service.

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

Critical
Category
Data Flow
Content
def send_message(to_agent_id: str, content: str) -> Dict:
    """发送私聊消息"""
    response = httpx.post(
        f"{API_BASE}/api/messages",
        json={"to_agent_id": to_agent_id, "content": content},
        headers=_headers(),
Confidence
99% confidence
Finding
Private messaging sends both user content and authentication headers to the host specified by `API_BASE`. A malicious override can therefore exfiltrate the API key and sensitive message content, which is especially serious in a community/messaging skill that may handle confidential conversations and wallet coordination.

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

Critical
Category
Data Flow
Content
def get_conversations() -> List[Dict]:
    """获取会话列表"""
    response = httpx.get(
        f"{API_BASE}/api/messages/conversations",
        headers=_headers(),
        timeout=30
Confidence
98% confidence
Finding
Conversation retrieval uses authentication headers and trusts the environment-derived base URL. Redirecting this request can expose the API key and private conversation metadata to an attacker-controlled endpoint.

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

Critical
Category
Data Flow
Content
def get_unread() -> Dict:
    """获取未读消息数"""
    response = httpx.get(
        f"{API_BASE}/api/messages/unread",
        headers=_headers(),
        timeout=30
Confidence
98% confidence
Finding
Unread message counts may seem minor, but this endpoint still transmits the stored credential to the configured host. In this skill, that makes `API_BASE` manipulation a practical credential-exfiltration vector.

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

Critical
Category
Data Flow
Content
if before:
        params["before"] = before

    response = httpx.get(
        f"{API_BASE}/api/messages/with/{other_agent_id}",
        params=params,
        headers=_headers(),
Confidence
99% confidence
Finding
Chat history retrieval sends authentication headers to an environment-controlled endpoint and returns potentially sensitive private-message content. This can expose both the account credential and message history to an attacker, making the issue particularly severe in the messaging context of this skill.

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

Critical
Category
Data Flow
Content
def mark_read(message_id: str) -> Dict:
    """标记单条消息已读"""
    response = httpx.post(
        f"{API_BASE}/api/messages/{message_id}/read",
        headers=_headers(),
        timeout=30
Confidence
98% confidence
Finding
Marking a message as read is an authenticated state-changing call using the untrusted base URL. Even though the action is minor, the shared credential exposure remains significant.

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

Critical
Category
Data Flow
Content
def mark_all_read() -> Dict:
    """标记全部消息已读"""
    response = httpx.post(
        f"{API_BASE}/api/messages/read/all",
        headers=_headers(),
        timeout=30
Confidence
98% confidence
Finding
This bulk read-marking endpoint is authenticated and trusts `API_BASE` from the environment. The core risk is credential leakage and deceptive state changes when pointed at a rogue service.

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

Critical
Category
Data Flow
Content
def get_balance() -> Dict:
    """查看钱包余额"""
    response = httpx.get(
        f"{API_BASE}/api/wallet/balance",
        headers=_headers(),
        timeout=30
Confidence
99% confidence
Finding
Wallet balance retrieval sends authentication headers to the configured API host. In a wallet-enabled skill, exposing the API key to an attacker-controlled endpoint can enable subsequent financial actions, so the context makes this materially more dangerous than ordinary profile endpoints.

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

Critical
Category
Data Flow
Content
def get_wallet_info() -> Dict:
    """查看钱包详情(含链上地址)"""
    response = httpx.get(
        f"{API_BASE}/api/wallet/info",
        headers=_headers(),
        timeout=30
Confidence
99% confidence
Finding
Wallet info includes chain-address details and is fetched with authentication from a host derived from `WEIXIA_API_BASE`. Redirecting this request can leak both the credential and sensitive wallet metadata, increasing financial and privacy risk.

VirusTotal

66/66 vendors flagged this skill as clean.

View on VirusTotal

Static analysis

No suspicious patterns detected.