Back to skill

Security audit

Alibaba Cloud AI Audio ASR

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly coherent for cloud audio transcription, but its async helper follows an unvalidated result URL and can read stored credentials and persist sensitive transcript data.

Review before installing if you handle sensitive audio or run on a network with private services. Use only with audio you are allowed to send to Alibaba Cloud, keep outputs in a controlled directory, clean up transcripts when no longer needed, and prefer a version that allowlists provider result URLs before using async --wait mode.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/transcribe_audio.py:221
Finding

Unvalidated Transcription Result URL Enables Server-Side Request Forgery

Content
View full analysis

Vulnerability Details

File Location: scripts/transcribe_audio.py:221-223 and scripts/transcribe_audio.py:336-339
Vulnerability Type: Server-Side Request Forgery through an untrusted API response URL
Risk Level: Medium

Vulnerable code:

python
def _fetch_json_url(url: str) -> dict[str, Any]:
    try:
        with urllib.request.urlopen(url, timeout=180) as resp:
            raw = resp.read().decode("utf-8")
    except urllib.error.HTTPError as exc:
        detail = exc.read().decode("utf-8", errors="ignore")
        raise RuntimeError(f"Transcription URL HTTP {exc.code}: {detail}") from exc
    except urllib.error.URLError as exc:
        raise RuntimeError(f"Transcription URL request failed: {exc}") from exc

    try:
        return json.loads(raw)
    except json.JSONDecodeError as exc:
        raise RuntimeError(f"Invalid transcription JSON: {raw[:500]}") from exc
python
if async_mode and status.upper() == "SUCCEEDED":
    transcription_url = (((final_resp.get("output") or {}).get("result") or {}).get("transcription_url") or "")
    if isinstance(transcription_url, str) and transcription_url:
        transcription_json = _fetch_json_url(transcription_url)
        final_resp["transcription_result"] = transcription_json

Technical Analysis

The asynchronous task response supplies transcription_url, which is passed directly to urllib.request.urlopen. The implementation does not constrain the URL scheme or destination, validate the resolved IP address, restrict redirects, or allowlist expected Alibaba Cloud result-storage domains.

Consequently, any party capable of influencing the task response—such as a compromised upstream service, intercepted response path, or malicious proxy—could direct the process to make a request to an attacker-selected destination. Potential destinations include loopback interfaces, private network services, link-local cloud metadat ...[truncated 2441 chars]

Remediation
View remediation

Remediation Suggestions

  1. Require https and reject URLs containing user information, unexpected ports, fragments, or malformed hostnames.
  2. Allowlist the exact Alibaba Cloud or OSS domains documented for transcription-result delivery. Use strict hostname-boundary comparisons rather than substring matching.
  3. Resolve the hostname and reject every address in loopback, private, link-local, multicast, unspecified, reserved, and other non-public ranges for both IPv4 and IPv6.
  4. Disable automatic redirects or validate the scheme, hostname, port, and resolved addresses at every redirect hop.
  5. Mitigate DNS rebinding by connecting only to a validated resolved address while preserving correct TLS hostname verification.
  6. Set a substantially shorter connection/read timeout and enforce a maximum response size before parsing JSON.
  7. Validate the response content type and expected transcription-result schema.
  8. Prefer authenticated result retrieval through a fixed provider API when available rather than following a URL supplied in response data.
  9. Store output files with restrictive permissions when transcripts may contain sensitive speech or internal response data.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (12)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/transcribe_audio.py (reported line 53)May include surrounding context.

python
def _load_env() -> None:
    _load_dotenv(Path.cwd() / ".env")
    repo_root = _find_repo_root(Path(__file__).resolve())
    if repo_root:
        _load_dotenv(repo_root / ".env")

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/transcribe_audio.py (reported line 56)May include surrounding context.

python
def _load_env() -> None:
    _load_dotenv(Path.cwd() / ".env")
    repo_root = _find_repo_root(Path(__file__).resolve())
    if repo_root:
        _load_dotenv(repo_root / ".env")

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/transcribe_audio.py (reported line 306)May include surrounding context.

python
api_key = os.getenv("DASHSCOPE_API_KEY")
    if not api_key:
        print(
            "Error: DASHSCOPE_API_KEY is not set. Configure it via env/.env or ~/.alibabacloud/credentials.",
            file=sys.stderr,
        )
        sys.exit(1)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill documents capabilities that access environment secrets, read local files, write transcripts/evidence, and make outbound network requests, but it does not declare any explicit tool scope or permissions boundary. In an agent setting, this weakens least-privilege controls and can allow unintended use of sensitive files, API keys, or network egress beyond what a user expects.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
82% confidence
Finding

The validation and output guidance create persistent local artifacts under output/aliyun-qwen-asr/, and the skill further instructs storing transcripts and API responses there. Persistence of transcripts, raw responses, and logs can leak sensitive speech content or tokens to later sessions, other users, or backup systems if not handled carefully.

Content

Scanner excerpt · SKILL.md (reported line 14)May include surrounding context.

Validation

bash
mkdir -p output/aliyun-qwen-asr
python -m py_compile skills/ai/audio/aliyun-qwen-asr/scripts/transcribe_audio.py && echo "py_compile_ok" > output/aliyun-qwen-asr/validate.txt

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill encourages uploading audio to a third-party cloud ASR service and storing resulting transcripts locally, but it does not prominently warn users about data egress and persistence. This can expose sensitive spoken content, identifiers, or regulated data when users assume processing is local or ephemeral.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

The documented curl command sends user audio references and authentication credentials to an external service endpoint, which is a real data egress behavior. In the context of an ASR skill this is expected, but it remains security-relevant because sensitive audio content may be transmitted off-system to a third party.

Content

Scanner excerpt · SKILL.md (reported line 74)May include surrounding context.

Sync transcription (OpenAI-compatible protocol):

bash
curl -sS --location 'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions' \
  --header "Authorization: Bearer $DASHSCOPE_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code sends either a local audio file encoded as a data URI or a user-supplied audio URL to DashScope over HTTPS, but there is no confirmation prompt and no visible user-facing warning in the CLI help or runtime output about uploading audio to a third-party service. Because audio may contain sensitive personal or organizational information, this network transmission should be explicitly disclosed to the user.

Content

No source excerpt is available for this finding.

Tainted flow: 'output_path' from os.getenv (line 346, credential/environment) → pathlib.Path.write_text (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/transcribe_audio.py (reported line 356)May include surrounding context.

python
)
    )
    output_path.parent.mkdir(parents=True, exist_ok=True)
    output_path.write_text(json.dumps(normalized, ensure_ascii=False, indent=2), encoding="utf-8")

    if args.print_response:
        print(json.dumps(normalized, ensure_ascii=True))

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The workflow says to confirm whether an operation is read-only or mutating and to run a minimal read-only query first, but the rest of the skill only documents ASR submission endpoints and local output writing. There is no read-only connectivity query described in this skill, and async transcription explicitly creates remote tasks, so the workflow guidance does not match the actual documented behavior.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The manifest describes a skill for transcribing recorded audio with Qwen ASR models and documenting request/response fields, but it does not mention credential discovery from .env files or ~/.alibabacloud/credentials. While useful for implementation, this is an additional local-secret access capability beyond the stated user-facing purpose.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The program automatically loads secrets from .env files and from ~/.alibabacloud/credentials, but the CLI interface and examples do not warn the user that credential material will be accessed from local configuration sources. This is a sensitive operation under the rule because it accesses stored credentials without any explicit notice.

Content

No source excerpt is available for this finding.