Back to skill

Security audit

Audio Summary

Security checks for vulnerabilities and agentic risk

Overview

This audio/video summarizer has a clear purpose, but it ships with an exposed API key and unsafe command execution that could let crafted filenames run local commands.

Do not install this version unless you are prepared to review and patch it first. The embedded DashScope key should be revoked and replaced with a user-provided secret, ffmpeg should be called through subprocess with an argument list rather than os.system, temporary files should be unique/private, and the skill should clearly warn users before uploading audio or video-derived content to a third-party ASR provider.

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

T09 · Insecure Skill Coding Practices

Error
Location
audio_summary_skill.py:7
Finding
Hard-Coded DashScope API Credential<![CDATA[ ## Vulnerability Details **File Location**: `audio_summary_skill.py`, lines 7-13 **Vulnerability Type**: Hard-coded secret **Risk Level**: High ### Vulnerable Code ```python API_KEY = 'sk-76735bc919a549a7a643f6b401815840' BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1" client = OpenAI( api_key=API_KEY, base_url=BASE_URL, ) ``` ### Technical Analysis A complete Alibaba Cloud DashScope API key is embedded directly in the source code. Anyone who can read the project files, a distributed skill package, a source archive, or repository history can recover and reuse this credential independently of the skill. Hard-coded credentials cannot be securely rotated per deployment and are likely to leak through version-control history, backups, logs, or copied project artifacts. Removing the key only from the current version would not invalidate copies that have already been exposed. ### Attack Path 1. An attacker obtains read access to the project, its source archive, or repository history. 2. The attacker extracts the API key from line 7. 3. The attacker configures an API client to use the documented DashScope endpoint. 4. Requests are submitted under the identity, quota, and billing scope associated with the exposed key. 5. The attacker continues using the credential until it is revoked or restricted by the provider. ### Impact Assessment Successful exploitation does not directly grant local operating-system privileges. It grants whatever remote API permissions are assigned to the exposed key. Potential consequences include: - Unauthorized use of paid model services. - Consumption or exhaustion of API quotas. - Charges being attributed to the credential owner. - Disruption of legitimate transcription requests. - Access to other API operations if the key has broader permissions than those required by this skill. The precise cloud-side scope depends on the provider configuration and cannot be determined from the reviewed files. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Revoke and rotate the exposed key immediately; changing the source code alone does not invalidate leaked copies. 2. Remove the credential from the source tree and purge it from repository history and distributed artifacts where feasible. 3. Obtain the key at runtime from a protected environment variable or secrets manager: ```python API_KEY = os.environ.get("DASHSCOPE_API_KEY") if not API_KEY: raise RuntimeError("DASHSCOPE_API_KEY is not configured") ``` 4. Grant the replacement key only the minimum API permissions required for transcription. 5. Apply provider-side spending limits, quotas, expiration, source restrictions, and monitoring where supported. 6. Add secret scanning to pre-commit hooks and continuous integration. 7. Avoid logging credentials or including them in documentation and example configuration files. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
audio_summary_skill.py:15
Finding
OS Command Injection Through an Untrusted Media Path<![CDATA[ ## Vulnerability Details **File Location**: `audio_summary_skill.py`, lines 15-20 **Vulnerability Type**: Shell command injection **Risk Level**: Critical ### Vulnerable Code ```python def extract_audio(video_path, audio_path): print(f"正在从视频提取音频并极致压缩: {video_path}") # 压缩为 16k mono mp3, 32k 码率以确保 Base64 编码后不超过 10MB (约支持 10-15 分钟视频) cmd = f'ffmpeg -y -i "{video_path}" -vn -ar 16000 -ac 1 -ab 32k "{audio_path}" -loglevel error' os.system(cmd) return os.path.exists(audio_path) ``` ### Technical Analysis The command-line argument `video_path` originates from `sys.argv[1]` and is interpolated into a command string passed to `os.system`. Because `os.system` invokes a command shell, shell metacharacters contained in a crafted filename can be interpreted as command syntax. Surrounding the value with double quotes is not an adequate defense. A filename containing a double quote can terminate the quoted argument, after which separators and additional commands can be introduced. The preliminary existence check in `run_skill` does not prevent exploitation because operating systems can permit filenames containing shell-significant characters. An attacker can create such a file before invoking the skill. The fixed `audio_path` does not eliminate the vulnerability because exploitation is possible through the user-controlled input path alone. ### Attack Path 1. The attacker creates an input file whose filename contains a quote and shell command separators while retaining a supported video suffix. 2. The attacker invokes the skill with the exact crafted path, allowing the `os.path.exists` check to succeed. 3. `extract_audio` inserts the path into the `cmd` string without shell-safe argument handling. 4. `os.system` passes the constructed string to the platform shell. 5. The shell terminates the intended quoted argument and interprets the injected text as additional commands. 6. Those commands execute with the operating-system identity and pri ...[truncated 952 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Replace shell-string execution with `subprocess.run` using an argument array and with shell processing disabled: ```python import subprocess def extract_audio(video_path, audio_path): command = [ "ffmpeg", "-y", "-i", str(video_path), "-vn", "-ar", "16000", "-ac", "1", "-ab", "32k", str(audio_path), "-loglevel", "error", ] try: subprocess.run(command, check=True, shell=False) except (OSError, subprocess.CalledProcessError): return False return os.path.isfile(audio_path) ``` Additional hardening should include: 1. Resolve and validate the input as a regular file. 2. Restrict accepted file types, while recognizing that extension checks alone do not establish file safety. 3. Avoid executing the skill with administrator or root privileges. 4. Check the `ffmpeg` exit status instead of treating output-file existence as proof of success. 5. Apply execution timeouts and resource limits to reduce denial-of-service risks from malformed media. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
audio_summary_skill.py:70
Finding
Predictable Shared Temporary File Enables Races and Unsafe Overwrites<![CDATA[ ## Vulnerability Details **File Location**: `audio_summary_skill.py`, lines 70 and 89-90 **Vulnerability Type**: Unsafe temporary-file handling **Risk Level**: High ### Vulnerable Code ```python if video_input.lower().endswith(('.mp4', '.mkv', '.mov', '.avi')): audio_tmp = "temp_audio_uri_skill.mp3" if not extract_audio(video_input, audio_tmp): print("音频提取失败。") return else: audio_tmp = video_input ``` ```python # 清理临时文件 if audio_tmp == "temp_audio_uri_skill.mp3" and os.path.exists(audio_tmp): os.remove(audio_tmp) ``` The predictable path is also passed to `ffmpeg` with forced overwrite enabled: ```python cmd = f'ffmpeg -y -i "{video_path}" -vn -ar 16000 -ac 1 -ab 32k "{audio_path}" -loglevel error' ``` ### Technical Analysis Every video-processing invocation uses the same relative temporary filename, `temp_audio_uri_skill.mp3`, in the process working directory. The file is neither created atomically nor placed in a private temporary directory. This creates several hazards: - Concurrent invocations can overwrite, transcribe, or remove each other's temporary audio. - An attacker with write access to the working directory can pre-create the path. - On platforms and filesystem configurations where the output operation follows symbolic links, the combination of a pre-created link and `ffmpeg -y` may cause an accessible target file to be overwritten or truncated. - Cleanup is not placed in a `finally` block, so exceptions can leave potentially sensitive extracted audio behind. - A process may transcribe audio generated by a different invocation, causing cross-request data disclosure. The exact effect of symbolic-link handling depends on the operating system, filesystem, and `ffmpeg` behavior. The concurrency and predictable-name issues are present regardless. ### Attack Path #### Concurrent-run path 1. Two users or processes invoke the skill from the same working directory. 2. Both select `temp_audio_uri_skill.mp3 ...[truncated 1566 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Use a unique, private temporary directory for each invocation and guarantee cleanup with a context manager: ```python import tempfile from pathlib import Path def run_skill(video_input): if not os.path.isfile(video_input): print(f"Input file not found: {video_input}") return if video_input.lower().endswith((".mp4", ".mkv", ".mov", ".avi")): with tempfile.TemporaryDirectory(prefix="audio-summary-") as temp_dir: audio_tmp = Path(temp_dir) / "audio.mp3" if not extract_audio(video_input, audio_tmp): print("Audio extraction failed.") return result = transcribe_with_data_uri(audio_tmp) else: result = transcribe_with_data_uri(video_input) # Save the result after temporary resources have been handled. ``` Additional hardening should include: 1. Ensure temporary directories are created with permissions restricted to the current user. 2. Avoid predictable files in shared or attacker-writable directories. 3. Keep extraction, transcription, and cleanup within `try`/`finally` or managed contexts. 4. Prevent multiple processes from sharing the same temporary path. 5. Validate temporary outputs as regular files and reject symbolic links where applicable. 6. Consider securely deleting extracted audio when required by the application's data-retention policy. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Missing User Warnings

High
Confidence
99% confidence
Finding
A hardcoded API key is embedded directly in the source code, which exposes a live credential to anyone who can view the file, logs, backups, or repository history. An attacker could reuse the key for unauthorized API access, incur charges, access associated resources, or pivot into related service abuse.

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Content
print(f"正在从视频提取音频并极致压缩: {video_path}")
    # 压缩为 16k mono mp3, 32k 码率以确保 Base64 编码后不超过 10MB (约支持 10-15 分钟视频)
    cmd = f'ffmpeg -y -i "{video_path}" -vn -ar 16000 -ac 1 -ab 32k "{audio_path}" -loglevel error'
    os.system(cmd)
    return os.path.exists(audio_path)

def transcribe_with_data_uri(audio_path):
Confidence
96% confidence
Finding
The skill builds a shell command with user-controlled input (`video_path`) and executes it via `os.system`, which invokes a shell. Quoting with double quotes is not sufficient to prevent shell metacharacter expansion such as command substitution, so a crafted filename could trigger arbitrary command execution on the host.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The natural-language instructions throughout the skill file are Chinese-only, which can impose a language constraint on users without opt-in. The file does not state that the skill is intended only for Chinese-speaking users or provide an alternative language option.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill sends user-provided audio/video content to an external ASR provider, but the description does not warn about this data transfer or its privacy implications. Users may unknowingly submit sensitive conversations, meetings, or recordings to a third-party service, creating confidentiality, compliance, and consent risks.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
In this skill context, shell execution is directly tied to processing attacker-influenced media paths, so the command-execution capability is not merely incidental. Because the feature is exposed in a summarization utility, users may supply untrusted filenames or files from shared locations, increasing the chance of command injection or unsafe execution flows.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
The script's user-visible messages and the transcription instruction are written only in Chinese, and the model prompt directs output in that language context without any opt-in or locale selection. This can violate language/locale policy when users are not given a choice.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill base64-encodes local audio and transmits it to a third-party ASR endpoint without explicit user consent, warning, or data-handling notice. This can leak sensitive spoken content, personal data, or confidential business information, especially because summarization tools are often used on meetings or private recordings.

Static analysis

No suspicious patterns detected.