Back to skill

Security audit

ecommerce-voice-cs

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to do the advertised voice customer-service and sales work, but it under-protects API keys and session state in ways users should review before installing.

Install only if you are comfortable sending generated customer-service or sales text to SenseAudio and retaining audio files locally. Avoid passing real API keys through chat-style payloads until the skill stops writing api_key values to .session_state, fixes session-id collision handling, restricts audio output to a controlled directory, and requires strict explicit confirmation before activating sales mode.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
helper.py:118
Finding

SenseAudio API keys are persisted in plaintext session-state files

Content
View full analysis
None: _state_file(session_id).write_text( json.dumps(state, ensure_ascii=False, indent=2), encoding="utf-8", ) ``` Caller-provided API keys are copied into the state configuration: ```python @staticmethod def _merge_after_sales_payload(cfg: dict[str, Any], payload: dict[str, Any]) -> None: for key in ("api_key", "refund_policy", "shipping_fee_by", "audio_output_path"): value = str(payload.get(key, "")).strip() if value: cfg[key] = value ``` Equivalent storage occurs for sales-mode configuration through `_merge_sales_payload`. Repository artifacts confirm that the resulting state schema contains plaintext credentials: ```json "sales": { "api_key": "k", "voice_id": "male_0018_a" } ``` This pattern appears in: - `.session_state/persist-fix.json:13` - `.session_state/persist-fix-2.json:13` - `.session_state/persist-fix-3.json:13` ### Technical Analysis The Skill accepts a SenseAudio API key through its runtime payload, stores it in the session configuration, and serializes the complete configuration directly to a JSON file. There is no credential redaction, encryption, secret-store integration, expiry mechanism, or explicit owner-only file permission enforcement. Although the API key is legitimately required to authenticate TTS requests, persisting it in session state is not necessary for the declared functionality. The key can remain in process memory or be retrieved from the documented `SENSEAUDIO_API_KEY` environment variable when a request is made. The generated files inherit permissions from the process umask. In a shared or incorrectly configured environment, other local users or processes may therefore be able to read the credential ...[truncated 1231 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
helper.py:101
Finding

Lossy session-ID normalization enables cross-session state collisions

Content
View full analysis
Path: safe = "".join(ch if ch.isalnum() or ch in ("-", "_") else "_" for ch in session_id) return STATE_DIR / f"{safe}.json" def _load_state(session_id: str) -> dict[str, Any]: path = _state_file(session_id) if not path.exists(): return { "mode": "idle", "stage": "idle", "after_sales": dict(AFTER_SALES_DEFAULTS), "sales": dict(SALES_DEFAULTS), } return json.loads(path.read_text(encoding="utf-8")) ``` ### Technical Analysis The mapping from a caller-controlled `session_id` to a state filename is not one-to-one. Every character other than an alphanumeric character, hyphen, or underscore is replaced with an underscore. Different session IDs can consequently resolve to the same file. For example: - `tenant/a` becomes `tenant_a.json` - `tenant:a` becomes `tenant_a.json` - `tenant_a` becomes `tenant_a.json` The state file contains mode configuration, business rules, output paths, product information, and potentially the plaintext API key described in the preceding finding. No authenticated principal, tenant identifier, or original session ID is recorded and checked before the state is loaded or overwritten. This is an access-control problem rather than ordinary filename sanitization. Preventing path traversal is appropriate, but the chosen transformation destroys session uniqueness. ### Attack Path 1. A victim uses a predictable session ID such as `tenant/a`. 2. The Skill normalizes that ID and stores the victim state in `.session_state/tenant_a.json`. 3. An attacker who can choose a session ID submits `tenant_a` or another colliding value such as `tenant:a`. 4. `_state_file` maps the attacker-controlled ID to the victim's state file. 5. `_load_state` loads the ...[truncated 1093 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
helper.py:261
Finding

Sales mode activates on any non-empty reply without explicit confirmation

Content
View full analysis
Remediation
View remediation
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (31)

Tp4

High
Category
MCP Tool Poisoning
Confidence
75% confidence
Finding

