Back to skill

Security audit

video-subtitle-skill

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent for subtitle generation, but it should be reviewed because it uploads user media to SenseAudio and gives unsafe API-key handling instructions.

Install only if you are comfortable sending selected audio or video content to SenseAudio for cloud transcription. Avoid confidential or regulated recordings unless that service is approved for your use. Do not run the documented echo command that prints SENSEAUDIO_API_KEY, avoid passing the key with --senseaudio-api-key, and prefer a protected environment or secret store. Review output directories because transcripts, JSON details, subtitles, and burned-in videos may persist sensitive content locally.

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
scripts/video_subtitle.py:590
Finding
SenseAudio API Credential Exposure Through Terminal Output and Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:31`; `scripts/video_subtitle.py:590-615` **Vulnerability Type**: API credential disclosure through logs, shell history, and process metadata **Risk Level**: Medium ### Vulnerable Code In `SKILL.md:31`, the documented API-key check prints the complete credential: ```bash echo "SENSEAUDIO_API_KEY=$SENSEAUDIO_API_KEY" ``` In `scripts/video_subtitle.py:590-615`, the command-line interface accepts the credential as a process argument and passes it into the subtitle-generation workflow: ```python parser.add_argument("--senseaudio-api-key", type=str, default=None, help="SenseAudio API 密钥") args = parser.parse_args() if not os.path.exists(args.input): print(f"错误: 文件不存在: {args.input}") return output_dir = args.output if output_dir is None: output_dir = interactive_select_output_dir( args.input, default_subdir="subtitle_output" ) generate_subtitles( input_path=args.input, output_dir=output_dir, senseaudio_api_key=args.senseaudio_api_key, ``` ### Technical Analysis The documented environment-variable check expands and prints the complete `SENSEAUDIO_API_KEY`. Terminal output may be retained in agent transcripts, CI logs, terminal scrollback, shell-session recordings, or centralized logging systems. This unnecessarily discloses the secret when the task only requires determining whether it is configured. The `--senseaudio-api-key` option creates an additional exposure channel. Secrets supplied as command-line arguments may be saved in shell history and can be visible in process metadata while the program is running. Depending on operating-system configuration, other local users, monitoring agents, diagnostic utilities, or process collectors may be able to inspect these arguments. The API key is subsequently used as a bearer credential for the SenseAudio API. Disclosure therefore permits authentication as the affected SenseAudio account. Altho ...[truncated 1635 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the secret-printing check in `SKILL.md` with a presence-only test: ```bash if [ -n "${SENSEAUDIO_API_KEY:-}" ]; then echo "SENSEAUDIO_API_KEY is configured" else echo "SENSEAUDIO_API_KEY is not configured" fi ``` 2. Remove or deprecate `--senseaudio-api-key`. Prefer retrieving the credential from the environment or a protected configuration or secret-management facility. 3. If interactive credential entry remains supported, use `getpass.getpass()` so the secret is not echoed: ```python from getpass import getpass api_key = getpass( "Enter the SenseAudio API key: " ).strip() ``` 4. Never include the API key in status messages, exceptions, diagnostics, request dumps, or debug logs. If an identifier is needed for troubleshooting, display only a short, non-sensitive fingerprint. 5. Update `README.md`, `SKILL.md`, and `USAGE.md` to warn users not to place credentials directly in command-line arguments. 6. Rotate any API key that has already been printed in logs, included in shell history, or supplied through the command-line option. Remove historical copies from logs and shell history where feasible. 7. Explicitly disclose that audio is uploaded to `https://api.senseaudio.cn` for cloud transcription so users can make an informed decision before sensitive media is transmitted. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (24)

Missing User Warnings

High
Confidence
98% confidence
Finding
The skill description explains subtitle generation but does not clearly warn that audio/video content will be transmitted to the external SenseAudio ASR API. This is a significant privacy and data-governance issue because users may provide sensitive recordings without understanding that their media leaves the local environment for third-party processing.

Tainted flow: 'files' from open (line 105, file read) → requests.post (network output)

High
Category
Data Flow
Content
for retry in range(3):
        try:
            resp = requests.post(ASR_API_URL, headers=headers, files=files,
                                 data=data_tuples, timeout=120)
            if resp.status_code == 429:
                wait = 10 * (retry + 1)
Confidence
98% confidence
Finding
The script uploads user-provided audio content to a third-party cloud ASR service. This is a real data-exfiltration/privacy risk because the content may contain sensitive speech, and the interface does not require explicit informed consent before transmission.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The README advertises automatic transcription, translation, and subtitle generation via SenseAudio ASR but does not clearly disclose that uploaded audio/video content may be sent to an external cloud service. This can mislead users into processing sensitive recordings under the assumption the work is local, creating privacy, confidentiality, and compliance risk for meetings, customer calls, or regulated data.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill instructs the agent to access environment variables, run shell commands, use the network-backed ASR service, and write output files, but it does not declare any tool scope or permissions boundary. This creates an authorization and transparency gap: the agent may perform sensitive operations without explicit limitation or user-visible scoping, increasing the risk of overreach or misuse in environments that rely on manifest-declared permissions.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The burn-in feature creates a new modified video file, but the skill does not clearly warn users that media outputs will be altered and an additional file will be written. This can surprise users, consume storage, and create integrity/confusion issues if they expect read-only analysis rather than generation of modified media artifacts.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The trigger examples include broad, everyday phrasing such as requests to summarize a video, which could invoke the skill in cases where the user did not intend external transcription or file-processing behavior. In this skill's context, accidental invocation is more dangerous because it can cause media to be uploaded to a third-party ASR API and produce new output files without a clear upfront confirmation.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
pip install requests

# 系统依赖
sudo apt install ffmpeg            # 音频提取 & 字幕烧入
sudo apt install fonts-noto-cjk    # 中日韩字幕字体(烧入时需要)

# 配置环境变量(添加到 ~/.bashrc 或 ~/.zshrc)
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
pip install requests

# 系统依赖
sudo apt install ffmpeg            # 音频提取 & 字幕烧入
sudo apt install fonts-noto-cjk    # 中日韩字幕字体(烧入时需要)

# 配置环境变量(添加到 ~/.bashrc 或 ~/.zshrc)
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
pip install requests

# 系统依赖
sudo apt install ffmpeg            # 音频提取 & 字幕烧入
sudo apt install fonts-noto-cjk    # 中日韩字幕字体(烧入时需要)

# 配置环境变量(添加到 ~/.bashrc 或 ~/.zshrc)
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
pip install requests

# 系统依赖
sudo apt install ffmpeg            # 音频提取 & 字幕烧入
sudo apt install fonts-noto-cjk    # 中日韩字幕字体(烧入时需要)

# 配置环境变量(添加到 ~/.bashrc 或 ~/.zshrc)
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The guide instructs users to use a cloud ASR service (SenseAudio API) but does not clearly warn that video/audio content may be uploaded off the local system. This can expose sensitive meetings, interviews, or personal media to a third party without informed consent, especially given the skill’s stated support for meeting transcription and summarization.

External Transmission

Medium
Category
Data Exfiltration
Content
# ============== 配置 ==============
SENSEAUDIO_API_KEY = os.environ.get("SENSEAUDIO_API_KEY", "")
ASR_API_URL = "https://api.senseaudio.cn/v1/audio/transcriptions"
MAX_FILE_SIZE = 10 * 1024 * 1024  # 10MB

# ASR 模型选择
Confidence
95% confidence
Finding
The skill is designed to send audio to an external domain, which is a genuine data-transfer behavior relevant to security review. In this context the transmission is expected for cloud ASR, but it still increases risk because user media leaves the local environment.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
"-vn", "-ac", "1", "-ar", str(sample_rate),
        "-acodec", "pcm_s16le", output_audio,
    ]
    result = subprocess.run(cmd, capture_output=True, text=True)
    if result.returncode != 0:
        raise RuntimeError(f"ffmpeg 提取音频失败:\n{result.stderr}")
    return output_audio
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
"-vn", "-ac", "1", "-ar", str(sample_rate),
        "-acodec", "pcm_s16le", output_audio,
    ]
    result = subprocess.run(cmd, capture_output=True, text=True)
    if result.returncode != 0:
        raise RuntimeError(f"ffmpeg 提取音频失败:\n{result.stderr}")
    return output_audio
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
"-vn", "-ac", "1", "-ar", str(sample_rate),
        "-acodec", "pcm_s16le", output_audio,
    ]
    result = subprocess.run(cmd, capture_output=True, text=True)
    if result.returncode != 0:
        raise RuntimeError(f"ffmpeg 提取音频失败:\n{result.stderr}")
    return output_audio
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Missing User Warnings

