Back to skill

Security audit

asr-skill

Security checks for vulnerabilities and agentic risk

Overview

This transcription skill has a coherent purpose, but its shipped script imports a missing local package through a broad ancestor path and stores task metadata in a weakly scoped persistent file.

Review before installing. The transcription workflow itself is understandable, but this package is not self-contained: it relies on a missing `asr_skill` Python package resolved from a broad ancestor path, and async runs leave task metadata behind. Install only in an isolated environment where the `asr_skill` dependency is pinned and trusted, and avoid using it on sensitive media until task-state storage and cleanup are tightened.

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

Error
Location
scripts/transcribe.py:132
Finding

Dependency Confusion Through an Overly Broad Python Import Path

Content
View full analysis

Vulnerability Details

File Location: scripts/transcribe.py, lines 132-140
Vulnerability Type: Local dependency confusion and Python module path hijacking
Risk Level: High

Vulnerable Code

python
try:
    # Import heavy dependencies here
    current_dir = Path(__file__).resolve().parent
    project_root = current_dir.parent.parent.parent
    if str(project_root) not in sys.path:
        sys.path.insert(0, str(project_root))

    from asr_skill import transcribe
    from asr_skill.core.device import get_device_with_fallback

Technical Analysis

The script calculates project_root by traversing three parent directories from the directory containing the script and then prepends that location to sys.path. Given the reviewed project layout, this resolves outside the Skill package and may resolve to a broadly shared directory such as /tmp.

The reviewed project does not contain the imported asr_skill package. Consequently, the implementation executes whichever package named asr_skill Python finds in the manually trusted ancestor directory. Importing a Python package executes its top-level code, so this behavior provides a direct code-execution primitive if an attacker can place a package in that directory.

The get_device_with_fallback import is also unused, unnecessarily increasing the number of modules whose initialization code is executed.

Attack Path

  1. A local attacker determines the directory produced by current_dir.parent.parent.parent.
  2. The attacker creates an asr_skill package in that directory, including an attacker-controlled __init__.py.
  3. The victim starts either synchronous or asynchronous transcription.
  4. run_worker() inserts the attacker-accessible ancestor directory at the beginning of sys.path.
  5. Python resolves from asr_skill import transcribe to the attacker-controlled package.
  6. The malicious package's top-level code executes with t ...[truncated 608 chars]
Remediation
View remediation

Remediation Suggestions

  1. Bundle the required implementation within the Skill package and use package-relative imports.
  2. Remove the manual insertion of an ancestor directory into sys.path.
  3. If asr_skill is an external dependency, declare it through standard Python packaging with an exact or appropriately constrained version and verified package provenance.
  4. Run the application from an isolated virtual environment whose dependencies are installed from a trusted, pinned lock file.
  5. Verify that the imported package resolves to the expected installation path before executing transcription.
  6. Remove the unused get_device_with_fallback import to reduce unnecessary module execution.
  7. Avoid placing or executing the project under shared writable directories such as /tmp.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/transcribe.py:34
Finding

Unsafe Shared Task-State Storage Allows Metadata Exposure and File Manipulation

Content
View full analysis

Vulnerability Details

File Location: scripts/transcribe.py, lines 34-57
Vulnerability Type: Insecure state-file location, unsafe file creation, and non-atomic concurrent writes
Risk Level: Medium

Vulnerable Code

python
# Determine project root relative to this script
current_dir = Path(__file__).resolve().parent
# Script is at skills/asr/scripts/transcribe.py
# project_root is at ../../../
PROJECT_ROOT = current_dir.parent.parent.parent
TASKS_DIR = PROJECT_ROOT / ".asr_skill"
TASKS_FILE = TASKS_DIR / "tasks.json"

# --- Task Management ---

class TaskManager:
    def __init__(self):
        TASKS_DIR.mkdir(parents=True, exist_ok=True)
        if not TASKS_FILE.exists():
            self._save_tasks({})

    def _load_tasks(self):
        try:
            with open(TASKS_FILE, 'r') as f:
                return json.load(f)
        except (json.JSONDecodeError, FileNotFoundError):
            return {}

    def _save_tasks(self, tasks):
        with open(TASKS_FILE, 'w') as f:
            json.dump(tasks, f, indent=2)

Technical Analysis

Task state is stored three levels above the script instead of in a secure, user-specific application data directory. Under the reviewed temporary installation layout, this calculation can resolve to /tmp, resulting in a path such as /tmp/.asr_skill/tasks.json.

The implementation does not validate directory ownership, reject symbolic links, establish restrictive permissions, lock the state file, or write updates through an atomic replacement operation. The ordinary open(..., 'w') call follows symbolic links and truncates the destination before writing.

The state file records input media paths, output paths, task timestamps, processing status, and exception messages. These values may expose sensitive filenames or operational information. Multiple asynchronous workers also perform unsynchronized read-modify-write operations, all ...[truncated 1762 chars]

Remediation
View remediation

Remediation Suggestions

  1. Store task state in a user-specific application data directory, such as a platform-appropriate directory obtained through platformdirs.
  2. Create the state directory with permissions equivalent to 0700 and the task file with permissions equivalent to 0600.
  3. Verify directory and file ownership before reading or writing state.
  4. Reject symbolic links and other unexpected file types. Where supported, use secure open flags such as O_NOFOLLOW.
  5. Write task data to a securely created temporary file in the same directory, flush and synchronize it, and atomically replace the destination with os.replace().
  6. Use inter-process file locking or a transactional store such as SQLite to protect concurrent read-modify-write operations.
  7. Avoid retaining full media paths and raw exception details unless necessary. Apply retention limits and delete completed task metadata after an appropriate period.
  8. Fail safely if the state directory already exists but has unexpected ownership or permissive access controls.
Vulnerability Patterns
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (6)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill documents and invokes capabilities equivalent to shell execution plus file read/write, but it does not declare any tool scope or permissions boundary. This creates a transparency and governance gap: an agent may execute the skill with broader powers than users or reviewers expect, increasing the risk of unintended file access, overwrites, or command execution through the referenced scripts.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The markdown explicitly says the ASR model is "Chinese optimized," which is a locale/language constraint. Because the skill description otherwise presents the tool as a general ASR transcription skill and does not offer opt-in or clearly document a justified region-specific limitation, this can violate the language/locale policy criterion.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill claims local/private processing, yet it also states that FFmpeg and models are auto-installed or downloaded on first run. That mismatch can expose metadata such as IP address, environment details, and requested artifacts to external services, and it may violate user expectations or policy in restricted environments where 'local' implies no network access.

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 · scripts/transcribe.py (reported line 110)May include surrounding context.

python
"-of", "default=noprint_wrappers=1:nokey=1", 
            str(file_path)
        ]
        result = subprocess.run(cmd, capture_output=True, text=True, check=True)
        return float(result.stdout.strip())
    except (subprocess.CalledProcessError, FileNotFoundError, ValueError):
        pass

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 · scripts/transcribe.py (reported line 275)May include surrounding context.

python
]
        
        # Detach process
        subprocess.Popen(
            cmd,
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL,

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script persists task metadata, including input file paths, timestamps, status, and later output locations, into a project-local JSON file without any disclosure, retention policy, or access control. In an ASR skill, those paths and outputs may reveal sensitive audio/video subjects, filenames, workspace structure, or transcription artifacts, creating a privacy and information exposure risk.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.