Back to skill

Security audit

VoiceTrust

Security checks for vulnerabilities and agentic risk

Overview

VoiceTrust is not malicious, but it stores biometric voice data and can authorize commands from voice similarity without enough safeguards against spoofing or path misuse.

Install only if you are comfortable with local biometric voiceprint storage and do not use `allow_command` as the only authorization for sensitive actions. Keep the runtime in a private directory, use a simple fixed speaker ID such as `owner`, review downloaded model hashes, and require another confirmation factor for destructive, financial, administrative, or privacy-sensitive commands.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (5)

T09 · Insecure Skill Coding Practices

Error
Location
runtime/src/inference/pipeline.py:302
Finding

Voice commands rely on speaker similarity without replay or spoof resistance

Content
View full analysis
= 1.2 and speaker_match >= 85.0 and confidence >= 85.0 ) if ( failure_reason is None and vad_status == "ok" and (speech_duration >= 3.0 or short_high_confidence_override) and speaker_match >= 78.0 and confidence >= 80.0 and identity_score >= 82.0 ): decision = "allow_command" else: decision = "reject_command" ``` The available anti-spoofing component is disabled: ```python class AntiSpoofingDetector: """Anti-spoofing placeholder.""" def __init__( self, model_name: str = "rawnet2_asvspoof", device: str = "cpu", savedir: Optional[str] = None, ): self.device = device self.savedir = Path(savedir) if savedir else None self.classifier = None print("Anti-spoofing backend disabled: no local model assets configured") ``` ### Technical Analysis The command-gating decision uses speaker-embedding similarity, audio quality, estimated speech duration, and voice-activity metadata. It does not incorporate challenge-response authentication, replay detection, liveness verification, or a functioning synthetic-speech detector. Speaker recognition determines whether audio resembles an enrolled speaker, but it does not establish that the owner is currently present or intentionally issuing the command. A sufficiently clear recording or generated voice clone may therefore meet the same similarity and confidence thresholds as live speech. The short-sample override increases exposure by allowing samples as short as 1.2 seconds when similarity and confidence are high. The Skill documentation instructs downstream integrations to perm ...[truncated 1241 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
runtime/src/data/owner_profiles.py:53
Finding

Unsanitized speaker identifiers allow filesystem path traversal

Content
View full analysis
Path: return self.root / speaker_id def profile_path(self, speaker_id: str) -> Path: return self.speaker_dir(speaker_id) / "profile.json" def aggregate_path(self, speaker_id: str) -> Path: return self.speaker_dir(speaker_id) / "aggregate.npy" def sample_embedding_path(self, speaker_id: str, sample_index: int) -> Path: return self.speaker_dir(speaker_id) / f"sample_{sample_index:03d}.npy" ``` Enrollment then creates directories and files at those paths: ```python def append_sample(self, speaker_id: str, audio_path: str, embedding: np.ndarray) -> OwnerProfile: existing = self.load_profile(speaker_id) sdir = self.speaker_dir(speaker_id) sdir.mkdir(parents=True, exist_ok=True) samples = list(existing.samples) if existing else [] sample_index = len(samples) + 1 emb_path = self.sample_embedding_path(speaker_id, sample_index) np.save(emb_path, embedding) ``` The legacy voiceprint paths and deletion path have the same issue: ```python def save_voiceprint(speaker_id: str, embedding: np.ndarray, voiceprint_dir: Path = VOICEPRINT_DIR): voiceprint_dir.mkdir(parents=True, exist_ok=True) voiceprint_path = voiceprint_dir / f"{speaker_id}.npy" np.save(voiceprint_path, embedding) def load_voiceprint(speaker_id: str, voiceprint_dir: Path = VOICEPRINT_DIR) -> np.ndarray: voiceprint_path = voiceprint_dir / f"{speaker_id}.npy" if voiceprint_path.exists(): return np.load(voiceprint_path) return None ``` ```python if args.clear_speaker: voiceprint_path = VOICEPRINT_DIR / f"{args.clear_speaker}.npy" ...[truncated 2232 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
runtime/src/data/owner_profiles.py:50
Finding

Sensitive biometric profile files are created without enforced restrictive permissions

Content
View full analysis
None: sdir = self.speaker_dir(profile.speaker_id) sdir.mkdir(parents=True, exist_ok=True) self.profile_path(profile.speaker_id).write_text( json.dumps(profile.to_dict(), indent=2, ensure_ascii=False) ) ``` ```python sdir = self.speaker_dir(speaker_id) sdir.mkdir(parents=True, exist_ok=True) samples = list(existing.samples) if existing else [] sample_index = len(samples) + 1 emb_path = self.sample_embedding_path(speaker_id, sample_index) np.save(emb_path, embedding) ... agg_path = self.aggregate_path(speaker_id) np.save(agg_path, aggregate) ``` The legacy voiceprint store behaves similarly: ```python def save_voiceprint(speaker_id: str, embedding: np.ndarray, voiceprint_dir: Path = VOICEPRINT_DIR): """Save voiceprint to disk.""" voiceprint_dir.mkdir(parents=True, exist_ok=True) voiceprint_path = voiceprint_dir / f"{speaker_id}.npy" np.save(voiceprint_path, embedding) ``` ### Technical Analysis Owner embeddings are biometric identifiers, while `profile.json` also records source audio paths and enrollment metadata. The code creates directories and files using default operating-system behavior and the caller's ambient umask. It does not enforce owner-only directory mode `0700` or file mode `0600`. On systems with a permissive umask, shared workspace permissions, or multi-user access, these artifacts may be readable by other local accounts or processes. The quickstart advises operators to protect the directories, but documentation alone does not enforce protection. ### Atta ...[truncated 1021 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
runtime/requirements.txt:4
Finding

