Back to skill

Security audit

Listenhub

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it claims, but its image-generation setup can make persistent shell configuration changes and run privileged package installs with too little user control.

Review this before installing. It is not clearly malicious, but you should only use it if you are comfortable sending prompts, text, URLs, and reference images to external services. Avoid sensitive content. Do not let the image script auto-install packages or auto-write secrets into your shell startup files; set dependencies and LISTENHUB_API_KEY yourself in a safer location if possible.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate-image.sh:345
Finding
Persistent Shell Command Injection Through Unsafe Configuration Serialization<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate-image.sh:345-393` **Vulnerability Type**: Persistent shell command injection and plaintext credential storage **Risk Level**: High ### Vulnerable Code ```bash # Configure API Key if [ -z "${LISTENHUB_API_KEY:-}" ]; then echo "1. API Key" >&2 echo " Visit https://listenhub.ai/settings/api-keys" >&2 echo " (Requires subscription)" >&2 echo "" >&2 echo -n " Please paste your API key: " >&2 read -r api_key if [ -z "$api_key" ]; then echo "Error: API key cannot be empty" >&2 exit 1 fi # Check if config already exists (avoid duplicate append) if ! grep -q "^export LISTENHUB_API_KEY=" "$shell_rc" 2>/dev/null; then echo "export LISTENHUB_API_KEY=\"$api_key\"" >> "$shell_rc" else # If exists, replace sed_inplace "$shell_rc" "s|^export LISTENHUB_API_KEY=.*|export LISTENHUB_API_KEY=\"$api_key\"|" fi export LISTENHUB_API_KEY="$api_key" echo "" >&2 fi # Configure output path if [ -z "${LISTENHUB_OUTPUT_DIR:-}" ]; then echo "2. Output path" >&2 echo -n " Image save location (default: ~/Downloads): " >&2 read -r output_dir # Default to ~/Downloads if [ -z "$output_dir" ]; then output_dir="$HOME/Downloads" fi # Expand ~ symbol output_dir="${output_dir/#\~/$HOME}" # Create directory if not exists mkdir -p "$output_dir" # Check if config already exists (avoid duplicate append) if ! grep -q "^export LISTENHUB_OUTPUT_DIR=" "$shell_rc" 2>/dev/null; then echo "export LISTENHUB_OUTPUT_DIR=\"$output_dir\"" >> "$shell_rc" else sed_inplace "$shell_rc" "s|^export LISTENHUB_OUTPUT_DIR=.*|export LISTENHUB_OUTPUT_DIR=\"$output_dir\"|" fi export LISTENHUB_OUTPUT_DIR="$output_dir" echo "" >&2 fi ``` ### Technical Analysis The script reads an API key and output directory from standard input and interpolates those values directly into a shell startup file such as `.zshrc`, `.bashrc`, or `.profile`. Wrapping a valu ...[truncated 2484 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not store API keys in shell startup files. Use an operating-system credential store, such as macOS Keychain, Secret Service, or an appropriately secured application-specific configuration file. 2. If a local configuration file is used: - Create it with an owner-only mode such as `0600`. - Verify ownership before reading or modifying it. - Store data in a non-executable format such as JSON. 3. Validate API keys against the exact provider-defined format and length. Reject quotes, newlines, carriage returns, NUL bytes, and unexpected control characters. 4. Canonicalize and validate output directories separately. Do not serialize them as executable shell source. 5. If shell assignment persistence is unavoidable, use a robust shell serializer such as `printf '%q'` rather than manual quoting. 6. Do not place untrusted values directly in `sed` expressions. Prefer reconstructing a configuration file through a safe parser and atomic replacement. 7. Write updates to a securely created temporary file, set restrictive permissions, and atomically rename it into place. 8. Avoid automatically modifying `.zshrc`, `.bashrc`, `.bash_profile`, or `.profile`; instead, print an explicit opt-in setup command after safely escaping its value. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/generate-image.sh:248
Finding
Automatic Privileged Package Installation Without Explicit Approval<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate-image.sh:248-320` **Vulnerability Type**: Excessive privilege use and unprompted system modification **Risk Level**: Medium ### Vulnerable Code ```bash check_dependencies() { local missing_deps=() local install_cmd="" # Check jq if ! command -v jq &>/dev/null; then missing_deps+=("jq") fi # Check curl if ! find_curl &>/dev/null; then missing_deps+=("curl") fi # If missing dependencies, auto-install if [ ${#missing_deps[@]} -gt 0 ]; then echo "→ Missing required tools: ${missing_deps[*]}" >&2 echo " Auto-installing..." >&2 echo "" >&2 case "$PLATFORM" in macos) install_cmd="brew install ${missing_deps[*]}" if ! command -v brew &>/dev/null; then echo "Error: Homebrew not detected" >&2 echo " Please install Homebrew first: https://brew.sh" >&2 echo " Or install manually: ${missing_deps[*]}" >&2 exit 1 fi ;; linux) # Detect Linux distribution if command -v apt-get &>/dev/null; then install_cmd="sudo apt-get update && sudo apt-get install -y ${missing_deps[*]}" elif command -v yum &>/dev/null; then install_cmd="sudo yum install -y ${missing_deps[*]}" elif command -v dnf &>/dev/null; then install_cmd="sudo dnf install -y ${missing_deps[*]}" elif command -v pacman &>/dev/null; then install_cmd="sudo pacman -S --noconfirm ${missing_deps[*]}" else echo "Error: No supported package manager detected" >&2 echo " Please install manually: ${missing_deps[*]}" >&2 exit 1 fi ;; windows) if command -v choco &>/dev/null; then install_cmd="choco install -y ${missing_deps[*]}" elif command -v scoop &>/dev/null; then install_cmd="scoop install ${missing_deps[*]}" else echo "Error: Choco ...[truncated 3047 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace automatic installation with a dependency check that exits safely and displays platform-specific installation instructions. 2. If installation assistance is retained, display the exact command and require explicit, affirmative user confirmation before execution. 3. Never invoke `sudo` automatically as part of ordinary image generation. 4. Remove `eval`. Execute fixed commands directly or use Bash arrays so arguments cannot be reinterpreted as shell syntax. 5. Separate setup from generation by providing a dedicated, explicitly invoked installation command or setup script. 6. Document all system modifications and external package sources before asking the user to proceed. 7. Prefer using already available system tools or a controlled application environment rather than modifying global host packages. ]]>
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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (47)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
This finding points to undeclared reads of local shell configuration files to obtain API keys and outbound network requests to GitHub for version checks. Those behaviors are security-relevant because they touch sensitive local files and expand the network trust boundary beyond the primary service, yet are not clearly reflected in the high-level purpose statement.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding
This finding points to undeclared reads of local shell configuration files to obtain API keys and outbound network requests to GitHub for version checks. Those behaviors are security-relevant because they touch sensitive local files and expand the network trust boundary beyond the primary service, yet are not clearly reflected in the high-level purpose statement.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
This finding points to undeclared reads of local shell configuration files to obtain API keys and outbound network requests to GitHub for version checks. Those behaviors are security-relevant because they touch sensitive local files and expand the network trust boundary beyond the primary service, yet are not clearly reflected in the high-level purpose statement.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding
This finding points to undeclared reads of local shell configuration files to obtain API keys and outbound network requests to GitHub for version checks. Those behaviors are security-relevant because they touch sensitive local files and expand the network trust boundary beyond the primary service, yet are not clearly reflected in the high-level purpose statement.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
This finding points to undeclared reads of local shell configuration files to obtain API keys and outbound network requests to GitHub for version checks. Those behaviors are security-relevant because they touch sensitive local files and expand the network trust boundary beyond the primary service, yet are not clearly reflected in the high-level purpose statement.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
This finding points to undeclared reads of local shell configuration files to obtain API keys and outbound network requests to GitHub for version checks. Those behaviors are security-relevant because they touch sensitive local files and expand the network trust boundary beyond the primary service, yet are not clearly reflected in the high-level purpose statement.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
This finding points to undeclared reads of local shell configuration files to obtain API keys and outbound network requests to GitHub for version checks. Those behaviors are security-relevant because they touch sensitive local files and expand the network trust boundary beyond the primary service, yet are not clearly reflected in the high-level purpose statement.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
This finding points to undeclared reads of local shell configuration files to obtain API keys and outbound network requests to GitHub for version checks. Those behaviors are security-relevant because they touch sensitive local files and expand the network trust boundary beyond the primary service, yet are not clearly reflected in the high-level purpose statement.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This finding points to undeclared reads of local shell configuration files to obtain API keys and outbound network requests to GitHub for version checks. Those behaviors are security-relevant because they touch sensitive local files and expand the network trust boundary beyond the primary service, yet are not clearly reflected in the high-level purpose statement.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
This finding points to undeclared reads of local shell configuration files to obtain API keys and outbound network requests to GitHub for version checks. Those behaviors are security-relevant because they touch sensitive local files and expand the network trust boundary beyond the primary service, yet are not clearly reflected in the high-level purpose statement.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
The script parses user shell startup files to load environment variables, accessing persistent user configuration unrelated to generating an image. This broadens data access beyond the stated purpose and sets up later persistence behavior against sensitive files such as .zshrc and .bashrc.

Context-Inappropriate Capability

High
Confidence
96% confidence
Finding
The script automatically installs missing packages by constructing and executing platform-specific package manager commands, including sudo on Linux and noninteractive flags on pacman. For a media-generation skill, modifying system packages is unnecessary and expands the blast radius from image generation to privileged system changes, which could be abused or surprise users.

Chaining Abuse

High
Category
Tool Misuse
Content
linux)
        # Detect Linux distribution
        if command -v apt-get &>/dev/null; then
          install_cmd="sudo apt-get update && sudo apt-get install -y ${missing_deps[*]}"
        elif command -v yum &>/dev/null; then
          install_cmd="sudo yum install -y ${missing_deps[*]}"
        elif command -v dnf &>/dev/null; then
