Back to skill

Security audit

Local speech to text Qwen3-ASR w/ OpenVINO (no API key)

Security checks for vulnerabilities and agentic risk

Overview

This Windows ASR skill has a coherent local transcription purpose, but it should be reviewed because it can automatically install/download code and execute Python from broadly auto-discovered local paths.

Install only if you are comfortable with a Windows skill that creates a persistent local ASR environment, downloads about 2 GB of model data, installs Python packages, and may run setup/download scripts automatically. Prefer running setup manually from a known skill directory, avoid broad auto-discovery, and verify Python/Git installers, dependencies, model files, and any existing *_openvino directory before use.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T07 · Tool Hijacking and Spoofing

Error
Location
acoustic_pipeline.py:59
Finding

Untrusted Runtime Auto-Discovery Can Execute Attacker-Controlled Python Code

Content
View full analysis
Optional[Path]: """Scan all drives for a *_openvino/asr directory.""" import string for drive in string.ascii_uppercase: base_path = Path(f"{drive}:\\") if not base_path.exists(): continue # look for *_openvino/asr under this drive try: for item in base_path.iterdir(): if item.is_dir() and "_openvino" in item.name: asr_candidat ...[truncated 2788 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
setup.py:33
Finding

Dependencies, Existing Repository Contents, and Model Artifacts Lack Reproducible Integrity Controls

Content
View full analysis
=2025.4", "numpy<2.0", "librosa", "transformers", "huggingface_hub", "accelerate", "soundfile", "scipy", "modelscope", ] ``` ```python # Upgrade pip venv_run(["-m", "pip", "install", "--upgrade", "pip", "--quiet"], check=True) missing = [] for pkg in PACKAGES: imp = pkg.split(">=")[0].split("<")[0].replace("-", "_") r = venv_run(["-c", f"import {imp}"], capture_output=True) if r.returncode != 0: missing.append(pkg) if missing: print(f" Installing: {missing}") venv_run(["-m", "pip", "install", "--quiet"] + missing, check=True) ``` ```python repo = asr_dir / "Qwen3-ASR" if repo.exists(): print(f" Repo already exists: {repo} [OK]") else: print(f" Cloning from {QWEN_ASR_REPO}...") subprocess.run(["git", "clone", QWEN_ASR_REPO, str(repo)], check=True) subprocess.run(["git", "-C", str(repo), "checkout", QWEN_ASR_COMMIT], check=True) print(" Cloned [OK]") print(" Installing qwen_asr package...") venv_run(["-m", "pip", "install", "-q", "-e", str(repo)], check=True) ``` ```python MODEL_ID = "snake7gun/Qwen3-ASR-0.6B-fp16-ov" ``` ```python from modelscope import snapshot_download ``` ```python snapshot_download(MODEL_ID, local_dir=str(model_dir)) ``` ### Technical Analysis Most Python dependencies use no exact version, while `openvino` and `numpy` use open version ranges. Installation also upgrades `pip` to whatever version is current at execution time. No lock file or package hashes are used, making installation results mutable and non-reproducible. The Qwen3-ASR repository declares a specific commit for a fresh clone, which is a positive control. However, if the repository directo ...[truncated 2275 chars]
Remediation
View remediation

T03 · Remote Payload Retrieval and Execution

Warning
Location
SKILL.md:195
Finding

Downloaded Python and Git Installers Are Executed Without Explicit Integrity Verification

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (33)

Hidden Instructions

High
Category
Prompt Injection
Confidence
60% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

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

md
---

name: local-qwen3-asr-aipc
description: >

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill can automatically run setup.py and download_model.py, which grants arbitrary code execution and potentially triggers network downloads as part of normal use. In this context, that behavior is more dangerous because it is tied to missing-environment handling rather than a clearly separated installation workflow.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code dynamically imports and executes transcribe.py from a filesystem location that may have been auto-located from scanned drives or state.json. Dynamic import of untrusted local Python files is equivalent to arbitrary code execution and is especially risky here because the source path is not strongly authenticated.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
86% confidence
Finding

The skill instructs the agent to automatically redeploy runtime files and avoid user review, which grants the skill autonomy to change local executable components. Even if intended for maintenance, automatic modification of runtime scripts increases the chance of unreviewed code execution from repository-managed files.