Medium
Confidence
99% confidence
Finding
The code transmits full audio content to an external API without an explicit privacy warning or consent step in the user interface. In a media-processing skill, this is dangerous because users may reasonably expect local subtitle generation and may unknowingly upload confidential recordings.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
Enabling sentiment analysis extends processing beyond subtitle generation into behavioral or emotional inference. In the context of a subtitle skill, that is a scope expansion with privacy implications because it derives additional sensitive attributes from speech without being central to the stated task.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
"""查找系统中可用的中文字体"""
    import shutil
    if shutil.which("fc-list"):
        result = subprocess.run(
            ["fc-list", ":lang=zh", "-f", "%{family}\n"],
            capture_output=True, text=True
        )
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
"Source Han Sans SC", "Source Han Serif SC",
    ]
    for fb in fallbacks:
        result = subprocess.run(["fc-match", fb], capture_output=True, text=True)
        if result.returncode == 0 and "NotoSans" in result.stdout or "Wen" in result.stdout:
            return fb
    return "Noto Sans CJK SC"
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
]

    print(f"  烧入字幕: {os.path.basename(video_path)} -> {os.path.basename(output_path)}")
    result = subprocess.run(cmd, capture_output=True, text=True)
    if result.returncode != 0:
        raise RuntimeError(f"ffmpeg 字幕烧入失败:\n{result.stderr}")
    return output_path