Confidence
91% confidence
Finding
Chaining sudo apt-get update && sudo apt-get install creates a multi-step privileged workflow executed as one automated action. This compounds risk by broadening changes made to the system and reducing opportunities for the user to inspect or abort before installation proceeds.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
elif command -v dnf &>/dev/null; then
          install_cmd="sudo dnf install -y ${missing_deps[*]}"
        elif command -v pacman &>/dev/null; then
          install_cmd="sudo pacman -S --noconfirm ${missing_deps[*]}"
        else
          echo "Error: No supported package manager detected" >&2
          echo "  Please install manually: ${missing_deps[*]}" >&2
Confidence
94% confidence
Finding
The --noconfirm parameter suppresses user review for pacman operations, which is a dangerous use of a powerful tool option in this context. It facilitates silent system changes and undermines informed consent for actions outside the skill's advertised scope.

Credential Access

High
Category
Privilege Escalation
Content
Error: LISTENHUB_API_KEY not set

Setup:
  1. Get API key from https://listenhub.ai/settings/api-keys
  2. Add to ~/.zshrc or ~/.bashrc:
     export LISTENHUB_API_KEY="lh_sk_..."
  3. Run: source ~/.zshrc
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding
The skill declares broad shell and network-driven behavior but does not define an explicit tool scope such as allowed-tools or permissions. In agent environments, that increases the chance the skill can invoke more capabilities than reviewers or orchestrators expect, especially given its instructions to run shell scripts, read shell rc files, and contact external services.