Content

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

md
1. **Windows / PowerShell only.** Never use Linux commands (`ls`, `rm`, `cat`). Never use `&&` or `call`.
2. **Every step reads `state.json` itself** — do not pass paths between steps manually.
3. **Use `VENV_PY` from state.json for inference calls** — never use system python for inference. `check_env.py` and `setup.py` are the only scripts intentionally run with system python (they create or validate the venv, so they must not depend on it). `check_env.py` validates the *venv's* packages, not system Python's — `PACKAGES_MISSING` from check_env.py means the venv is incomplete, not the system installation.
4. `transcribe.py` is automatically deployed to `ASR_DIR` when `setup.py` runs. If it is missing, re-run `setup.py`.
5. **If `transcribe.py` fails at runtime**, do NOT edit it manually. Re-run `setup.py` to redeploy the original from the repository.
6. **Never diagnose "model issues" without running Step 1's check script first.** The model layout may use a `thinker/` subdirectory — the scripts handle this automatically.
7. **Do not generate helper scripts in agent workspace directories.** Use repository-managed `check_env.py` instead.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
96% confidence
Finding

The skill tells the agent to automatically run setup.py up to three times when the environment is missing or incomplete. This is dangerous because setup scripts commonly install packages, clone repositories, and execute arbitrary code, so autonomous retries amplify the likelihood of unintended execution and network activity without user consent.

Content

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

md
IMPORTANT:
* Many networks (corporate / China mainland / campus) require proxy
* Download supports resume — safe to retry after fixing network
* If `STATE=MISSING`, `VENV_PY=BROKEN`, or `PACKAGES_MISSING`: automatically run `setup.py` (up to 3 attempts). Only ask user to run it manually if all 3 attempts fail. `setup.py` is idempotent — it skips any step already completed (venv, packages, repo clone, asr_engine.py, transcribe.py). Re-running a working environment is safe and fast.
* If `MODEL_STATUS=MISSING`: automatically run `download_model.py` (up to 3 attempts). Only ask user to run it manually if all 3 attempts fail or if a single attempt runs longer than 8 minutes without completing (likely a slow connection — download_model.py supports resume so partial progress is not lost). `download_model.py` exits immediately if the model is already complete — re-running the script on an already-downloaded model is safe.
* Always announce what you are doing before each attempt: "⚙️ Automatically setting up the environment (attempt N/3)…"

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
95% confidence
Finding

The skill directs the agent to automatically run download_model.py, including retries, whenever the model is missing. Although framed as recovery logic, this authorizes unattended network downloads and execution of repository code, which can expose the environment to supply-chain risks and unexpected resource consumption.

Content

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

md
* Many networks (corporate / China mainland / campus) require proxy
* Download supports resume — safe to retry after fixing network
* If `STATE=MISSING`, `VENV_PY=BROKEN`, or `PACKAGES_MISSING`: automatically run `setup.py` (up to 3 attempts). Only ask user to run it manually if all 3 attempts fail. `setup.py` is idempotent — it skips any step already completed (venv, packages, repo clone, asr_engine.py, transcribe.py). Re-running a working environment is safe and fast.
* If `MODEL_STATUS=MISSING`: automatically run `download_model.py` (up to 3 attempts). Only ask user to run it manually if all 3 attempts fail or if a single attempt runs longer than 8 minutes without completing (likely a slow connection — download_model.py supports resume so partial progress is not lost). `download_model.py` exits immediately if the model is already complete — re-running the script on an already-downloaded model is safe.
* Always announce what you are doing before each attempt: "⚙️ Automatically setting up the environment (attempt N/3)…"

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
| `'python' is not recognized...` | Python missing; install required (see below) |
| `Python was not found; run without arguments...` | **Windows Store alias** — run `py --version` instead (see below) |

**If output contains "run without arguments to install from the Microsoft Store"**, the Windows Store App Execution Alias is shadowing the real Python. Do NOT ask the user to change settings, and do NOT write helper scripts. Use `where.exe` (native Windows tool, works in both PowerShell and cmd) to find the real Python:

