Back to skill

Security audit

voice-generate

Security checks for vulnerabilities and agentic risk

Overview

This skill is mostly a coherent writing-voice generator, but it automatically trusts local project files and unvalidated register names in ways that can read or apply unintended Markdown instructions.

Install only if you trust the projects where you use it and understand that it may read local voice-profile files plus `.voice/override.md`. Avoid using it in untrusted repositories, and prefer profiles/registers with strict filename validation and an explicit review of any project override before generation.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • 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
  • 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 (2)

T01 · Skill Instruction Hijacking

Warning
Location
SKILL.md:144
Finding
Untrusted Project Voice Overrides Are Elevated to Authoritative Prompt Instructions<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:49-52, 79-82, 144-147` **Vulnerability Type**: Prompt injection through project-controlled configuration **Risk Level**: Medium ### Vulnerable Code ```markdown Check for per-project override: ```bash if [ -f ".voice/override.md" ]; then # Merge project overrides with profile fi ``` ``` ```markdown You are writing a piece in a specific voice. The voice features below were extracted from the writer's own work. Follow them as concrete instructions, not suggestions. ``` ```markdown If `.voice/override.md` exists in the current project: - Read override content - Merge with profile (overrides take precedence) - Note in output: "Applied project voice override" ``` ### Technical Analysis The skill directs the agent to read `.voice/override.md` from the current project and merge its contents into the active voice profile. It explicitly states that project overrides take precedence and that extracted voice features must be followed as concrete instructions. A project repository is not necessarily trusted. An attacker who controls repository contents can place arbitrary natural-language instructions in `.voice/override.md`. The skill does not require: - A schema limiting the file to recognized style properties. - Validation that the content only describes writing style. - Separation of untrusted configuration data from executable prompt instructions. - Rejection of tool-use, disclosure, safety-override, or unrelated operational directives. - User confirmation before applying the override. Consequently, repository-controlled text can be promoted into authoritative instructions in the generation prompt. This creates an indirect prompt-injection boundary violation. ### Attack Path 1. An attacker adds a malicious `.voice/override.md` to a repository. 2. The victim opens the repository and invokes the voice-generation skill. 3. The skill detects and reads `.voice/override.md`. 4. The skill merges its ...[truncated 1337 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Treat `.voice/override.md` as untrusted repository data rather than free-form instructions. 2. Replace free-form merging with a strict structured format, such as validated YAML or JSON containing an allowlist of style fields. 3. Permit only narrowly scoped properties, such as sentence length, tone, vocabulary preferences, and formatting conventions. 4. Reject content containing tool requests, file operations, network operations, credential requests, instruction-priority claims, or attempts to override safety and user constraints. 5. Delimit override values as quoted data and explicitly instruct the model that they cannot alter the task, security rules, or tool behavior. 6. Ensure system, developer, and current user instructions always take precedence over project files. 7. Display the parsed override to the user and obtain confirmation before applying it in an untrusted project. 8. Log the source and exact validated fields that were applied instead of silently merging the entire file. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
modules/register-selection.md:27
Finding
Unvalidated Register Name Permits Path Traversal Outside the Registers Directory<![CDATA[ ## Vulnerability Details **File Location**: `modules/register-selection.md:27-38` **Vulnerability Type**: Path traversal in register file resolution **Risk Level**: Medium ### Vulnerable Code ```bash PROFILE_DIR="$HOME/.claude/voice-profiles/$PROFILE_NAME" REGISTER_FILE="$PROFILE_DIR/registers/${REGISTER_NAME}.md" if [ ! -f "$REGISTER_FILE" ]; then echo "Register '$REGISTER_NAME' not found. Available:" ls "$PROFILE_DIR/registers/" echo "Using default register." REGISTER_FILE="$PROFILE_DIR/registers/default.md" fi ``` ### Technical Analysis The register name can be selected through an explicit user request, but `REGISTER_NAME` is interpolated directly into a filesystem path without validation or canonical containment checking. Shell quoting prevents whitespace splitting and ordinary shell metacharacter execution, but it does not prevent filesystem traversal. A value containing `../` segments can cause `REGISTER_FILE` to resolve outside `$PROFILE_DIR/registers/`. The `.md` suffix limits the attack to paths that resolve with that suffix, but an attacker can still select another reachable Markdown file. If the selected file exists, the fallback branch is not entered, and the skill may load its contents as active register instructions. For example, a value conceptually equivalent to: ```text ../../../attacker-controlled/instructions ``` would produce a path ending in: ```text $PROFILE_DIR/registers/../../../attacker-controlled/instructions.md ``` The operating system resolves the traversal segments before opening the file. ### Attack Path 1. An attacker supplies an explicit register name containing one or more `../` traversal segments. 2. The skill constructs `REGISTER_FILE` using the unvalidated value. 3. The resulting path resolves outside the intended `registers` directory. 4. The attacker arranges for a Markdown file to exist at the resolved location, or targets an existing readable Markdown file. 5. The file check succeeds, so t ...[truncated 968 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Restrict register names to a conservative filename allowlist, for example: ```bash case "$REGISTER_NAME" in (*[!A-Za-z0-9_-]*|'') echo "Invalid register name" >&2 exit 1 ;; esac ``` 2. Prefer selecting the requested register from an enumerated list of files already discovered inside the register directory rather than constructing a path from raw input. 3. Canonicalize the register directory and candidate path with a platform-appropriate utility such as `realpath`. 4. Verify that the canonical candidate remains a direct child of the canonical register directory before reading it. 5. Reject absolute paths, directory separators, traversal sequences, control characters, and symbolic-link escapes. 6. Consider requiring regular files owned by the expected user and disallowing symbolic links. 7. Apply equivalent validation to `PROFILE_NAME` if it can be influenced by users or repository content. 8. If validation fails, report the invalid name and use the known canonical `default.md` path rather than probing the attacker-supplied path. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (4)

Vague Triggers

Medium
Confidence
97% confidence
Finding
The trigger list includes generic terms like "voice," "generation," and "writing," which are broad enough to cause accidental or overly frequent invocation outside the intended style-transfer use case. In an agent ecosystem, that increases the chance this skill activates on unrelated prompts and then performs profile loading and file reads unexpectedly.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill explicitly instructs reading from $HOME/.claude/voice-profiles and optional project-local .voice/override.md without any user-facing disclosure, confirmation step, or access boundary. That creates a confidentiality risk because the agent may ingest local data the user did not realize would be accessed, including sensitive writing samples or project-specific content.

Behavior Manipulation

Medium
Category
Prompt Injection
Content
Load: `@modules/source-framing`

**Default framing** (always use unless user overrides):

```
Below are my rough notes on this topic. I'm still thinking
Confidence
82% confidence
Finding
The instruction to always frame source material as "rough notes" unless the user overrides changes the semantic presentation of user input in a way that can steer model behavior without transparent consent. This is a form of prompt-level manipulation that may distort user intent, suppress structure the user provided, and produce outputs that misrepresent the source material.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The module explicitly describes 'Auto-Fix Rules (Silent)' that alter generated text before any review or user disclosure. In a voice/style-transfer pipeline, silent rewriting can change meaning, tone, or factual nuance while making the output appear author-authentic, which creates integrity and attribution risks even if the substitutions seem minor.

Static analysis

No suspicious patterns detected.