Back to skill

Security audit

AssemblyAI Transcriber

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real AssemblyAI transcription skill, but it uploads audio to a cloud service and has under-scoped API key lookup behavior users should review.

Review this skill before installing if you may transcribe confidential, regulated, or third-party audio. Expect selected audio to be sent to AssemblyAI, prefer an environment variable or a protected secret store over plaintext config files, and be aware that the current script may choose a local config-file key before the environment variable.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/transcribe.py:15
Finding
Undocumented Ancestor Credential File Access Violates Least Privilege## Vulnerability Details **File Location**: `scripts/transcribe.py`, lines 15–19 and 26–30 **Vulnerability Type**: Undocumented credential discovery outside the intended configuration scope **Risk Level**: Medium ### Vulnerable Code ```python CONFIG_PATHS = [ Path.home() / ".assemblyai_config.json", Path.cwd() / ".assemblyai_config.json", Path(__file__).parent.parent.parent.parent / ".assemblyai_config.json", ] ``` ```python def load_api_key(): """Load API key from config file.""" for config_path in CONFIG_PATHS: if config_path.exists(): with open(config_path) as f: config = json.load(f) return config.get("api_key") ``` ### Technical Analysis The script searches for an AssemblyAI API key in three locations. The home-directory and current-working-directory paths correspond to documented configuration behavior. However, the third path is derived by traversing four parent directories from the script. In the audited project layout, `scripts/transcribe.py` is located under the project artifact directory, and this traversal resolves to `/.assemblyai_config.json`. Reading a configuration file from the filesystem root is undocumented and unnecessary for the declared transcription functionality. The candidate paths are evaluated before the `ASSEMBLYAI_API_KEY` environment variable. Consequently, any readable configuration file found at one of these locations silently overrides the caller's environment credential. The code also performs no file ownership, permission, regular-file, or symlink validation. This behavior crosses the expected configuration boundary and can cause transcription requests and audio uploads to use a credential belonging to another user, deployment, or administrative context. ### Attack Path 1. An attacker, administrator, image builder, or unrelated application creates a readable `/.assemblyai_config.json` containin ...[truncated 1636 chars]
Remediation
## Remediation Suggestions 1. Remove the ancestor-derived configuration path: ```python CONFIG_PATHS = [ Path.home() / ".assemblyai_config.json", Path.cwd() / ".assemblyai_config.json", ] ``` 2. Prefer the explicitly supplied environment variable over configuration-file discovery: ```python def load_api_key(): api_key = os.environ.get("ASSEMBLYAI_API_KEY") if api_key: return api_key for config_path in CONFIG_PATHS: if config_path.is_file(): with config_path.open(encoding="utf-8") as f: config = json.load(f) api_key = config.get("api_key") if api_key: return api_key raise ValueError("No AssemblyAI API key found") ``` 3. Permit configuration files only at clearly documented, intentional locations. If workspace configuration is supported, resolve it against a trusted workspace root rather than the process's arbitrary current directory. 4. On platforms that expose suitable metadata, verify that credential files: - Are regular files rather than device nodes or directories. - Are owned by the expected user. - Are not writable by group or other users. - Do not unexpectedly resolve through symbolic links. 5. Emit a safe diagnostic identifying which configuration source was selected without printing the credential. 6. Document credential precedence and the fact that selected audio is transmitted to AssemblyAI before processing.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (8)

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The README encourages users to transcribe local audio files and Telegram voice messages via AssemblyAI but does not clearly disclose that the audio content will be transmitted to a third-party cloud service. This can cause users to unknowingly send sensitive conversations, personal data, or regulated content off-device, creating privacy, compliance, and consent risks.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill advertises capabilities that require environment access and outbound network use, but it does not explicitly declare any tool scope such as permissions or allowed-tools. This weakens least-privilege controls and makes it harder for users or an agent platform to understand and constrain what the skill can access before execution.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The description says the skill transcribes audio but does not clearly warn that the audio will be uploaded to a third-party service, AssemblyAI. This creates a privacy and data-handling risk because users may provide sensitive meetings, interviews, or voice messages without understanding that the content leaves the local environment.

Session Persistence

Medium
Category
Rogue Agent
Content
## Setup

1. Create AssemblyAI account: https://www.assemblyai.com/
2. Get API key (free tier: 100 min/month)
3. Set environment variable:
Confidence
90% confidence
Finding
The setup instructions encourage storing the API key in a persistent config file under the user's home directory as an alternative to an environment variable. Persistent plaintext credential storage increases the chance of accidental disclosure through backups, misconfigured permissions, or other local file access by tools or users.

External Transmission

Medium
Category
Data Exfiltration
Content
Path(__file__).parent.parent.parent.parent / ".assemblyai_config.json",
]

BASE_URL = "https://api.assemblyai.com/v2"


def load_api_key():
Confidence
91% confidence
Finding
The skill is explicitly designed to send audio and transcript requests to an external API endpoint, which constitutes third-party data transmission. In a transcription skill handling meetings, interviews, and voice messages, that transmission can carry sensitive speech content off-device, making the external transfer security-relevant even if it is core functionality.

Session Persistence

Medium
Category
Rogue Agent
Content
return os.environ["ASSEMBLYAI_API_KEY"]
    
    raise ValueError(
        "No API key found. Create ~/.assemblyai_config.json with: "
        '{"api_key": "YOUR_KEY"}'
    )
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The script uploads local audio files and submits remote audio URLs to AssemblyAI, but it provides no explicit consent prompt, privacy notice, or warning that potentially sensitive recordings will be transmitted to a third-party processor. In the context of meetings, interviews, and voice messages, this can expose personal, confidential, or regulated data without informed user awareness.

Natural-Language Policy Violations

Low
Confidence
96% confidence
Finding
The transcript formatter emits German labels such as "Transkript", "Sprache", and "Dauer" regardless of user preference. This is a natural-language locale constraint that is neither optional nor justified as region-specific behavior.

Static analysis

No suspicious patterns detected.