Back to skill

Security audit

Listenhub

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it claims, but it also includes under-disclosed system modification, credential persistence, and script self-update behavior that users should review before installing.

Install only if you are comfortable with third-party API submission of your content and images, and review or remove the auto-update, sudo package-install, and shell-rc credential handling before use. Prefer setting LISTENHUB_API_KEY in the current environment or a dedicated secret store rather than letting the skill modify shell startup files.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
Findings (5)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/lib.sh:10
Finding
Unverified Remote Replacement of Executable Skill Scripts<![CDATA[ ## Vulnerability Details **File Location**: `scripts/lib.sh:10-15, 25-86` **Vulnerability Type**: Runtime download and installation of unverified executable code **Risk Level**: High ### Code Snippet ```bash VERSION_FILE="${SKILL_DIR}/VERSION" REMOTE_VERSION_URL="https://raw.githubusercontent.com/marswaveai/skills/main/skills/listenhub/VERSION" check_version() { # Skip if no local VERSION file [ -f "$VERSION_FILE" ] || return 0 local local_ver remote_ver http_code response local_ver=$(cat "$VERSION_FILE" 2>/dev/null | tr -d '[:space:]') # Validate local version before integer comparisons [[ "$local_ver" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || return 0 # Fetch remote version with 5s timeout, check HTTP status response=$(curl -sS --max-time 5 -w "\n%{http_code}" "$REMOTE_VERSION_URL" 2>/dev/null) || return 0 http_code=$(echo "$response" | tail -1) remote_ver=$(echo "$response" | head -1 | tr -d '[:space:]') # Only compare if HTTP 200 and valid semver-like format [[ "$http_code" == "200" && "$remote_ver" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || return 0 # Same version, skip [ "$local_ver" != "$remote_ver" ] || return 0 # Parse semver: major.minor.patch local local_major local_minor local_patch local remote_major remote_minor remote_patch IFS='.' read -r local_major local_minor local_patch <<< "$local_ver" IFS='.' read -r remote_major remote_minor remote_patch <<< "$remote_ver" if [ "$remote_major" -gt "$local_major" ] || \ { [ "$remote_major" -eq "$local_major" ] && [ "$remote_minor" -gt "$local_minor" ]; }; then local base_url="https://raw.githubusercontent.com/marswaveai/skills/main/skills/listenhub" local api_url="https://api.github.com/repos/marswaveai/skills/contents/skills/listenhub/scripts" local update_success=true if ! curl -fsSL --max-time 10 "$base_url/VERSION" -o "$VERSION_FILE.tmp" 2>/dev/null; then update_success=false fi if [ "$update_success" = true ]; then lo ...[truncated 2669 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove automatic executable updates from normal Skill execution. - Distribute updates through a separate, user-initiated installation or package-management process. - If runtime updating is unavoidable: - Pin downloads to an immutable commit or signed release. - Verify every file against a signed manifest and cryptographic hash. - Maintain an explicit allowlist of expected filenames. - Reject unexpected files and symbolic links. - Download into a private staging directory and validate the complete release before installation. - Require explicit user confirmation before replacing executable files. - Preserve and verify a rollback copy. - Do not treat a mutable Git branch as a trusted executable release channel. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/lib.sh:107
Finding
Arbitrary Shell Command Execution Through Unsafe Configuration Evaluation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/lib.sh:107-115` **Vulnerability Type**: Shell command injection through `eval` **Risk Level**: High ### Code Snippet ```bash # Load API key from shell config (try multiple sources) # Note: source may fail on zsh-specific syntax, so we use || true if [ -n "${LISTENHUB_API_KEY:-}" ]; then : # Already set, skip loading elif [ -f ~/.zshrc ]; then # Extract just the export line to avoid zsh syntax issues eval "$(grep 'export LISTENHUB_API_KEY' ~/.zshrc 2>/dev/null || true)" elif [ -f ~/.bashrc ]; then eval "$(grep 'export LISTENHUB_API_KEY' ~/.bashrc 2>/dev/null || true)" fi ``` ### Technical Analysis The script extracts matching text from `.zshrc` or `.bashrc` and passes the result directly to `eval`. The grep pattern is not anchored to a strict assignment and does not validate or safely decode the value. Any matching line can contain command substitutions, command separators, redirections, or additional shell statements. This also expands the trust boundary: noninteractive Skill scripts execute configuration fragments even though they do not need to source or interpret general shell startup code. ### Attack Path 1. An attacker, compromised installer, or another local process writes a line containing `export LISTENHUB_API_KEY` and malicious shell syntax into `.zshrc` or `.bashrc`. 2. `LISTENHUB_API_KEY` is absent from the current environment. 3. The user invokes any script that sources `scripts/lib.sh`. 4. The matching configuration text is passed to `eval`. 5. Embedded shell syntax executes with the privileges of the Skill process. For example, command substitution embedded in the assigned value would be evaluated before the variable is assigned. ### Impact Assessment Successful exploitation provides arbitrary command execution as the user running the Skill. This can expose the API key, user content, files readable by the process, and other session credentials. If the Skill is run from ...[truncated 118 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove `eval` entirely. - Prefer receiving `LISTENHUB_API_KEY` from the process environment or a dedicated credential store. - If a configuration file must be parsed: - Use a dedicated file with mode `0600`. - Read it as data rather than shell code. - Match exactly one anchored key assignment. - Reject control characters, command substitutions, whitespace anomalies, and unexpected key formats. - Validate the value against the documented `lh_sk_...` key syntax and a reasonable maximum length. - Do not parse general-purpose shell startup files for secrets. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/generate-image.sh:254
Finding
Automatic Privileged System Package Installation During Image Generation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate-image.sh:254-316` **Vulnerability Type**: Unnecessary privilege elevation and unattended system modification **Risk Level**: High ### Code Snippet ```bash check_dependencies() { local missing_deps=() local install_cmd="" if ! command -v jq &>/dev/null; then missing_deps+=("jq") fi if ! find_curl &>/dev/null; then missing_deps+=("curl") fi if [ ${#missing_deps[@]} -gt 0 ]; then echo "→ Missing required tools: ${missing_deps[*]}" >&2 echo " Auto-installing..." >&2 case "$PLATFORM" in macos) install_cmd="brew install ${missing_deps[*]}" if ! command -v brew &>/dev/null; then echo "Error: Homebrew not detected" >&2 exit 1 fi ;; linux) 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 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: Chocolatey or Scoop not detected" >&2 exit 1 fi ;; *) echo "Error: Unsupported platform" >&2 exit 1 ;; esac # Execute installation if eval "$install_cmd"; then echo "✓ Dependencies installed successfully" >&2 else echo "Error: Auto-installa ...[truncated 1503 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Never invoke `sudo` or install system packages automatically during media generation. - When a dependency is missing, stop and report: - The missing dependency. - Why it is needed. - Platform-specific installation commands for the user to review separately. - Require an explicit, separate opt-in operation before any dependency installation. - If an installer is retained, execute fixed commands using shell arrays rather than `eval`. - Prefer documented prerequisites, bundled verified tooling, or an isolated container/environment over system-wide mutation. - Do not perform package-manager metadata updates as a side effect of a generation request. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate-image.sh:345
Finding
Unsafe Plaintext Persistence of an Unvalidated API Key in Shell Startup Files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate-image.sh:345-365` **Vulnerability Type**: Persistent shell injection and insecure secret storage **Risk Level**: High ### Code Snippet ```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 ``` ### Technical Analysis The supplied key is checked only for non-emptiness. It is interpolated into a shell startup file without shell-safe encoding. A value containing quotes, command substitution syntax, newlines, backslashes, or sed replacement metacharacters can alter the generated command or corrupt the configuration file. The credential is also stored in plaintext in `.zshrc`, `.bashrc`, `.profile`, or a similar startup file without checking or enforcing restrictive file permissions. Startup files are executable configuration, not dedicated secret-storage mechanisms. ### Attack Path 1. A crafted value is supplied at the API-key prompt, potentially through copied setup material or automated input. 2. The script embeds the value directly into an `export` statement in the selected startup file. 3. Special characters terminate or alter the intended assignment. 4. A later interactive shell reads the startup file. 5. Injected shell syntax executes persistently in future sessions. Separately, any process or ...[truncated 410 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Validate API keys against the documented prefix, allowed character set, and a reasonable maximum length. - Reject newlines, control characters, quotes, shell metacharacters, and malformed values. - Prefer an operating-system credential manager or another established secret store. - If file storage is unavoidable: - Use a dedicated configuration file rather than executable shell startup files. - Create it with mode `0600`. - Serialize the value as data using a format with safe parsing. - Use atomic writes and preserve existing permissions. - Require explicit user approval before persisting a credential. - If a shell assignment must be generated, use a proven shell-quoting mechanism rather than direct string interpolation. ]]>

other

Warning
Location
SKILL.md:161
Finding
Local Reference Images May Be Published Through Unrelated Third-Party Hosts<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:161-164` **Vulnerability Type**: Privacy exposure through third-party file hosting **Risk Level**: Medium ### Code Snippet ```markdown **Reference Images via Image Hosts** When reference images are local files, upload to a known image host and use the direct image URL in `--reference-images`. Recommended hosts: `imgbb.com`, `sm.ms`, `postimages.org`, `imgur.com`. Direct image URLs should end with `.jpg`, `.png`, `.webp`, or `.gif`. ``` ### Technical Analysis The Skill instructs the Agent to upload local reference images to independent image-hosting services before submitting their URLs to the generation API. This creates an additional disclosure channel beyond ListenHub/Labnana. The workflow does not require informed consent for the selected host, warn that direct links may be publicly accessible, describe retention or deletion behavior, or prohibit uploading sensitive images. A “known” host is not equivalent to a private or access-controlled transfer mechanism. ### Attack Path 1. A user provides a local reference image for image generation. 2. The Agent follows the Skill instruction and selects one of the recommended public hosts. 3. The local image is uploaded to that third party. 4. A direct URL is created and transmitted to the generation service. 5. The image may remain accessible under the host’s retention, indexing, and access-control policies. ### Impact Assessment Private photographs, identity documents, proprietary artwork, screenshots, location data, or other sensitive image content may be disclosed to an additional organization and potentially to anyone possessing or discovering the direct URL. The user may be unable to reliably revoke or delete all hosted copies. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Do not upload local files to third-party hosts automatically. - Require explicit, host-specific informed consent before any upload. - Clearly disclose: - The identity of the third-party host. - Whether the resulting URL is public. - Applicable retention and deletion limitations. - That the URL will also be shared with the generation provider. - Warn users not to upload sensitive, regulated, confidential, or identifying images. - Prefer a first-party authenticated upload mechanism or short-lived, access-controlled object URLs. - Provide a deletion procedure and avoid hosts that do not support reliable revocation. ]]>
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 (49)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
An undeclared self-update mechanism that fetches and replaces local scripts from GitHub, plus access to shell configuration files for credentials, materially expands the trust boundary of the skill. Remote code replacement and credential scraping from rc files create supply-chain and secret-exposure risks if the update source is compromised or if users are unaware these operations occur.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
An undeclared self-update mechanism that fetches and replaces local scripts from GitHub, plus access to shell configuration files for credentials, materially expands the trust boundary of the skill. Remote code replacement and credential scraping from rc files create supply-chain and secret-exposure risks if the update source is compromised or if users are unaware these operations occur.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
An undeclared self-update mechanism that fetches and replaces local scripts from GitHub, plus access to shell configuration files for credentials, materially expands the trust boundary of the skill. Remote code replacement and credential scraping from rc files create supply-chain and secret-exposure risks if the update source is compromised or if users are unaware these operations occur.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
An undeclared self-update mechanism that fetches and replaces local scripts from GitHub, plus access to shell configuration files for credentials, materially expands the trust boundary of the skill. Remote code replacement and credential scraping from rc files create supply-chain and secret-exposure risks if the update source is compromised or if users are unaware these operations occur.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
An undeclared self-update mechanism that fetches and replaces local scripts from GitHub, plus access to shell configuration files for credentials, materially expands the trust boundary of the skill. Remote code replacement and credential scraping from rc files create supply-chain and secret-exposure risks if the update source is compromised or if users are unaware these operations occur.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
An undeclared self-update mechanism that fetches and replaces local scripts from GitHub, plus access to shell configuration files for credentials, materially expands the trust boundary of the skill. Remote code replacement and credential scraping from rc files create supply-chain and secret-exposure risks if the update source is compromised or if users are unaware these operations occur.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
An undeclared self-update mechanism that fetches and replaces local scripts from GitHub, plus access to shell configuration files for credentials, materially expands the trust boundary of the skill. Remote code replacement and credential scraping from rc files create supply-chain and secret-exposure risks if the update source is compromised or if users are unaware these operations occur.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
An undeclared self-update mechanism that fetches and replaces local scripts from GitHub, plus access to shell configuration files for credentials, materially expands the trust boundary of the skill. Remote code replacement and credential scraping from rc files create supply-chain and secret-exposure risks if the update source is compromised or if users are unaware these operations occur.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
An undeclared self-update mechanism that fetches and replaces local scripts from GitHub, plus access to shell configuration files for credentials, materially expands the trust boundary of the skill. Remote code replacement and credential scraping from rc files create supply-chain and secret-exposure risks if the update source is compromised or if users are unaware these operations occur.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
An undeclared self-update mechanism that fetches and replaces local scripts from GitHub, plus access to shell configuration files for credentials, materially expands the trust boundary of the skill. Remote code replacement and credential scraping from rc files create supply-chain and secret-exposure risks if the update source is compromised or if users are unaware these operations occur.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
An undeclared self-update mechanism that fetches and replaces local scripts from GitHub, plus access to shell configuration files for credentials, materially expands the trust boundary of the skill. Remote code replacement and credential scraping from rc files create supply-chain and secret-exposure risks if the update source is compromised or if users are unaware these operations occur.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The script auto-installs dependencies by invoking package managers and, on Linux, uses sudo and noninteractive flags. For an image-generation skill, silently changing system packages is unnecessary and expands impact far beyond the stated media-generation purpose, creating a path to privileged system modification if the script is run in a trusted environment.

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
96% confidence
Finding
The chained apt-get update && apt-get install sequence performs multiple privileged actions in one automated flow. Chaining amplifies impact because it refreshes package metadata and then immediately installs packages without giving the user a pause point, which is excessive for an image-generation helper.

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
96% confidence
Finding
The use of --noconfirm suppresses safety prompts for package installation, making the package-manager invocation harder for users to intercept or review. In this context it meaningfully increases the danger of the already unjustified system-modification capability.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The shared library automatically checks a remote repository and replaces local script files at runtime, which gives remote content the ability to change executable code on the user's machine without explicit approval. In a media-generation skill, self-modifying behavior is unnecessary and materially increases supply-chain and remote code execution risk if the upstream repository, GitHub API response path, or update channel is compromised.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
The script reads shell startup files and `eval`s extracted content in order to obtain credentials, which expands the skill's privilege boundary from its own environment into user profile files. Using `eval` on data parsed from `~/.zshrc` or `~/.bashrc` is especially risky because crafted lines or unexpected shell syntax could trigger arbitrary command execution, and a media-generation skill does not need this capability to function safely.

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
95% confidence
Finding
The skill invokes shell scripts, performs networked API operations, and appears to access local environment/configuration, yet it declares no explicit tool scope or allowed-tools boundary. That increases the chance of overbroad execution in hosts that rely on manifest-level permissions, making unintended shell or network use harder to constrain and audit.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The activation phrases are broad and overlap with ordinary requests like 'read this aloud' or 'generate an image,' increasing the chance the skill is invoked in contexts where the user did not intend network calls, file writes, or third-party data transfer. In a skill with external APIs and local side effects, accidental activation materially increases privacy and execution risk.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The skill instructs uploading local reference images to third-party image hosts without warning about privacy, retention, or public accessibility. Users may unknowingly expose sensitive local images, metadata, or copyrighted material to external services outside the primary vendor's control.

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-provided content and submits it to an external ListenHub API via `api_post` without any explicit notice, confirmation, or consent gate at the point of transmission. In this skill's context, users may paste sensitive text, internal documents, or proprietary material expecting local transformation, so silent outbound transfer creates a real privacy and data-handling risk.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The language validation hard-limits execution to Chinese or English, and the usage text presents only zh|en as permitted values. This is a natural-language policy concern because it forces a locale constraint without user opt-in or an explicit justification for why other languages are unsupported.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The script packages user-provided query text and optional source URLs/texts into a JSON body and sends them to a remote API endpoint, but there is no explicit notice, consent check, or data-sensitivity gating before transmission. In a skill that accepts arbitrary article text, links, and prompts, this can lead to unintended disclosure of sensitive or copyrighted content to an external service.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The usage text constrains --language to zh|en, and later validation rejects any other language. This is a natural-language policy concern because the skill forces a limited locale set without indicating user opt-in rationale or documenting why the restriction is necessary.