The code chunk demonstrates a single skill class named EcommerceVoiceCSSkill and configures it with after-sales/refund-policy parameters. Its example interactions are customer-service oriented ('act as a customer service robot', 'can I return it after opening?') and include TTS-related voice/audio settings. However, the declared description emphasizes two distinct, independently enabled modes, including a separate phone sales mode that generates promotional scripts from product features and discount ranges. That second mode, and any trigger-based switching between modes, is not evidenced in the supplied code chunk. The TTS/audio-output aspects do align, but the overall declared scope is broader than what the provided code actually demonstrates.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The description claims a broader, dual-purpose voice skill with two isolated modes and speech generation features. The code shown only contains an after-sales text response generator based on refund rules. That is partially consistent with one portion of the description, but materially incomplete relative to the declared primary purpose: there is no evidence of the second phone-sales mode or any audio/TTS-related behavior. Because the declared functionality centers on a two-mode voice skill and the actual code only implements one text-only rules component, this is a description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

描述的核心卖点是“双模式电商语音技能”,其中售后客服和电话推销应分别可触发、独立运行。但该代码块只围绕售后客服流程实现:切换到客服模式、收集退款规则配置、生成客服回复、输出合成语音。没有任何电话推销模式的状态、触发词、配置项、产品信息处理或销售话术生成逻辑。因此这不是轻微遗漏,而是对主要能力范围的实质性少实现,描述明显高于代码实际行为。其余如 API key、voice clone、音频落盘等与已实现的客服语音能力一致。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

代码的核心功能只是底层语音合成服务封装,而不是描述中的完整“电商 AI 语音技能”。它确实支持将给定文本合成为音频并保存文件,也支持 API Key/音色句柄等配置校验,因此与“输出 TTS 音频、配置确认、音色选择、语音落盘”部分有一定重合。但声明中的主要业务能力——依据退款规则生成售后客服回复、依据产品信息生成电话推销话术、通过不同触发词切换两套互不干扰模式——在代码中完全没有体现。相反,代码包含了对 SenseAudio 云端 API 的 HTTP 访问,这属于实际资源访问能力,但声明权限为空且未明确说明存在外部网络调用。因此描述与代码实际行为存在实质性不一致。

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The document specifies that generated audio files are retained on disk and that the host should immediately autoplay them, but it does not require user consent, retention limits, or safety checks on playback behavior. In a voice-enabled ecommerce/customer-service skill, this can expose sensitive spoken content to unintended listeners and leave recoverable artifacts on disk, increasing privacy and local data exposure risk.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill declares capabilities that imply environment access, local file read/write, and network use, but it does not define any explicit tool scope or permission boundaries. In a skill host, this can lead to overbroad authority being granted implicitly, making accidental secret exposure, arbitrary file writes, or unintended outbound requests more likely.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The description and trigger design define the skill as a Chinese-language voice/customer-service workflow, but the document does not offer language/locale choice or state that the skill is intentionally limited to a Chinese-region use case. Under the policy, forcing a specific language without opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill explicitly instructs the host to save generated audio to a local path and retain it after playback, but the description does not present this as a user-visible privacy or storage warning. Because generated speech may contain customer-service content, product details, or other sensitive conversation data, silent retention can create local data exposure, accidental disclosure, and accumulation of sensitive files.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The code hard-codes a child-like default voice (child_0001_b) and uses it automatically unless an environment variable overrides it. In a customer-service and telemarketing voice skill, this can mislead recipients, create compliance and consent issues, and increase the risk of socially manipulative or inappropriate synthetic voice use without explicit operator choice or disclosure.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The activation triggers, confirmation phrases, and user-facing responses are fixed in Chinese, and the code even special-cases Chinese confirmation handling. This enforces a specific language/locale without offering the user a choice or documenting an opt-in, which matches the language-policy violation category.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill accepts api_key=... from user messages, merges it into session state, and persists that state to a JSON file under .session_state. This can store sensitive credentials on disk without clear warning, increasing risk of credential disclosure through local file access, backups, logs, or multi-user host environments.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

