Back to skill

Security audit

realtime-transcription

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to provide the advertised transcription workflow, but it records and stores sensitive audio-derived text while relying on broad permissions and unpinned executable dependencies/model code.

Review before installing. Only use this skill where recording microphone or system audio is appropriate and consented to, avoid sensitive meetings or private media, and expect transcripts plus summaries to be saved locally. Prefer a dedicated virtual environment, pinned dependency versions, and a pinned or verified model that does not require trust_remote_code before running it.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
Findings (5)

T03 · Remote Payload Retrieval and Execution

Error
Location
realtime_asr.py:186
Finding
Unpinned Third-Party Model Code Is Trusted and Executed<![CDATA[ ## Vulnerability Details **File Location**: `realtime_asr.py:186-191`; related download instructions at `README.md:54` and `SKILL.md:52` **Vulnerability Type**: Remote model-supplied code execution through an unsafe trust configuration **Risk Level**: High ### Vulnerable Code ```python with contextlib.redirect_stdout(io.StringIO()): self.asr_model = AutoModel( model=model_path, trust_remote_code=True, device="cpu", disable_update=True, ) ``` The model is acquired using the following documented command: ```bash modelscope download --model gongjy/SenseVoiceSmall --local_dir ./model/SenseVoiceSmall ``` ### Technical Analysis The model is downloaded from a mutable third-party ModelScope repository without an immutable revision, checksum, or signature verification. The application then initializes the model with `trust_remote_code=True`, permitting model-associated custom Python code to execute. The `disable_update=True` setting does not establish the integrity of the initially downloaded model or its accompanying code. It only affects subsequent update behavior. If the model repository, distribution account, download channel, or local model directory is compromised, malicious Python code can execute when the model is loaded. ### Attack Path 1. An attacker compromises or gains control over the referenced ModelScope repository, its account, or the model delivery channel. 2. The attacker publishes a modified model revision containing malicious custom Python code. 3. A user follows the documented download command without pinning or verifying the artifact. 4. The user starts the transcription process. 5. `AutoModel` loads the downloaded model with `trust_remote_code=True`. 6. The malicious model code executes with the permissions and environment of the user running the Skill. A local attacker who can replace files under `./model/SenseVoiceSmall` could exploit the same loading behavior. ### Impact Assessment Su ...[truncated 628 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Set `trust_remote_code=False` and use a model format that does not require execution of repository-provided Python code. 2. Pin the model to a reviewed, immutable revision or content digest. 3. Publish and verify cryptographic hashes or signatures for every model and code artifact. 4. Prefer an official, audited model source and vendor any required custom model code after security review. 5. Store the verified model in a directory that untrusted users and processes cannot modify. 6. Run model loading in a restricted subprocess or container with: - No access to Agent credentials or unrelated user files. - Network access disabled unless strictly necessary. - Read-only model files. - Minimal operating-system permissions. 7. Fail closed when model integrity verification is unavailable or unsuccessful. ]]>

T08 · Insecure Dependencies

Warning
Location
realtime_asr.py:21
Finding
Unpinned Python Dependencies Are Installed into the Active Environment<![CDATA[ ## Vulnerability Details **File Location**: `realtime_asr.py:21-27` and `realtime_asr.py:58-61` **Vulnerability Type**: Unsafe dependency installation and supply-chain exposure **Risk Level**: Medium ### Vulnerable Code ```python REQUIRED_DEPS = { 'sounddevice': 'PyAudio binding for microphone/system audio capture', 'librosa': 'Audio resampling and preprocessing', 'funasr': 'SenseVoice ASR model framework', 'torch': 'PyTorch deep learning runtime', 'numpy': 'Numerical array processing', } ``` ```python result = subprocess.run( [sys.executable, '-m', 'pip', 'install', '--quiet', pkg], capture_output=True, text=True, timeout=300 ) ``` ### Technical Analysis Dependencies are identified only by package name. No reviewed versions, cryptographic hashes, lock file, package-index restriction, or isolated virtual environment is specified. The installer invokes pip through the active Python interpreter, so the selected package releases and their installation logic may execute within the user's current Python environment. Python package installation can execute package build backends and installation hooks. Consequently, compromise of a dependency release, package account, configured package index, or network trust path could result in code execution during installation. Unbounded version selection also creates reproducibility and compatibility risks even without a malicious package. ### Attack Path 1. An attacker compromises one of the named dependency projects or the package index configured for pip. 2. The attacker publishes or serves a malicious package release. 3. The user invokes `python3 realtime_asr.py --install-deps`. 4. The installer requests the dependency by unpinned name. 5. Pip selects and downloads the attacker-controlled release. 6. Malicious build or installation code executes with the permissions of the user. 7. The installed package can execute again when imported by the transcription app ...[truncated 577 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin every dependency to a reviewed version in a lock file. 2. Record and enforce cryptographic hashes, for example with pip's `--require-hashes`. 3. Install dependencies into a dedicated virtual environment rather than the active global or shared interpreter. 4. Configure an explicitly trusted package index and disable unexpected additional indexes. 5. Generate and review a software bill of materials for direct and transitive dependencies. 6. Scan packages for known vulnerabilities and review upgrades before changing locked versions. 7. Prefer prebuilt, verified wheels where practical, and avoid executing source builds from untrusted origins. 8. Separate dependency installation from normal runtime operation and require explicit user approval. ]]>

T01 · Skill Instruction Hijacking

Warning
Location
summary_prompt.py:30
Finding
Audio Transcript Content Can Inject Instructions into the Summarization Prompt<![CDATA[ ## Vulnerability Details **File Location**: `summary_prompt.py:30-43` **Vulnerability Type**: Indirect prompt injection through untrusted transcript content **Risk Level**: Medium ### Vulnerable Code ```python def build_summary_prompt(transcript_text: str, max_chars: int = 4000) -> str: """ Build the summary prompt, truncating the transcript if it exceeds max_chars to avoid overwhelming the LLM context. """ if len(transcript_text) > max_chars: # Keep the beginning and end (most important parts) half = max_chars // 2 truncated = transcript_text[:half] + "\n\n... [truncated] ...\n\n" + transcript_text[-half:] else: truncated = transcript_text return SYSTEM_PROMPT + "\n\n--- Transcript ---\n\n" + truncated ``` ### Technical Analysis The transcript is attacker-influenceable data derived from microphone or system audio. It is appended directly to the instruction prompt as plain text. The prompt does not explicitly state that instructions found inside the transcript are untrusted quoted data and must never be followed. An attacker whose speech is captured can introduce instruction-like content such as requests to ignore previous directions, alter the title, omit facts, or emit crafted Markdown and YAML. Because instructions and transcript data share the same prompt string, the language model may interpret transcript content as higher-level operational instructions instead of content to summarize. The transcript is truncated by retaining its beginning and end. An attacker can improve the likelihood of injection survival by placing malicious instructions near either retained boundary. ### Attack Path 1. An attacker speaks near the microphone or plays audio through the captured system-audio source. 2. The ASR engine converts the spoken instruction into transcript text. 3. `build_summary_prompt` appends that text directly to the summarization prompt. 4. The active LLM interprets the transcript ...[truncated 858 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Use separate system and user message roles where the LLM interface supports them. 2. Add an explicit system-level rule that transcript content is untrusted data and that any instructions contained within it must not be followed. 3. Enclose transcript content in a structured data field, such as a JSON value, instead of concatenating it directly with instructions. 4. Require the model to return a strict structured schema and validate it before use. 5. Enforce title length, character, and line-count restrictions independently of model output. 6. Reject unexpected fields, embedded frontmatter, code fences, links, and control characters where they are unnecessary. 7. Treat summaries as untrusted output when displaying or passing them to downstream tools. 8. Consider a second validation stage that detects instruction-following artifacts or unsupported claims before archival. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
archiver.py:52
Finding
Unescaped LLM and Transcript Content Can Inject YAML and Markdown<![CDATA[ ## Vulnerability Details **File Location**: `archiver.py:52-75` **Vulnerability Type**: Stored YAML frontmatter and Markdown injection **Risk Level**: Medium ### Vulnerable Code ```python content = f"""\ --- title: "{title}" date: {date_str} time: "{time_str} - {end_time_str}" source: {source} duration: {duration_min}m --- ## 摘要 {summary} ## 完整转录 ``` {transcript_text} ``` """ with open(file_path, "w", encoding="utf-8") as f: f.write(content) ``` ### Technical Analysis The generated `title`, `summary`, and transcript are interpolated into a Markdown document without output encoding appropriate to their syntactic contexts. A title containing a quote followed by a newline can terminate the intended YAML scalar and introduce additional frontmatter keys. The summary is inserted as unrestricted Markdown. A transcript containing a sequence of three backticks can terminate the intended code block and inject active Markdown outside the fence. Although `sanitize_filename` is used for the filename, it does not sanitize the original title inserted into frontmatter. It also does not protect the summary or transcript body. Prompt injection through captured audio can therefore be combined with this output-handling flaw to create persistent crafted archive documents. ### Attack Path 1. An attacker causes crafted words or instruction-like content to enter the audio transcript. 2. The transcript influences the LLM-generated title or summary, or directly contains Markdown fence delimiters. 3. `parse_summary_response` accepts the generated title and summary without strict structural validation. 4. `archive` interpolates the values directly into YAML and Markdown. 5. The resulting file contains attacker-controlled frontmatter fields or Markdown outside the intended transcript block. 6. A user or downstream indexing/rendering system opens and processes the crafted archive. ### Impact Assessment The vulnerability can corrupt archive metadata, spoof titles ...[truncated 538 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Generate frontmatter with a safe YAML serializer rather than string interpolation. 2. Restrict titles to one line and reject carriage returns, newlines, control characters, and unexpected syntax. 3. Enforce the documented title length independently of the LLM. 4. Treat summary output as untrusted Markdown and sanitize it according to the capabilities of the eventual renderer. 5. Protect transcript fencing by selecting a fence longer than every backtick run in the transcript, indenting transcript lines, or storing the transcript in a separate plaintext file. 6. Disable raw HTML and unsafe URI schemes in downstream Markdown renderers. 7. Validate the completed frontmatter by parsing it before writing or publishing the archive. 8. Write archive files using restrictive permissions when recordings may contain sensitive information. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
skill.yaml:35
Finding
Stop Command Trusts an Unvalidated Mutable PID File<![CDATA[ ## Vulnerability Details **File Location**: `skill.yaml:35`; the same command is documented at `SKILL.md:96` **Vulnerability Type**: Unsafe process termination through an unvalidated PID file **Risk Level**: Medium ### Vulnerable Code ```yaml stop: "kill $(cat .tmp/asr.pid 2>/dev/null) 2>/dev/null; rm -f .tmp/asr.pid" ``` ### Technical Analysis The stop command reads shell arguments from `.tmp/asr.pid` and passes them directly to `kill`. It does not validate that the file contains exactly one positive decimal process ID, verify ownership of the process, or confirm that the target process is the expected transcription process. Because shell command substitution performs word splitting, a modified PID file can supply multiple arguments or option-like values. For example, a negative process identifier can target a process group, and some platform-specific values may target a broader set of processes. Even a valid positive PID may refer to an unrelated process if the transcription process ended and its PID was subsequently reused. The PID file is created with default permission behavior under a relative runtime directory. The code does not enforce restrictive directory or file permissions or atomic exclusive creation. ### Attack Path 1. A local attacker or another process with write access to the project runtime directory modifies `.tmp/asr.pid`. 2. The attacker writes an unrelated PID, multiple PIDs, or a dangerous option-like or negative value. 3. The user asks the Agent to stop transcription. 4. The configured shell command expands the PID-file contents as arguments to `kill`. 5. `kill` sends a termination signal to processes other than the intended transcription process. 6. The command removes the PID file, reducing evidence and preventing straightforward process-identity verification after the action. A race is also possible if the original process exits and its PID is reused before the stop command runs. ### Impact Assessment An attacker c ...[truncated 447 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the shell command substitution with a dedicated Python stop routine. 2. Accept only a single positive decimal PID and reject zero, negative values, whitespace-separated values, and option-like input. 3. Verify that the process belongs to the current user. 4. Verify process identity through its executable path, command line, or a stronger process handle before sending a signal. 5. Account for PID reuse by recording and checking process start time. 6. Create the runtime directory with restrictive permissions and create the PID file atomically. 7. Use a lock file or operating-system process-management primitive instead of an unauthenticated mutable PID file. 8. Remove the PID file only after process identity has been verified and termination has been handled safely. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (21)

Missing User Warnings

High
Confidence
97% confidence
Finding
The skill records microphone or system audio and archives transcripts, but the description does not provide a clear privacy warning or consent expectations. This increases the risk of users enabling capture without understanding that sensitive speech or system audio may be transcribed, summarized, and stored on disk.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
Press `Ctrl+C` in the terminal, or:
```bash
kill $(cat .tmp/asr.pid 2>/dev/null) 2>/dev/null; rm -f .tmp/asr.pid
```

## After Stopping — Summary & Archive
Confidence
85% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
check_deps: "python3 realtime_asr.py --check-deps"
  start_blackhole: "python3 realtime_asr.py --source blackhole --output .tmp/transcript.txt --state .tmp/asr.pid"
  start_mic: "python3 realtime_asr.py --source mic --output .tmp/transcript.txt --state .tmp/asr.pid"
  stop: "kill $(cat .tmp/asr.pid 2>/dev/null) 2>/dev/null; rm -f .tmp/asr.pid"
  read_transcript: "cat .tmp/transcript.txt 2>/dev/null || echo 'No transcript available'"

paths:
Confidence
85% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Chaining Abuse

High
Category
Tool Misuse
Content
check_deps: "python3 realtime_asr.py --check-deps"
  start_blackhole: "python3 realtime_asr.py --source blackhole --output .tmp/transcript.txt --state .tmp/asr.pid"
  start_mic: "python3 realtime_asr.py --source mic --output .tmp/transcript.txt --state .tmp/asr.pid"
  stop: "kill $(cat .tmp/asr.pid 2>/dev/null) 2>/dev/null; rm -f .tmp/asr.pid"
  read_transcript: "cat .tmp/transcript.txt 2>/dev/null || echo 'No transcript available'"

paths:
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Chaining Abuse

High
Category
Tool Misuse
Content
check_deps: "python3 realtime_asr.py --check-deps"
  start_blackhole: "python3 realtime_asr.py --source blackhole --output .tmp/transcript.txt --state .tmp/asr.pid"
  start_mic: "python3 realtime_asr.py --source mic --output .tmp/transcript.txt --state .tmp/asr.pid"
  stop: "kill $(cat .tmp/asr.pid 2>/dev/null) 2>/dev/null; rm -f .tmp/asr.pid"
  read_transcript: "cat .tmp/transcript.txt 2>/dev/null || echo 'No transcript available'"

paths:
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The README promotes real-time capture, transcription, summarization, and archival of microphone or system audio, but it does not prominently warn users that sensitive conversations, media, notifications, or third-party audio may be recorded and stored on disk. In this context, the omission can lead to unintended collection and retention of personal or confidential data, especially because the skill supports system-wide audio capture and automatic archiving.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The trigger list in metadata includes a bare stop phrase ("停止" / "stop") without requiring that this skill already be active or that the command be scoped to transcription. In an agent environment, generic stop words are common in unrelated conversations and can unintentionally terminate recording or invoke follow-on logic, making accidental activation plausible.

Ssd 3

Medium
Confidence
89% confidence
Finding
The workflow directs the operator to read the full transcript, send it to an LLM for summarization, and archive the complete transcript alongside the summary. This creates a natural-language data leakage path because potentially sensitive spoken content is intentionally propagated to additional processing and persistent storage without minimization.

Vague Triggers

Medium
Confidence
96% confidence
Finding
The trigger table explicitly maps a generic "停止" / "stop" utterance to stopping the process, summary generation, and archival. Because the action chain includes handling sensitive transcript data after stopping, an ambiguous phrase can cause unintended workflow execution and privacy-impacting data processing.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
This tool captures microphone or system audio and writes transcripts to disk, but the usage/help text does not provide a clear privacy warning about recording sensitive conversations, meetings, credentials spoken aloud, or copyrighted media. In this context, the skill's core purpose is surveillance-adjacent data capture, so lack of explicit notice and consent guidance makes the privacy risk more significant.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Content
missing = []
    for pkg in REQUIRED_DEPS:
        try:
            __import__(pkg.replace('-', '_'))
        except ImportError:
            missing.append(pkg)
    return missing
Confidence
75% confidence
Finding
Dynamic __import__() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
A transcription utility does not need to self-install Python packages during normal operation, so this capability is broader than its core purpose. Runtime dependency installation introduces unnecessary supply-chain exposure and can lead to execution of package-provided code if the environment or package source is compromised.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
Several printed messages and CLI outputs are hard-coded in Chinese, while the file otherwise uses English descriptions and does not indicate that the skill is intended only for Chinese-speaking users. This creates a language-policy issue because the skill imposes a locale on users without opt-in or justification.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
print(f"  [{i}/{total}] 安装 {pkg}... {desc}")
        print(f"  ⏳ pip3 install {pkg} ", end="", flush=True)
        try:
            result = subprocess.run(
                [sys.executable, '-m', 'pip', 'install', '--quiet', pkg],
                capture_output=True, text=True, timeout=300
            )
Confidence
87% confidence
Finding
The script can invoke pip at runtime to install packages, which expands its capabilities beyond transcription into code acquisition and execution from package repositories. Even though the package list is hard-coded and subprocess.run is used safely without shell=True, installing and importing packages on demand increases supply-chain risk and can execute untrusted package install-time code.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
Executing a subprocess to perform pip installation grants the skill the ability to modify its runtime environment and fetch executable content, which is an elevated action unrelated to live audio transcription. In context, this is not overtly malicious, but it materially increases the attack surface through package supply-chain abuse.

Unbounded Resource Access

Medium
Category
Excessive Agency
Content
while not self.stop_event.is_set():
                try:
                    chunk = self.audio_queue.get(timeout=0.2)
                except queue.Empty:
                    continue
Confidence
75% confidence
Finding
Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The skill explicitly records audio, summarizes the resulting transcript, and archives it as Markdown, but the manifest does not provide a strong, explicit warning about retention and sensitive data handling. Because the skill can capture microphone or system audio, silent archival materially increases the risk of storing confidential conversations without informed user consent.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The trigger phrase "停止" is extremely broad and can easily appear in ordinary conversation, causing unintended activation of stop behavior. In a transcription skill, accidental stopping can interrupt capture and trigger downstream summarization and archival of sensitive content without a clearly deliberate invocation.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The English trigger phrase "transcribe" is too generic to distinguish from normal user requests about transcription. This can cause the skill to activate unexpectedly and begin recording or handling transcript data when the user may have only been asking a question, increasing privacy and consent risks.

Natural-Language Policy Violations

Low
Confidence
72% confidence
Finding
The README defines activation phrases in both Chinese and English, but it does not explain whether the skill expects one language, supports both equally, or how language selection is determined. This can create a locale-policy ambiguity because language behavior is prescribed without explicit user choice or opt-in.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
The generated Markdown content hard-codes Chinese headings ("摘要" and "完整转录") for every archive file. This imposes a specific language choice on users without any visible option, opt-in, or documented reason that the skill is region-specific.

Static analysis

No suspicious patterns detected.