Back to skill

Security audit

azure-transcription

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent Azure transcription purpose, but its example export code can write transcript files outside the intended output folder and its dependency/credential guidance is under-scoped.

Review before installing. Use only vetted and pinned dependencies, keep Azure credentials scoped to transcription, confirm consent/compliance for audio sent to Azure, choose explicit output directories, and sanitize transcript names before exporting files.

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

T08 · Insecure Dependencies

Warning
Location
SKILL.md:266
Finding

Unpinned Third-Party Dependency Installation

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, line 266
Vulnerability Type: Unpinned and unverified third-party dependency
Risk Level: Medium

Vulnerable Code

bash
# Dependency installation
pip install azure-ai-transcription

The same unpinned installation instruction is repeated in the dependency table at SKILL.md:339:

markdown
| azure-ai-transcription | Python SDK | Required | `pip install azure-ai-transcription` |

Technical Analysis

The Skill instructs the Agent to install azure-ai-transcription without specifying an audited version, verifying package hashes, using a lockfile, or validating the expected publisher and package source. Consequently, the code installed during a Skill invocation may differ from the version evaluated during security review.

Python packages can execute code during installation or when imported. If the referenced package, one of its transitive dependencies, or the configured package repository is compromised, the resulting code would execute with the privileges of the Agent process. The risk is amplified because the Skill subsequently expects Azure credentials to be available through environment variables.

This finding does not establish that the named package is malicious. It identifies an unsafe dependency acquisition process that creates a supply-chain attack opportunity.

Attack Path

  1. An operator or Agent follows the Skill's environment-preparation instructions.
  2. The Agent executes pip install azure-ai-transcription.
  3. pip resolves the latest package and transitive dependencies from its configured package index because no version or integrity hash is specified.
  4. A compromised release, dependency, or package source supplies attacker-controlled package code.
  5. That code executes during installation or when the transcription module is imported.
  6. The malicious code receives the Agent process's filesystem, network, and env ...[truncated 626 chars]
Remediation
View remediation

Remediation Suggestions

  1. Verify that the package name and publisher correspond to the intended official Azure SDK before recommending installation.
  2. Pin the dependency to a specifically audited version, for example through a version-constrained requirements file.
  3. Generate and enforce cryptographic hashes using a hash-locked requirements file and pip install --require-hashes.
  4. Pin and review all transitive dependencies rather than only the direct dependency.
  5. Explicitly use a trusted package index and disable untrusted supplemental indexes to reduce dependency-confusion exposure.
  6. Install the package in an isolated virtual environment or container with minimal filesystem and network permissions.
  7. Avoid exposing production Azure credentials during dependency installation. Provide credentials only to the runtime process after installation and validation.
  8. Add an update-review procedure so dependency upgrades are tested and audited before deployment.

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:165
Finding

Path Traversal Through Unsanitized Transcript Name

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, line 165
Vulnerability Type: Path traversal and arbitrary file overwrite
Risk Level: High

Vulnerable Code

python
def _export_srt(self, result, output_dir):
    path = os.path.join(output_dir, f"{result['name']}.srt")
    with open(path, 'w', encoding='utf-8') as f:
        for i, seg in enumerate(result['segments'], 1):
            start = self._format_time(seg.start_time)
            end = self._format_time(seg.end_time)
            speaker = f"[{seg.speaker}] " if hasattr(seg, 'speaker') else ""
            f.write(f"{i}\n{start} --> {end}\n{speaker}{seg.text}\n\n")

The value used as result['name'] originates from the caller-supplied transcription name:

python
def submit_transcription(self, audio_url, name, locale="zh-CN",
                          diarization=True, callback=None):
    job = self.client.begin_transcription(
        name=name,
        locale=locale,
        content_urls=[audio_url],
        diarization_enabled=diarization
    )

    output = {
        'name': name,
        'status': result.status,
        'transcript': result.transcript,
        'segments': result.segments if hasattr(result, 'segments') else []
    }

Technical Analysis