After-sales mode sends user-provided content and configuration to EcommerceVoiceCSSkill/underlying TTS functionality using an API key, but the helper layer does not clearly disclose that this content is transmitted to an external service. In a customer-service workflow, messages may contain personal order details or other sensitive information, so silent off-box transmission creates a real privacy and data-handling risk.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

In sales mode, any non-empty reply during the confirmation stage is treated as confirmation, despite the surrounding UX text implying an explicit confirmation step. This weakens the safety boundary around mode activation and can cause accidental entry into an active mode that sends content to external TTS services and writes files to disk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Sales mode synthesizes generated content through VoiceCloneService using an external API, but the user is not clearly informed that content is being sent to a third-party service. Although sales text is less sensitive than after-sales support data, undisclosed external transmission still poses privacy, compliance, and trust risks.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The file returns user-facing service replies entirely in Chinese, including the default prompt and all after-sales guidance. This forces a specific language for all users without any opt-in, fallback, or indication that the skill is intentionally limited to a Chinese-speaking locale.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest says the skill supports two separately triggered capabilities: after-sales customer service and telephone sales script generation. In this file, all mode logic, trigger handling, prompts, configuration, and response generation are dedicated to customer service mode, and there is no implementation of a second telemarketing mode, product-pitch generation, or separate trigger phrase for that advertised capability.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The description promises two capabilities that can be independently enabled by different trigger words and kept isolated from each other. The code defines a single TRIGGER_PHRASE and uses a single boolean session flag is_cs_mode, which supports only entering customer service mode and does not implement an independent second mode or isolation between two modes.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trigger phrase is fixed to Chinese and the interaction flow relies on Chinese-only text responses, including the activation instruction at L62. This imposes a specific language/locale without any explicit user choice, which matches the language-policy violation criteria.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill uploads a voice sample and later generates audio files without any consent notice, retention disclosure, or confirmation in this file. In a voice-cloning context, silent collection and processing of biometric-like voice data increases privacy risk and can enable unauthorized cloning or deceptive content generation if the host app does not add its own safeguards.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The skill accepts and stores an API key through set_api_key, and also hydrates api_key from runtime payload at L98-L100, but there is no user-facing notice, logging, or explanatory comment about credential handling. Accessing and using credentials is a covered operation for this rule when no disclosure is present.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill accepts runtime-supplied clone_api_url and api_key values and applies them directly, allowing a caller to redirect voice-sample uploads and synthesis requests to an arbitrary endpoint. In this skill's context, that is more dangerous because it processes sensitive voice data; a malicious or compromised host/plugin could silently exfiltrate credentials and biometric audio to attacker-controlled infrastructure.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · src/ecommerce_voice_cs/voice.py (reported line 17)May include surrounding context.

python
API_DOCS_URL = "https://senseaudio.cn/docs/api-key"
    TTS_DOCS_URL = "https://senseaudio.cn/docs/text_to_speech_api"
    TTS_API_URL = "https://api.senseaudio.cn/v1/t2a_v2"
    MODEL_NAME = "SenseAudio-TTS-1.0"
    SUPPORTED_AUDIO_FORMATS = {"mp3", "wav", "pcm", "flac"}
    SUPPORTED_SAMPLE_RATES = {8000, 16000, 22050, 24000, 32000, 44100}

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The error/help text is presented only in Chinese, and similar Chinese-only messages appear elsewhere in the file. This imposes a specific language on users without an explicit opt-in or documented locale constraint, which matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The manifest describes selecting voices and outputting TTS audio for two business modes, but this class also exposes an upload_sample entry point for voice cloning via a private clone endpoint. Even though the method is not implemented, supporting sample-based cloning is a distinct capability beyond ordinary voice selection and is not clearly within the declared scope.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The code sends TTS content to a third-party remote service, but the skill description does not clearly disclose this external dependency or the associated data flow. In a customer-service/telemarketing context, the text may contain customer messages, refund details, or sales content, creating privacy and compliance risk if operators assume processing is local.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.