Back to skill

Security audit

meeting-to-text

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches a local meeting transcription purpose, but it can unexpectedly download a remote speaker model and load it unsafely despite claiming to be fully local.

Review before installing. This skill will process local recordings and write transcripts, but despite advertising a fully local workflow it may contact ModelScope to fetch a speaker model and then load that checkpoint in a way that can execute unsafe serialized content if the model source or cache is compromised. Prefer a version that vendors or preinstalls verified model files, disables runtime downloads, and uses safer checkpoint loading.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Findings (1)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/meeting_to_text.py:175
Finding

Remote Model Download Followed by Unsafe PyTorch Deserialization

Content
View full analysis
Path: target_dir = THREE_D_SPEAKER_CACHE / SPEAKER_MODEL_ID if (target_dir / "configuration.json").exists(): return target_dir THREE_D_SPEAKER_CACHE.mkdir(parents=True, exist_ok=True) from modelscope.hub.snapshot_download import snapshot_download downloaded = snapshot_download( SPEAKER_MODEL_ID, revision=SPEAKER_MODEL_REVISION, cache_dir=str(THREE_D_SPEAKER_CACHE), ) return Path(downloaded) ``` The downloaded checkpoint is subsequently loaded as follows: ```python model_dir = ensure_speaker_model_cached() checkpoint_path = model_dir / SPEAKER_MODEL_CKPT if not checkpoint_path.exists(): raise DiarizationError(f"Missing speaker model checkpoint: {checkpoint_path}") config = Config( { "feature_extractor": { "obj": "speakerlab.process.processor.FBank", "args": { "n_mels": 80, "sample_rate": SAMPLE_RATE, "mean_nor": True, }, }, "embedding_model": { "obj": "speakerlab.models.campplus.DTDNN.CAMPPlus", "args": { "feat_dim": 80, "embedding_size": 192, }, }, } ) feature_extractor = build("feature_extractor", config) embedding_model = build("embedding_model", config) state_dict = torch.load(str(checkpoint_path), map_location="cpu") embedding_model.load_state_dict(state_dict) embedding_model.eval() ``` ### Technical Analysis When the speaker model is not already cac ...[truncated 2893 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (14)

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
80% confidence
Finding

Skill instructs the agent to omit warnings, disclaimers, or ethical commentary. Stripping safety caveats hides risk from the user and is a common jailbreak preamble.

Content

Scanner excerpt · SKILL.md (reported line 49)May include surrounding context.

md
Always treat the last non-empty stdout line as the JSON result object.

Interpret results this way:
- Exit code `0` with `status: success`: transcript file was created with no warnings.
- Exit code `0` with `status: warning`: transcript file was created, but you must report the warnings and any skipped segments.
- Non-zero exit code or `status: error`: do not claim success; surface the warning list and the intended output path.

Hidden Instructions

High
Category
Prompt Injection
Confidence
60% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · references/runtime_paths.md (reported line 1)May include surrounding context.

md
# Troubleshooting

## Validation Errors

Hidden Instructions

High
Category
Prompt Injection
Confidence
60% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · references/troubleshooting.md (reported line 1)May include surrounding context.

md
# Troubleshooting

## Validation Errors

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill is described as fully local, but it silently downloads a speaker model at runtime when the cache is missing. This creates an undisclosed network egress path, may transmit metadata to a third-party service, and expands the trust boundary to remote content that can influence later model loading behavior.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

For a local transcription skill, runtime network download capability is unnecessary and dangerous because it permits external dependency retrieval during execution. In this context, that is more serious than usual: the code handles local meeting recordings, which may be sensitive, so unexpected online behavior undermines user expectations and increases supply-chain and privacy risk.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill instructs the agent to read local path references, invoke a Python interpreter, and write transcript output, but it declares no explicit tool/permission scope. That creates an authorization ambiguity where a host agent may execute shell and file operations more broadly than intended, increasing the chance of unsafe local file access or command execution through user-controlled paths.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The description says the skill should use default speaker labels like 说话人1, 说话人2 and treats related Chinese phrases as triggers. This imposes a specific language/locale choice in user-facing output without offering an alternative or opt-in, which violates the language/locale policy criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The behavior guarantee states the script will write timestamps and 说话人N, making the output language fixed to Chinese. There is no documented user choice or justification for this locale-specific constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The eval content requires output using Chinese text such as '带说话人标签', '说话人1', and Chinese warning wording, which implies a fixed locale/language expectation. In a JSON eval/config file, there is no accompanying justification or user opt-in showing that Chinese-only output is intentional or region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

This prompt specifies Chinese-language behavior for an English-source MP4 ('en_source.mp4') but provides no documented opt-in or rationale for forcing that locale. That creates a natural-language policy concern because the skill behavior appears constrained to a specific language without user choice.

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 · scripts/meeting_to_text.py (reported line 150)May include surrounding context.

python
"pcm_s16le",
        str(output_wav_path),
    ]
    completed = subprocess.run(command, capture_output=True, text=True, encoding="utf-8", errors="replace")
    if completed.returncode != 0 or not output_wav_path.exists():
        message = completed.stderr.strip() or completed.stdout.strip() or "ffmpeg failed to normalize media"
        raise MediaError(message)

Tainted flow: 'command' from os.getenv (line 133, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
87% confidence
Finding

The executable path comes from MEETING_TO_TEXT_FFMPEG, an environment variable, and is then executed directly via subprocess.run(). While this is not shell injection, it is still arbitrary program execution if an attacker can influence the environment or deployment configuration, causing the skill to run a malicious binary instead of ffmpeg.

Content

Scanner excerpt · scripts/meeting_to_text.py (reported line 150)May include surrounding context.

python
"pcm_s16le",
        str(output_wav_path),
    ]
    completed = subprocess.run(command, capture_output=True, text=True, encoding="utf-8", errors="replace")
    if completed.returncode != 0 or not output_wav_path.exists():
        message = completed.stderr.strip() or completed.stdout.strip() or "ffmpeg failed to normalize media"
        raise MediaError(message)

Insecure deserialization: torch.load() without weights_only=True

Medium
Category
Dangerous Code Execution
Confidence
97% confidence
Finding

torch.load() can deserialize pickle-based model files and may execute attacker-controlled code during loading. Because the checkpoint path is influenced by cache contents and can also be redirected via environment-controlled model locations, a malicious checkpoint could yield arbitrary code execution under the skill's privileges.

Content

Scanner excerpt · scripts/meeting_to_text.py (reported line 223)May include surrounding context.

python
feature_extractor = build("feature_extractor", config)
    embedding_model = build("embedding_model", config)
    state_dict = torch.load(str(checkpoint_path), map_location="cpu")
    embedding_model.load_state_dict(state_dict)
    embedding_model.eval()
    return feature_extractor, embedding_model, circle_pad

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This code forces transcript speaker labels to use the Chinese string "说话人" regardless of the user's preferred language or locale. The file contains no user option, configuration, or documented justification for restricting output labels to Chinese, which creates a natural-language locale policy violation.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/meeting_to_text.py:225