The export routine incorporates result['name'] directly into a filesystem path without rejecting absolute paths, directory separators, or .. traversal components. os.path.join does not guarantee that the resulting path remains beneath output_dir.

For example, a name such as ../../shared/report produces a path equivalent to:

text
./transcripts/../../shared/report.srt

Filesystem path resolution escapes the intended transcript directory and writes report.srt under the sibling shared location. An absolute name can also cause os.path.join to discard the intended base directory on applicable platforms.

Because the file is o ...[truncated 1731 chars]

Remediation
View remediation

Remediation Suggestions

  1. Treat every transcription name as untrusted input.
  2. Reject names containing absolute paths, path separators, null characters, drive prefixes, or traversal components such as ...
  3. Apply a strict allowlist, such as letters, digits, underscores, and hyphens, and impose a reasonable maximum length.
  4. Resolve both the output directory and candidate destination to canonical paths, then verify containment before opening the file.
  5. Generate server-controlled filenames, such as UUIDs, and store the user-visible transcription name only as metadata.
  6. Use exclusive creation where overwriting is unnecessary, and define an explicit collision-handling policy.
  7. Run exports under a minimally privileged account restricted to the transcript directory.
  8. Apply equivalent validation to every export implementation, including SRT, VTT, and JSON.

A hardened implementation could use:

python
import re
from pathlib import Path

def _export_srt(self, result, output_dir):
    raw_name = str(result["name"])
    if not re.fullmatch(r"[A-Za-z0-9_-]{1,128}", raw_name):
        raise ValueError("Invalid transcript name")

    base = Path(output_dir).resolve()
    base.mkdir(parents=True, exist_ok=True)
    destination = (base / f"{raw_name}.srt").resolve()

    if destination.parent != base:
        raise ValueError("Transcript path escapes output directory")

    with destination.open("x", encoding="utf-8") as output:
        for index, segment in enumerate(result["segments"], 1):
            start = self._format_time(segment.start_time)
            end = self._format_time(segment.end_time)
            speaker = (
                f"[{segment.speaker}] "
                if hasattr(segment, "speaker")
                else ""
            )
            output.write(
                f"{index}\n{start} --> {end}\n"
                f"{speaker}{segment.text}\n\n"
            )
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (8)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill is explicitly designed to send audio to Azure and to export transcripts locally, yet the description does not clearly warn that potentially sensitive voice content will leave the local environment and may be written to disk. In enterprise contexts, meeting recordings and call audio often contain personal, confidential, or regulated data, so insufficient disclosure materially increases privacy and compliance risk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The file contains several natural-language and code examples that default to zh-CN, which can amount to forcing a specific language/locale absent opt-in or justification. Although one later example uses en-US, the skill repeatedly presents Chinese as the default behavior rather than explicitly asking users to choose an appropriate locale.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

Natural-language policy violations can appear in code examples and signatures. Here the example API defaults all transcriptions to Chinese, which may force an unintended locale for users unless they manually override it.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code example establishes Chinese as the default locale for batch processing. Without a documented opt-in or region-specific justification, this conflicts with the policy against forcing a specific language or locale.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The documented request/response schema describes a generic content-processing interface rather than a transcription workflow. In an agent setting, mismatched I/O contracts can cause the calling system to pass the wrong data, mishandle outputs, or route sensitive transcript data into unintended processing paths or storage locations.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation tells users to configure a generic API_KEY environment variable, while the code examples actually require TRANSCRIPTION_ENDPOINT and TRANSCRIPTION_KEY. This mismatch can cause operators to misconfigure credentials, trigger failed executions, or encourage unsafe workarounds such as hardcoding secrets directly into commands or source files.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The manifest description lists '自定义语音模型集成' as a core capability, but the code snippets only show realtime transcription, diarization, batch processing, and export. No code path actually passes a custom model identifier or config into the transcription client, so the documented capability is not reflected in behavior.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The FAQ states that BatchTranscriptionManager can retry failed tasks via retry_failed, but the class shown only appends failures to self.failed and contains no retry_failed method. This is a direct contradiction between documentation and the provided implementation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.