Back to skill

Security audit

Generate Protoss-style (StarCraft) voice effects using SoX and FFmpeg.

Security checks for vulnerabilities and agentic risk

Overview

This audio effect skill matches its stated purpose, but needs Review because its file handling can silently delete temporary artifacts and can overwrite predictable temporary paths in shared directories.

Review this before installing if you process audio in shared folders or care about retaining raw recordings. Prefer using it only in a private working directory, check for existing '_psionic' outputs or hidden temporary files with the same base name, and avoid letting the agent silently delete any user-provided recording.

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
protoss_fx.py:49
Finding

Predictable Temporary Files Allow Symlink-Based File Overwrite

Content
View full analysis

Vulnerability Details

File Location: protoss_fx.py, lines 49-53, with unsafe file writes at lines 59-65, 84-85, and 97-104
Vulnerability Type: Predictable and unsafe temporary-file handling
Risk Level: Medium

The application derives all temporary filenames deterministically from the output filename and places them in the output directory:

python
work_dir = os.path.dirname(os.path.abspath(output_path))
filename_base = os.path.splitext(os.path.basename(output_path))[0]

temp_wav_in = os.path.join(work_dir, f".{filename_base}_in.wav")
temp_wav_psi = os.path.join(work_dir, f".{filename_base}_psi.wav")
temp_wav_mix = os.path.join(work_dir, f".{filename_base}_mix.wav")

These predictable paths are subsequently passed to FFmpeg and SoX as output files:

python
subprocess.run(
    ["ffmpeg", "-y", "-i", input_path, "-vn", temp_wav_in],
    check=True,
    stdout=subprocess.DEVNULL,
    stderr=subprocess.DEVNULL
)
python
cmd_psi = [
    "sox",
    temp_wav_in,
    temp_wav_psi,
    "pitch", "-200",
    "reverse",
    "reverb", "80", "50", "100", "100", "0", "0",
    "reverse",
    "vol", "0.5"
]
subprocess.run(cmd_psi, check=True)
python
cmd_mix = [
    "sox",
    temp_wav_psi,
    temp_wav_mix,
    "bass", "+5",
    "highpass", "100",
    "norm", "-1"
]
subprocess.run(cmd_mix, check=True)
python
subprocess.run(
    ["ffmpeg", "-y", "-i", temp_wav_mix, output_path],
    check=True,
    stdout=subprocess.DEVNULL,
    stderr=subprocess.DEVNULL
)

Technical Analysis

Temporary files must be created atomically with unpredictable names inside a directory inaccessible to untrusted users. Here, an attacker can calculate each temporary pathname from the expected output name. The files are created in the output directory, which may be shared or attacker-writable.

If an external utility follows a pre-existing sy ...[truncated 2120 chars]

Remediation
View remediation

Remediation Suggestions

  1. Create a private temporary directory using tempfile.TemporaryDirectory() and place all intermediate files inside it:

    python
    import tempfile
    
    with tempfile.TemporaryDirectory(prefix="protoss_fx_") as temp_dir:
        temp_wav_in = os.path.join(temp_dir, "input.wav")
        temp_wav_psi = os.path.join(temp_dir, "psionic.wav")
        temp_wav_mix = os.path.join(temp_dir, "mix.wav")
        # Run the processing stages inside this block.
    
  2. Ensure the temporary directory has permissions that prevent access by other users. Python's standard temporary-directory API provides unpredictable naming and suitably restrictive creation semantics on supported platforms.

  3. Validate the final output path separately. Reject a pre-existing symbolic link by inspecting it with os.path.lexists() and os.path.islink(), or use platform-appropriate no-follow and exclusive-creation controls.

  4. Avoid unconditional FFmpeg -y behavior for the final destination. Require explicit user authorization before replacing an existing output file.

  5. For stronger output integrity, encode into a safely created temporary file in the destination filesystem and publish it with an atomic rename only after successful processing.

  6. Do not use existence checks followed by ordinary file creation as a security control because that introduces a time-of-check/time-of-use race. Rely on atomic operating-system file-creation primitives instead.

Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill explicitly directs execution of local shell commands (python3, ffmpeg, sox) but does not declare any permissions or allowed-tools scope. That creates an authorization/visibility gap where an agent may invoke shell capabilities without clear policy boundaries, increasing the chance of unintended command execution or unsafe file operations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The instruction to silently clean up raw or intermediate files authorizes deletion without notifying the user, which can remove user-provided recordings or evidence of processing. In a file-processing skill, silent deletion reduces auditability and can cause data loss if temporary-vs-user-owned files are misidentified.

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

python
try:
        # Step 1: Convert input to WAV (canonical format for SoX)
        # Using ffmpeg to handle any weird input formats (mp3, ogg, etc.)
        subprocess.run(
            ["ffmpeg", "-y", "-i", input_path, "-vn", temp_wav_in],
            check=True,
            stdout=subprocess.DEVNULL,

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

python
"reverse",
            "vol", "0.5"
        ]
        subprocess.run(cmd_psi, check=True)

        # Step 3: Mastering ("The Void")
        # We discard the dry vocal completely. Only the processed shadow remains.

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

python
"highpass", "100",
            "norm", "-1"
        ]
        subprocess.run(cmd_mix, check=True)

        # Step 4: Encode final output (MP3/Original format)
        subprocess.run(

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

python
subprocess.run(cmd_mix, check=True)

        # Step 4: Encode final output (MP3/Original format)
        subprocess.run(
            ["ffmpeg", "-y", "-i", temp_wav_mix, output_path],
            check=True,
            stdout=subprocess.DEVNULL,

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

Telling the agent not to narrate the processing step reduces transparency around execution of a transformation script on user files. While not inherently malicious, suppressing disclosure makes it harder for users to understand what commands ran, what files were touched, and whether unexpected behavior occurred.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.