Vague Triggers

Medium
Confidence
93% confidence
Finding
The trigger phrases are broad enough that ordinary requests like 'read this aloud' or 'generate an image' could invoke the skill in contexts where the user did not intend external processing. Because the skill sends content and URLs to remote services and may touch local configuration, accidental invocation can cause unintentional data disclosure or unwanted side effects.

Vague Triggers

Medium
Confidence
88% confidence
Finding
The mode detection relies on ambiguous everyday keywords and then proceeds automatically in several cases, including selecting speakers and transmitting content to backend services. In a skill with shell and network access, weak intent classification increases the chance of unintended external submission of user text or URLs.

Context-Inappropriate Capability

Medium
Confidence
97% confidence
Finding
The skill instructs the agent to upload local reference images to unrelated third-party image hosts such as imgbb, imgur, or postimages. That creates a clear data exfiltration path: local user files are sent to external services outside the primary vendor boundary, potentially exposing sensitive images, metadata, or proprietary material.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
- The user provides only a short topic or phrase (e.g., "a cat"), AND
- The user has not explicitly stated they want verbatim generation

In this case, ask whether the user would like help enriching the prompt. Do not optimize without confirmation.

**When to never modify**:
- The user pastes a long, structured, or detailed prompt — treat them as experienced
Confidence
75% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The script takes arbitrary user-supplied content and transmits it to an external ListenHub API without any explicit notice, confirmation, or indication that the provided text will leave the local environment. In a skill that may be used with pasted documents, articles, or sensitive internal text, this creates a real privacy and data-handling risk through unintended exfiltration to a third-party service.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
This shell script sends the assembled request body to an external API endpoint, and that body can include the user's query plus optional source URLs and source text. Although the script usage explains functionality, it does not clearly warn the user that supplied content will be transmitted over the network.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The script packages user-supplied query text plus optional source URLs and source text, then sends them to an external ListenHub API via api_post without any explicit notice, confirmation, or minimization step. In a skill that accepts arbitrary article text and prompts, this can cause users to unknowingly transmit sensitive or proprietary content to a third party, creating a real privacy and data-handling risk even though the transfer appears functionally intended.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The script transmits user-supplied content directly to the external ListenHub API via `api_post "speech" "$BODY"` after only validating JSON structure, with no explicit notice, confirmation, or opt-in about network transmission. This can expose sensitive text, proprietary material, or personal data if a user assumes the tool operates locally, especially because the skill invites arbitrary text, article content, and other user-provided material for audio generation.

External Transmission

Medium
Category
Data Exfiltration
Content
fi

# Configuration
API_ENDPOINT="https://api.labnana.com/openapi/v1/images/generation"
AGENT_SKILLS_CLIENT_ID="PJBkELS1o_q9nJ~NzF2_Fmr21TNX&~eoJR49FFdFhD3U"
MAX_RETRIES=3
INITIAL_TIMEOUT=600
Confidence
84% confidence
Finding
The hardcoded API endpoint establishes that the script transmits user data to an external service. In context this is expected for cloud image generation, but it still matters because the skill accepts arbitrary user prompts and reference URLs and sends them off-device.

Static analysis

No suspicious patterns detected.