Confidence
74% confidence
Finding
Although subprocess.run is used without shell=True, the code builds an ffmpeg subtitles filter string using user-controlled file paths and a discovered font name. ffmpeg filter parsers have their own escaping rules, and incomplete escaping can cause parsing errors or unintended file accesses within ffmpeg, making this riskier than a simple argv-based call.

Natural-Language Policy Violations

Low
Confidence
68% confidence
Finding
The natural-language instructions and trigger wording are entirely in Chinese, and the document does not state that users may interact in another language or choose their preferred locale. This can be interpreted as forcing a specific language without explicit opt-in.

Missing User Warnings

Low
Confidence
89% confidence
Finding
The documentation lists multiple generated artifacts, including transcript files and burned-in videos, but does not clearly warn users that the skill will create new local files and potentially overwrite or proliferate sensitive derivative data. This matters because transcripts and subtitled copies can persist private content in more easily searchable or shareable forms.

Natural-Language Policy Violations

Low
Confidence
87% confidence
Finding
User-visible docstrings, prompts, status messages, and CLI help are all written in Chinese, with no indication that another language is available. This can violate language/locale policy when a skill imposes a single language without offering user choice or documenting a justified locale restriction.

Intent-Code Divergence

Low
Confidence
76% confidence
Finding
The docstring states that the script does not call external LLMs, which conveys a stronger impression of local-only AI processing. In reality, the code transmits audio files to the external SenseAudio API for inference at `https://api.senseaudio.cn`, so the documentation understates external AI service usage in a way that can mislead users about where processing happens.

Static analysis

No suspicious patterns detected.