Runtime dependencies are installed from mutable, mostly unpinned version ranges

Content
View full analysis
=2.0.0 torchaudio>=2.0.0 numpy>=1.24.0 scipy>=1.10.0 librosa>=0.10.0 soundfile>=0.12.0 speechbrain==1.0.3 pyyaml>=6.0 tqdm>=4.65.0 pytest>=7.4.0 black>=23.0.0 ``` The documented installation command resolves these ranges directly: ```bash uv pip install --python .venv/bin/python -r requirements.txt ``` ### Technical Analysis All listed packages except SpeechBrain use lower-bound-only constraints. A fresh setup can therefore install arbitrary future releases and mutable transitive dependency versions that were not reviewed with the Skill. Python package installation and import can execute package-controlled code. If an upstream package, release process, account, or package index is compromised, the normal bootstrap process may install the affected release. Even without malicious activity, future incompatibilities can alter security-sensitive model loading and audio parsing behavior. Development packages such as `pytest` and `black` are also installed in the runtime environment, unnecessarily increasing the dependency and attack surface. ### Attack Path 1. An operator follows the quickstart and installs `runtime/requirements.txt`. 2. The package resolver selects the latest releases satisfying each `>=` constraint. 3. A compromised, malicious, or newly vulnerable direct or transitive release is selected. 4. Package installation, initialization, or later import executes the affected package code. 5. That code runs with the privileges of the operator performing setup or running VoiceTrust. ### Impact Assessment The potential scope equals the privileges of the Python installation or VoiceTrust runtime process. A compromised dependency could access local files, owner biometric data, network resources, environment variables, ...[truncated 297 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/ensure_models.py:84
Finding

Standard model setup reports success for unverified pre-existing model files

Content
View full analysis
list[str]: return [name for name in REQUIRED_FILES if not (MODEL_DIR / name).exists()] ``` The standard setup path only invokes `download_file()` for missing files: ```python def ensure_models(force: bool = False) -> dict: MODEL_DIR.mkdir(parents=True, exist_ok=True) before_missing = missing_files() actions = [] for name in REQUIRED_FILES: if force or name in before_missing: actions.append(download_file(name, force=force)) after_missing = missing_files() verification_errors = [a for a in actions if a.get("status") == "error"] return { "ok": not after_missing and not verification_errors, "model_dir": str(MODEL_DIR), "canonical_repository": CANONICAL_REPOSITORY, "model_upstream": MODEL_UPSTREAM, "model_mirror_note": MODEL_MIRROR_NOTE, "raw_base_url": RAW_BASE_URL, "missing_before": before_missing, "missing_after": after_missing, "actions": actions, "verification_errors": verification_errors, "files": file_report(), } ``` ### Technical Analysis The downloader contains hard-coded SHA-256 values and correctly verifies newly downloaded files. However, the ordinary `ensure_models()` flow does not verify pre-existing files before deciding success. If every required filename exists, `before_missing` is empty and no `download_file()` call occurs. As a result, `verification_errors` remains empty and `ok` becomes true even when `file_report()` marks one or more files as unverified. This creates inconsistent integrity behavior: downloaded files fail closed on a hash mismatch, while pr ...[truncated 1364 chars]
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (54)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Downloading model files from remote GitHub URLs, creating local asset directories, and performing bootstrap/setup is a major capability escalation relative to a result-interpretation skill. Remote fetch plus local write changes the supply-chain and persistence risk profile substantially, and reviewers may not scrutinize it appropriately if the description implies a passive reference tool.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Downloading model files from remote GitHub URLs, creating local asset directories, and performing bootstrap/setup is a major capability escalation relative to a result-interpretation skill. Remote fetch plus local write changes the supply-chain and persistence risk profile substantially, and reviewers may not scrutinize it appropriately if the description implies a passive reference tool.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Downloading model files from remote GitHub URLs, creating local asset directories, and performing bootstrap/setup is a major capability escalation relative to a result-interpretation skill. Remote fetch plus local write changes the supply-chain and persistence risk profile substantially, and reviewers may not scrutinize it appropriately if the description implies a passive reference tool.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Downloading model files from remote GitHub URLs, creating local asset directories, and performing bootstrap/setup is a major capability escalation relative to a result-interpretation skill. Remote fetch plus local write changes the supply-chain and persistence risk profile substantially, and reviewers may not scrutinize it appropriately if the description implies a passive reference tool.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Downloading model files from remote GitHub URLs, creating local asset directories, and performing bootstrap/setup is a major capability escalation relative to a result-interpretation skill. Remote fetch plus local write changes the supply-chain and persistence risk profile substantially, and reviewers may not scrutinize it appropriately if the description implies a passive reference tool.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Downloading model files from remote GitHub URLs, creating local asset directories, and performing bootstrap/setup is a major capability escalation relative to a result-interpretation skill. Remote fetch plus local write changes the supply-chain and persistence risk profile substantially, and reviewers may not scrutinize it appropriately if the description implies a passive reference tool.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Downloading model files from remote GitHub URLs, creating local asset directories, and performing bootstrap/setup is a major capability escalation relative to a result-interpretation skill. Remote fetch plus local write changes the supply-chain and persistence risk profile substantially, and reviewers may not scrutinize it appropriately if the description implies a passive reference tool.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Downloading model files from remote GitHub URLs, creating local asset directories, and performing bootstrap/setup is a major capability escalation relative to a result-interpretation skill. Remote fetch plus local write changes the supply-chain and persistence risk profile substantially, and reviewers may not scrutinize it appropriately if the description implies a passive reference tool.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Downloading model files from remote GitHub URLs, creating local asset directories, and performing bootstrap/setup is a major capability escalation relative to a result-interpretation skill. Remote fetch plus local write changes the supply-chain and persistence risk profile substantially, and reviewers may not scrutinize it appropriately if the description implies a passive reference tool.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Downloading model files from remote GitHub URLs, creating local asset directories, and performing bootstrap/setup is a major capability escalation relative to a result-interpretation skill. Remote fetch plus local write changes the supply-chain and persistence risk profile substantially, and reviewers may not scrutinize it appropriately if the description implies a passive reference tool.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