> ⚠️ **Do NOT write any helper .ps1 scripts. Run the command below directly in the terminal.**

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill advertises offline/local inference, but its instructions explicitly direct the agent to fetch and silently install Python and Git from the internet. This creates a supply-chain and unauthorized software installation risk because the agent may perform network downloads and execute installers without explicit user approval, which is more dangerous than a normal one-time dependency notice.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

When auto_bootstrap is enabled, the pipeline executes setup.py and download_model.py, which can modify the local environment and likely perform network activity. Although there are informational prints at execution time, the user-facing help and docstrings do not clearly warn that enabling this option will run installation scripts and download artifacts.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill scans all Windows drives and user-specific directories to locate runtime components, which exceeds the minimum access needed for a single transcription task. That broad host inspection increases exposure to sensitive filesystem metadata and makes it easier to pick up attacker-controlled directories or stale installations.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
95% confidence
Finding

This subprocess call executes local bootstrap scripts (setup.py or download_model.py) from an auto-discovered ASR directory. Because the directory can be selected through broad filesystem discovery rather than a pinned trusted location, the code may execute attacker-planted Python scripts and perform arbitrary local code execution.

Content

Scanner excerpt · acoustic_pipeline.py (reported line 263)May include surrounding context.

python
cmd = [str(Path(sys.executable)), str(script_path)]
        # run in the ASR directory so generated files land in the right place
        result = subprocess.run(
            cmd, 
            capture_output=True, 
            text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · acoustic_pipeline.py (reported line 349)May include surrounding context.

python
'-n',  # do not overwrite
                str(output_wav)
            ]
            result = subprocess.run(cmd, capture_output=True, timeout=300)
            
            if result.returncode == 0 and output_wav.exists():
                print(f"  [OK] Audio extracted: {output_wav.name}")

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
91% confidence
Finding

This subprocess call executes transcribe.py using a Python interpreter and script path discovered from state.json and broad drive scanning. Since both the interpreter path and script path may come from untrusted local filesystem locations, an attacker who can place or alter those files can gain arbitrary code execution when transcription runs.

Content

Scanner excerpt · acoustic_pipeline.py (reported line 437)May include surrounding context.

