Back to skill

Security audit

wecom-voice-agent

Security checks across malware telemetry and agentic risk

Overview

This appears to be a functional enterprise voice-assistant skill, but it needs Review because sensitive call, ticket, memory, and webhook data flows are broader and less secure than the privacy disclosures claim.

Review this before installing in any real enterprise environment. Do not enable ZWJH_MCP_SERVER, SUPERVISOR_WEBHOOK, or custom_intents.yaml integrations until the executable paths and endpoints are allowlisted, TLS verification is fixed, credentials are protected, and users/admins have approved what call transcripts, tickets, phone numbers, and emotion labels may be stored or shared. Expose the webhook only behind validated WeCom signatures and a hardened HTTPS deployment.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (31)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
}

        try:
            proc = subprocess.run(
                self.server_path.split(),
                input=json.dumps(init_request) + "\n",
                capture_output=True,
Confidence
90% confidence
Finding
This code launches an external program whose path comes from the ZWJH_MCP_SERVER environment variable. Although subprocess.run is invoked without shell=True, the design still grants code-execution capability to whoever can influence environment configuration, and the launched binary receives sensitive caller history requests over stdin. In a voice agent handling user identifiers and phone numbers, that makes compromise of configuration or deployment environment materially dangerous.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
return None

        try:
            proc = subprocess.run(
                self.server_path.split(),
                input=json.dumps(request, ensure_ascii=False) + "\n",
                capture_output=True,
Confidence
92% confidence
Finding
This request path repeatedly spawns an external executable based on environment-controlled configuration and sends it sensitive conversation summaries, user IDs, phone numbers, and emotional metadata. Even without shell injection, this is a trust-boundary violation because an attacker who controls the configured path can replace the MCP server with a malicious program that exfiltrates or tampers with data.

Tainted flow: 'req' from os.environ.get (line 277, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
payload = json.dumps({"text": message}).encode("utf-8")
            req = Request(SUPERVISOR_WEBHOOK, data=payload, headers={"Content-Type": "application/json"})
            resp = urlopen(req, timeout=5, context=ctx)
            return resp.status == 200
        except Exception as e:
            logger.warning(f"webhook 通知失败: {e}")
Confidence
98% confidence
Finding
The code sends notification data to a URL taken from an environment variable, and the destination is reached with TLS certificate verification and hostname checking explicitly disabled. That creates a real exfiltration and SSRF-style risk: a compromised or misconfigured environment can redirect ticket and user data to an attacker-controlled endpoint, and the disabled TLS checks make interception or spoofing much easier.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill advertises no declared permissions, yet the documentation clearly describes capabilities for environment-variable access, local file read/write, network access, shell/CLI execution, and MCP integration. This is dangerous because reviewers and users may make trust decisions based on an incomplete capability declaration, leading to underestimation of the skill’s access to sensitive data and external systems.

Intent-Code Divergence

Medium
Confidence
92% confidence
Finding
The README contains contradictory statements about outbound calling support, which can mislead operators about what capabilities are actually enabled. In a communications agent, capability confusion can cause unsafe deployment decisions, incorrect permission grants, or accidental exposure of telephony features that administrators believed were unavailable.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
The manifest states that only wttr.in is contacted, but the custom intent plugin documentation allows configurable arbitrary HTTP endpoints. That mismatch hides a much broader outbound communication surface, which could be used to send user-derived data or invoke unvetted third-party enterprise APIs without the disclosure users were promised.

Description-Behavior Mismatch

Critical
Confidence
99% confidence
Finding
The skill repeatedly claims all processing is local and that call records/transcripts are not uploaded, yet the changelog documents a memory bridge that pulls history and writes call data to an external MCP memory service. This directly contradicts the privacy and data-locality claims, and could expose sensitive call transcripts and metadata to external systems without informed consent.

Context-Inappropriate Capability

High
Confidence
95% confidence
Finding
The custom intent system permits configurable arbitrary enterprise API invocation using templated requests and environment-based credentials. In the context of a voice assistant, this greatly expands the trust boundary: spoken input may drive privileged actions against internal systems, potentially causing unauthorized operations, data access, or exfiltration if the configuration is unsafe or overly broad.

Intent-Code Divergence

High
Confidence
96% confidence
Finding
The FAQ claims the skill 'absolutely will not' store, upload, or forward any voice data, while elsewhere the document states that outbound-call recordings are stored locally for 90 days. False or contradictory privacy claims are dangerous because they can invalidate user consent and lead operators to handle highly sensitive recordings under incorrect assumptions.

Intent-Code Divergence

High
Confidence
99% confidence
Finding
The implementation disables both certificate validation and hostname verification before sending the webhook request. This permits man-in-the-middle interception and spoofed endpoints even when using HTTPS, undermining confidentiality and integrity of supervisor notifications that include user and ticket details.

Context-Inappropriate Capability

Medium
Confidence
87% confidence
Finding
The skill is described as a local bridge between emotion analysis and ticketing, but it also supports sending ticket and user context to an external webhook configured via environment variables. That broadens the trust boundary and creates a data disclosure path outside the local system, especially because the message contains userid, ticket ID, title, and emotional classification.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
The module reads the MCP server executable path directly from an environment variable and later executes it, which expands the skill's capabilities from memory lookup into arbitrary external program launch. In real deployments, environment variables are often mutable by operators, wrappers, or compromised orchestration, so this creates a straightforward execution pivot and data-exfiltration path.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The stated fallback is misleading and the implementation re-opens the file as WAV in `_duration_fallback`, so malformed or non-WAV inputs still fail instead of safely degrading. In this skill context, the more important issue is fail-open behavior: `_error_result` returns `is_speech=True`, so an attacker can supply invalid audio to bypass the prefilter and force downstream processing.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The README advertises weather queries through the external wttr.in API while also emphasizing privacy and local processing, but it does not clearly warn users that query content will be sent over the network to a third party. Even if only city names are transmitted, this creates a data-sharing boundary that users and administrators may not expect from a supposedly local-first voice assistant.

Missing User Warnings

High
Confidence
96% confidence
Finding
The privacy section says the skill does not store, upload, or forward user voice data, yet later states that outbound-call recordings are stored locally and retained indefinitely. This contradiction can undermine informed consent and may lead users or administrators to mishandle highly sensitive call recordings under the false assumption that no voice data is retained.

Vague Triggers

Medium
Confidence
87% confidence
Finding
The knowledge intent uses very generic trigger phrases such as “怎么”, “如何”, “什么时候”, and “告诉我”, which can appear in ordinary conversation and overlap with many other intents. In a voice assistant, this can cause misrouting of user requests into a generic knowledge handler, potentially bypassing safer task-specific flows, confirmation logic, or data-access constraints implemented in other handlers.

Vague Triggers

Medium
Confidence
82% confidence
Finding
Several action/system triggers are broad conversational phrases such as “通知”, “告诉”, “叫我”, or similar wording that may occur in natural speech without clear user intent to execute an operation. Because these map to action handlers, accidental invocation could send messages, create reminders, or otherwise perform side effects based on ambiguous voice input.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The guide instructs users to expose a locally hosted webhook server to the public internet via frp/ngrok, but it does not warn about the resulting attack surface or recommend access controls, request validation, HTTPS hardening, or minimizing exposed endpoints. In the context of a webhook receiver handling enterprise messaging callbacks, this omission can lead users to deploy an externally reachable service insecurely, increasing the risk of probing, abuse, or unintended data exposure.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The document tells users to retrieve and use CorpID, AgentID, Secret, and later an access_token, but gives no guidance on treating these as sensitive credentials or preventing leakage through shell history, screenshots, logs, or source files. In an enterprise integration context, exposed secrets can allow unauthorized API access to the WeCom application and compromise bot behavior or enterprise data.

Missing User Warnings

High
Confidence
85% confidence
Finding
The bridge automatically creates tickets, raises priority, and notifies supervisors based solely on detected negative emotion, without confirmation, rate limiting, or a user-visible notice. In context, this can be abused by intentionally provoking the classifier or by false positives, causing unauthorized workflow actions and unnecessary exposure of sensitive conversation context.

Missing User Warnings

High
Confidence
90% confidence
Finding
The supervisor notification sends ticket and user context to an external webhook without any user-facing warning or demonstrated consent boundary. Because the message includes userid, ticket metadata, and emotional state, this is a privacy and data-governance issue even if the webhook is legitimately configured.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The skill is explicitly designed to retrieve historical caller requests and preferences and use them to personalize future interactions, but the code contains no consent gate, privacy notice, retention control, or purpose limitation. Because the data includes phone numbers, preferences, prior requests, and emotional tendency, this can expose sensitive personal information in ways users may not expect.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
The scheduler persistently writes task data to tasks.json, including targets, names, scripts, metadata, execution timestamps, and results, which may contain sensitive customer contact and call-content data. Because this is stored locally without access-control hardening, minimization, encryption, or explicit operator disclosure, it increases the risk of privacy leakage from disk exposure, backup collection, or multi-user host access.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
The code persists user identifiers, ASR text, pending confirmation text, and full conversation history to local JSON files under temp_sessions with no access control, retention policy, encryption, or consent mechanism shown in this module. In a voice-agent context, those fields can contain sensitive personal or business data, so local compromise, shared-host access, backups, or accidental exposure could leak private transcripts.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The code automatically stores raw conversation text plus metadata such as session_id, emotion_tag, dialect_tag, and created_by into a persistent local database without any consent, minimization, or retention controls. In an agent context, this can capture sensitive personal, account, or support data and leave it exposed to other local users, backups, or later compromise of the host.

VirusTotal

VirusTotal findings are pending for this skill version.

View on VirusTotal

Static analysis

Detected: suspicious.insecure_tls_verification

HTTPS certificate verification is disabled.

Warn
Code
suspicious.insecure_tls_verification
Location
scripts/emotion_ticket_bridge.py:273