Back to skill

Security audit

U2-audio-file-transcriber

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real UniSound audio transcription tool, but it sends recordings and authentication metadata over plaintext HTTP and publishes shared test credentials.

Review before installing or using. Do not use this skill with sensitive, customer, financial, regulated, or production recordings unless the endpoint is changed to an authenticated HTTPS UniSound endpoint and credentials are unique and rotated. Treat the embedded UAT AppKey and Secret as public, use your own credentials, and install dependencies in an isolated environment.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/transcribe.py:28
Finding
Audio and Authentication Metadata Transmitted over Plaintext HTTP<![CDATA[ ## Vulnerability Details **File Location**: `scripts/transcribe.py:28`, `scripts/transcribe.py:123-132`, and `scripts/transcribe.py:153-164` **Vulnerability Type**: Plaintext transmission of sensitive data **Risk Level**: High ### Vulnerable Code ```python base_url: str = "http://af-asr.uat.hivoice.cn" ``` ```python def _build_params(self, **kwargs) -> dict[str, str]: """构建带签名的请求参数""" params = { "appkey": self.config.appkey, "timestamp": str(get_timestamp()), **kwargs, } params["signature"] = self._generate_signature(params) return params ``` ```python def upload_file(self, task_id: str, filepath: str) -> str: """上传音频文件""" url = self.config.urls["upload"] file_md5 = calculate_file_md5(filepath) params = self._build_params( userid=self.config.userid, task_id=task_id, md5=file_md5, audiotype=self.config.audiotype, ) with open(filepath, "rb") as f: response_data = self._request("POST", url, params=params, data=f) ``` The same insecure HTTP endpoint is also documented in `SKILL.md:9`, `SKILL.md:166`, and `SKILL.md:181`. ### Technical Analysis The default UniSound API endpoint uses unencrypted HTTP. The script sends audio content directly in the request body and places authentication and task metadata in query parameters, including the application key, timestamp, signature, user ID, task ID, and file digest. HTTP provides neither transport confidentiality nor endpoint authentication. A network-positioned attacker can inspect traffic, alter uploaded audio, modify API responses, or impersonate the remote service. The request signature does not replace TLS because it does not encrypt the recording or transcript and does not authenticate the server to the client. The `UNISOUND_BASE_URL` environment variable can also select an arbitrary endpoint, and the implementation does not require the configured URL to use HTTPS. ### Attack Path 1. A user ...[truncated 1211 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the default endpoint with an authenticated HTTPS endpoint supplied by UniSound. 2. Reject non-HTTPS base URLs before constructing or sending any request: ```python from urllib.parse import urlparse parsed = urlparse(config.base_url) if parsed.scheme != "https": raise ASRError("UNISOUND_BASE_URL must use HTTPS") ``` 3. Keep TLS certificate verification enabled and do not introduce `verify=False`. 4. Restrict configurable endpoints to an explicit allowlist of approved UniSound hostnames where feasible. 5. Avoid placing sensitive authentication metadata in URLs if the API supports authorization headers or signed request bodies. 6. Rotate credentials after migration because authentication metadata may previously have traversed untrusted networks. 7. Do not process production or sensitive recordings through the UAT HTTP endpoint. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:163
Finding
Shared UniSound API Credentials Embedded in Documentation<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:163-166`, `SKILL.md:208-210`, and `SKILL.md:215-217` **Vulnerability Type**: Hardcoded shared credentials **Risk Level**: Medium ### Vulnerable Code ```yaml AppKey: 681e01d78d8a40e8928bc8268020639b Secret: d7b2980cb61843d69fdab5e99deafcdf UserId: unisound-python-demo Base URL: http://af-asr.uat.hivoice.cn ``` The same values are repeated in configuration examples: ```bash export UNISOUND_APPKEY="681e01d78d8a40e8928bc8268020639b" export UNISOUND_SECRET="d7b2980cb61843d69fdab5e99deafcdf" export UNISOUND_USERID="unisound-python-demo" ``` ```text UNISOUND_APPKEY=681e01d78d8a40e8928bc8268020639b UNISOUND_SECRET=d7b2980cb61843d69fdab5e99deafcdf UNISOUND_USERID=unisound-python-demo ``` ### Technical Analysis The documentation contains a plaintext AppKey and Secret that are presented as UAT test credentials. Labeling credentials as test-only does not protect them from misuse. Anyone who can obtain the Skill package can copy these values and authenticate as the shared test client. Because the credentials are committed in documentation and repeated in ready-to-use examples, they must be treated as publicly disclosed. Shared credentials also prevent reliable attribution of requests to individual users. ### Attack Path 1. An attacker downloads or otherwise obtains the Skill package. 2. The attacker reads the AppKey and Secret from `SKILL.md`. 3. The attacker configures an independent client using the disclosed values. 4. The attacker sends requests to the UniSound UAT API as the shared demo identity. 5. The attacker may consume shared quota, generate unauthorized tasks, interfere with evaluation, or cause abusive activity to be attributed to legitimate users of the same credentials. ### Impact Assessment This issue does not expose local host privileges. It exposes the authority granted to the shared UAT API identity. The exact API privileges and quota available to that identity are not es ...[truncated 280 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Revoke or rotate the disclosed AppKey and Secret. 2. Remove all credential values from the repository and replace them with unambiguous placeholders: ```bash export UNISOUND_APPKEY="<your-app-key>" export UNISOUND_SECRET="<your-secret>" ``` 3. Provision unique, least-privilege, short-lived test credentials for each user or test environment. 4. Deliver credentials through environment configuration or a dedicated secret manager rather than documentation, source code, or committed `.env` files. 5. Add secret scanning to pre-commit hooks and continuous integration. 6. Review UAT service logs for misuse of the disclosed shared identity. 7. If repository history exists, remove the credentials from history where practical, while still rotating them because history rewriting alone does not restore secrecy. ]]>

T08 · Insecure Dependencies

Note
Location
requirements.txt:4
Finding
Non-Reproducible, Open-Ended Dependency Versions<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt:4-7` **Vulnerability Type**: Unpinned third-party dependencies **Risk Level**: Low ### Vulnerable Code ```text # HTTP请求库 requests>=2.31.0 # urllib3 (requests的依赖) urllib3>=2.0.0 ``` The installation instructions at `SKILL.md:50` also reference a nonexistent dependency file: ```bash pip install -r scripts/requirements.txt ``` The actual dependency file is located at the project root as `requirements.txt`. ### Technical Analysis The use of open-ended minimum constraints permits the package resolver to install any future `requests` or `urllib3` version satisfying the lower bound. Consequently, installations performed at different times may execute different, unreviewed dependency code. No malicious package, typosquatted package, or known vulnerable resolved version was identified in the reviewed project. The risk is the lack of reproducibility and review boundaries: a future compromised, incompatible, or vulnerable release could be selected automatically. Explicitly declaring `urllib3` separately from `requests` can also create combinations that were not tested together. The incorrect installation path may cause users to bypass the declared dependency file and install packages manually without consistent constraints. ### Attack Path 1. A user attempts to install project dependencies. 2. After correcting or bypassing the documented invalid path, the package resolver evaluates the open-ended constraints. 3. The resolver selects the newest available versions rather than a reviewed, reproducible set. 4. If a selected future release is compromised or introduces a security regression, its code is installed into the environment. 5. That dependency code executes when the transcription script imports and uses the HTTP libraries. This is a supply-chain exposure scenario; the audit found no evidence that the currently named packages are malicious. ### Impact Assessment The eventual impact de ...[truncated 568 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin dependencies to versions that have been reviewed and tested: ```text requests==<reviewed-version> urllib3==<reviewed-version> ``` 2. Generate and verify cryptographic hashes using a lock or constraints workflow, such as `pip-tools` with hash generation. 3. Test the selected `requests` and `urllib3` versions together before release. 4. Consider declaring only direct dependencies and allowing a generated lock file to record transitive versions. 5. Correct the installation command in `SKILL.md`: ```bash pip install -r requirements.txt ``` 6. Use automated dependency vulnerability scanning and controlled update reviews. 7. Install dependencies inside an isolated virtual environment without elevated operating-system privileges. ]]>
Vulnerability Patterns
  • 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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (14)

Credential Access

High
Category
Privilege Escalation
Content
$env:UNISOUND_USERID="unisound-python-demo"
```

*Using .env file (Recommended):*
```
UNISOUND_APPKEY=681e01d78d8a40e8928bc8268020639b
UNISOUND_SECRET=d7b2980cb61843d69fdab5e99deafcdf
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill documentation indicates capabilities involving environment variables, file output, and network access, but it does not declare an explicit tool scope such as permissions or allowed-tools. This weakens security boundaries because consumers of the skill cannot easily constrain what the skill is expected to access, increasing the chance of overbroad execution in an agent environment.

Context-Inappropriate Capability

Medium
Confidence
98% confidence
Finding
The documentation embeds a concrete AppKey and Secret and repeatedly presents them as usable test credentials. Even if intended for UAT, publishing live-looking secrets in a skill file can enable unauthorized API use, quota abuse, impersonation of the demo account, and normalizes unsafe secret-handling practices for users.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill instructs users to export explicit secrets directly in shell commands and .env examples without prominently warning about exposure through shell history, terminal logging, copied transcripts, or process inspection. In an agent or shared environment, this can lead to accidental credential disclosure beyond the intended user.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The script uploads local audio content to a remote ASR endpoint but provides no explicit privacy or consent warning at the point of use. Because audio may contain sensitive financial or customer-service data, users could unintentionally transmit regulated or confidential information off-host.

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Content
# 2. 上传文件
        print(f"  上传文件...", file=sys.stderr)
        self.upload_file(task_id, filepath)

        # 3. 开始转写
        print(f"  开始转写...", file=sys.stderr)
Confidence
55% confidence
Finding
Data is uploaded to cloud storage (S3 / GCS / Azure Blob). This may be a legitimate backup or exfiltration to an external bucket. Manual review is recommended.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
The file contains natural-language comments only in Chinese (for example, 'ASR语音识别Demo依赖包' and 'HTTP请求库') with no indication that the skill is intentionally region-specific or that another language is supported. This can violate language/locale policy when a skill imposes a language without user opt-in or justification.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# ASR语音识别Demo依赖包

# HTTP请求库
requests>=2.31.0

# urllib3 (requests的依赖)
urllib3>=2.0.0
Confidence
91% confidence
Finding
Using a lower-bound version specifier for requests allows future or environment-dependent versions to be installed, which harms build reproducibility and can unintentionally introduce vulnerable or incompatible releases. In a skill that performs network requests to an external ASR service, dependency drift increases supply-chain risk and makes it hard to verify whether a safe version is actually deployed.

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
85% confidence
Finding
The manifest references requests without pinning a specific release, while the package has multiple known advisories across versions. That does not prove the deployed version is vulnerable, but it does mean the manifest is insufficient to verify safety and could resolve to an affected version in some environments.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0

# urllib3 (requests的依赖)
urllib3>=2.0.0
Confidence
92% confidence
Finding
Using an unpinned urllib3 dependency permits non-deterministic installs and may pull in versions with security regressions or unresolved advisories. Because this skill relies on HTTP communication, weaknesses in the transport library could affect request handling, TLS behavior, redirects, proxies, or decompression handling.

Unverifiable Dependency: urllib3 has 16 known advisory(ies) (CVE-2025-66471 (urllib3 streaming API improperly handles highly compressed data); CVE-2024-37891 (urllib3's Proxy-Authorization request header isn't stripped during cross-origin ); CVE-2026-21441 (Decompression-bomb safeguards bypassed when following HTTP redirects (streaming ) +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
84% confidence
Finding
The manifest lists urllib3 without a pinned version even though multiple advisories exist for different releases. This creates uncertainty about whether deployed environments are exposed and is particularly relevant for a network-facing skill where HTTP client behavior is security-sensitive.

Natural-Language Policy Violations

Low
Confidence
81% confidence
Finding
Multiple docstrings, help text, status messages, and errors are presented in Chinese, and the script does not offer a language selection mechanism. This can violate a language/locale policy when users are not given a choice or clear justification for the forced locale.

Intent-Code Divergence

Low
Confidence
91% confidence
Finding
The inline comment '默认配置 - 直接填入你的凭据' implies credentials are expected to be embedded directly in the default configuration. However, the actual configuration flow in `from_env` loads and prioritizes environment variables, so the documentation of intended configuration behavior is misleading.

Context-Inappropriate Capability

Low
Confidence
78% confidence
Finding
The manifest describes an audio-file transcription skill, but does not mention accessing process environment variables for configuration or secrets. While using API credentials is implementation-relevant, reading ambient environment data is a broader capability than the user-facing purpose of 'transcribe audio files' suggests.

Static analysis

No suspicious patterns detected.