python
'--audio', str(audio_file),
                    '--language', language
                ]
                result = subprocess.run(
                    cmd,
                    capture_output=True,
                    text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · check_env.py (reported line 68)May include surrounding context.

python
"""Validate the venv in a background thread: Python works + key packages present + native intact."""
    try:
        # 1. check Python itself is executable
        proc = subprocess.run(
            [str(venv_py), "--version"],
            capture_output=True,
            timeout=5,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · check_env.py (reported line 84)May include surrounding context.

python
"print(pathlib.Path(importlib.util.find_spec('openvino').origin).parent) if not missing else None; "
            "sys.exit(len(missing))"
        )
        proc2 = subprocess.run(
            [str(venv_py), "-c", check_script],
            capture_output=True,
            timeout=10,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · download_model.py (reported line 43)May include surrounding context.

python
# This ensures modelscope and all deps are available without a nested subprocess.
if Path(sys.executable).resolve() != venv_py.resolve():
    print(f"[INFO] Switching to venv python: {venv_py}")
    result = subprocess.run([str(venv_py), str(Path(__file__).resolve())])
    sys.exit(result.returncode)

# ─────────────────────────────────────────────────────────────

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
74% confidence
Finding

This call executes a preexisting interpreter found in the shared venv path before the script has established trust in that environment. In a multi-user or attacker-writable filesystem location, a malicious python.exe planted there would run immediately when the script only intends to validate the venv.

Content

Scanner excerpt · setup.py (reported line 80)May include surrounding context.

python
venv_ok = False
if venv_py.exists():
    try:
        r = subprocess.run([str(venv_py), "--version"], capture_output=True, timeout=10)
        if r.returncode == 0:
            print(f"  Existing venv OK: {r.stdout.decode().strip()}")
            venv_ok = True

Tainted flow: 'venv_py' from os.environ.get (line 93, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
83% confidence
Finding

This is the clearest manifestation of the trust issue: the script executes python.exe from an existing shared venv path selected from a location influenced by environment-derived naming. If that filesystem location is attacker-controlled or previously poisoned, setup runs untrusted code before any package or repo verification.

Content

Scanner excerpt · setup.py (reported line 80)May include surrounding context.

python
venv_ok = False
if venv_py.exists():
    try:
        r = subprocess.run([str(venv_py), "--version"], capture_output=True, timeout=10)
        if r.returncode == 0:
            print(f"  Existing venv OK: {r.stdout.decode().strip()}")
            venv_ok = True

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script will delete and recreate an existing virtual environment automatically if it appears broken, without prompting the user or verifying that the target directory is the intended one. In context, the target path is computed outside the skill directory and may point to a shared location, so this can cause unintended data loss or destructive modification of user-managed environments.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · setup.py (reported line 92)May include surrounding context.

python
print("  Existing venv is broken — rebuilding...")
        shutil.rmtree(venv_dir, ignore_errors=True)
    print("  Creating venv...")
    subprocess.run([sys.executable, "-m", "venv", str(venv_dir)], check=True)
    venv_py = venv_dir / "Scripts" / "python.exe"
    r = subprocess.run([str(venv_py), "--version"], capture_output=True)
    print(f"  Venv created: {r.stdout.decode().strip()} [OK]")

Tainted flow: 'venv_dir' from os.environ.get (line 64, credential/environment) → subprocess.run (code execution)

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 · setup.py (reported line 92)May include surrounding context.

python
print("  Existing venv is broken — rebuilding...")
        shutil.rmtree(venv_dir, ignore_errors=True)
    print("  Creating venv...")
    subprocess.run([sys.executable, "-m", "venv", str(venv_dir)], check=True)
    venv_py = venv_dir / "Scripts" / "python.exe"
    r = subprocess.run([str(venv_py), "--version"], capture_output=True)
    print(f"  Venv created: {r.stdout.decode().strip()} [OK]")

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · setup.py (reported line 94)May include surrounding context.

python
print("  Creating venv...")
    subprocess.run([sys.executable, "-m", "venv", str(venv_dir)], check=True)
    venv_py = venv_dir / "Scripts" / "python.exe"
    r = subprocess.run([str(venv_py), "--version"], capture_output=True)
    print(f"  Venv created: {r.stdout.decode().strip()} [OK]")

def venv_run(args, **kw):

Tainted flow: 'venv_py' from os.environ.get (line 93, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
79% confidence
Finding

While this is not shell injection, it is still a trust-boundary issue: the path to venv_py is derived from a shared location influenced by environment state, and the script executes that binary. If an attacker can influence the target directory contents, this becomes arbitrary code execution under the user account.

Content

Scanner excerpt · setup.py (reported line 94)May include surrounding context.

python
print("  Creating venv...")
    subprocess.run([sys.executable, "-m", "venv", str(venv_dir)], check=True)
    venv_py = venv_dir / "Scripts" / "python.exe"
    r = subprocess.run([str(venv_py), "--version"], capture_output=True)
    print(f"  Venv created: {r.stdout.decode().strip()} [OK]")

def venv_run(args, **kw):

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
76% confidence
Finding

The helper executes whatever binary resides at venv_py and is later used to run pip installs and inline Python code. Because the script accepts and reuses an existing venv under a path derived from environment-controlled state, an attacker who can pre-place or replace that interpreter in the target directory could get arbitrary code execution under the user's context.

Content

Scanner excerpt · setup.py (reported line 98)May include surrounding context.

python
print(f"  Venv created: {r.stdout.decode().strip()} [OK]")

def venv_run(args, **kw):
    return subprocess.run([str(venv_py)] + args, **kw)

# ── Upgrade pip ────────────────────────────────────────────
print("\n[2/4] Upgrading pip...")

Tainted flow: 'venv_py' from os.environ.get (line 93, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
84% confidence
Finding

This helper centralizes execution of the interpreter located at venv_py for package installation and verification. Because the interpreter path comes from a location influenced by environment-derived naming and can refer to a preexisting venv, compromise of that path gives repeated arbitrary code execution and package-install side effects.

Content

Scanner excerpt · setup.py (reported line 98)May include surrounding context.

python
print(f"  Venv created: {r.stdout.decode().strip()} [OK]")

def venv_run(args, **kw):
    return subprocess.run([str(venv_py)] + args, **kw)

# ── Upgrade pip ────────────────────────────────────────────
print("\n[2/4] Upgrading pip...")

Static analysis

No suspicious patterns detected.