This file goes beyond interpreting VoiceTrust results and directly implements speaker enrollment, owner-profile loading, and persistent biometric management. In the stated skill context, that creates an unjustified capability expansion: a result-interpretation component can write and manage voice biometrics, increasing the chance of unauthorized enrollment, profile tampering, or privacy violations if exposed through the agent.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code provides write-capable biometric operations such as enrolling speakers, appending owner samples, and saving voiceprints to disk, despite the skill being described as an interpretation layer. That mismatch is dangerous because an attacker or misconfigured agent could create or overwrite trusted voice identities, effectively changing who is recognized as the owner.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill declares no explicit tool or permission scope despite static analysis indicating capabilities consistent with file I/O, network access, and shell execution. That creates a least-privilege failure: consumers may treat the skill as a harmless reference/interpreter while it can perform materially more powerful actions, increasing the risk of unauthorized asset downloads, local state changes, or command execution.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/quickstart.md (reported line 141)May include surrounding context.

Debian / Ubuntu:

bash
sudo apt update
sudo apt install -y ffmpeg

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/quickstart.md (reported line 142)May include surrounding context.

Debian / Ubuntu:

bash
sudo apt update
sudo apt install -y ffmpeg

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/quickstart.md (reported line 148)May include surrounding context.

Debian / Ubuntu:

bash
sudo apt update
sudo apt install -y ffmpeg

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/quickstart.md (reported line 154)May include surrounding context.

Debian / Ubuntu:

bash
sudo apt update
sudo apt install -y ffmpeg

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest describes a skill for explaining VoiceTrust result fields, trust labels, and command-gating decisions on voice/audio inputs. This file instead implements PyTorch datasets, waveform loading, resampling, padding/cropping, augmentation, speaker-verification training support, and dataloader creation, which are model-training/data-preparation capabilities rather than result interpretation.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The SpeakerDataset class and get_triplet method add speaker-verification training functionality, including triplet sampling for metric learning. That capability is materially different from interpreting VoiceTrust outputs and is not an obvious implementation detail of explaining trust labels or gating decisions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code persists biometric-related profile data and embeddings via write_text and np.save, which affects sensitive user data. The file contains no confirmation prompt, logging, print statement, or comment/docstring warning the user that owner voiceprint artifacts will be stored on disk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

Enrollment persists voice embeddings and related owner profile data to storage without any visible user-consent, retention, or disclosure controls in this file. Because voiceprints are sensitive biometric data, silent persistence raises privacy and compliance risk and can make compromise of stored profiles materially harmful.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The module-level documentation explicitly claims anti-spoofing as a model-backed capability, but the actual implementation is a disabled placeholder. In a voice verification skill, this mismatch can cause downstream systems or developers to assume deepfake detection exists and trust decisions based on synthetic-audio resistance when no such protection is active.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The save_voiceprint method persists a speaker embedding with np.save, which is a file write involving biometric voiceprint data. While the file operation is visible in code, there is no confirmation prompt and no docstring or inline comment warning that sensitive voiceprint data will be stored on disk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The load_voiceprint method reads a stored embedding from disk and re-enrolls it as a speaker identity. This is sensitive biometric data access, but the method has no docstring, comment, or user-facing disclosure describing the operation or its privacy implications.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

AntiSpoofingDetector.analyze() returns neutral probabilities and is_synthetic: False when no classifier is loaded, which can be interpreted as a benign result instead of 'detection unavailable.' In a command-gating or owner-verification context, an attacker using replayed or synthetic audio could bypass controls if the caller relies on this field without separately checking the error condition.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.