Back to skill

Security audit

Topmediai AI Music Generator

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to be a legitimate TopMediai music-generation integration, but it can send the user's API key and prompts to any configured base URL without host or HTTPS validation.

Review before installing. Use this only with a trusted .env and launcher environment, keep TOPMEDIAI_BASE_URL set to the official HTTPS TopMediai API unless you fully trust the alternate endpoint, avoid submitting confidential prompts or personal data, and leave TOPMEDIAI_DEBUG disabled in shared or logged environments.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/topmediai_api.py:20
Finding

Unrestricted API Base URL Enables Credential and User-Content Exfiltration

Content
View full analysis

Vulnerability Details

File Location: scripts/topmediai_api.py:20-22, 107-125, 153-157, 241-246, 265-271
Vulnerability Type: Unvalidated network destination for sensitive requests
Risk Level: High

Vulnerable Code

python
BASE_URL = os.environ.get("TOPMEDIAI_BASE_URL", "https://api.topmediai.com")
DEFAULT_KEY = os.environ.get("TOPMEDIAI_API_KEY")
DEBUG_MODE = str(os.environ.get("TOPMEDIAI_DEBUG", "0")).lower() in {"1", "true", "yes", "on"}
python
def _headers(api_key: Optional[str] = None) -> Dict[str, str]:
    key = api_key or DEFAULT_KEY
    if not key:
        raise RuntimeError(
            "TOPMEDIAI_API_KEY not configured. Edit: {} and set TOPMEDIAI_API_KEY=YOUR_KEY."
            "Get/purchase a key at https://www.topmediai.com/api/basic-information/interface-key/".format(_ENV_PATH)
        )
    return {"x-api-key": key, "Content-Type": "application/json"}


def generate_lyrics(prompt: str, api_key: Optional[str] = None) -> Dict[str, Any]:
    url = f"{BASE_URL}/v1/lyrics"
    headers = _headers(api_key)
    payload = {"prompt": prompt}
    _debug_request("POST", url, headers=headers, payload=payload)
    try:
        r = requests.post(url, json=payload, headers=headers, timeout=60)
python
def generate_music(
    action: str = "auto",
    prompt: Optional[str] = None,
    lyrics: Optional[str] = None,
    title: str = "",
    style: str = "Pop",
    mv: str = "v5.0",
    instrumental: int = 0,
    gender: str = "male",
    api_key: Optional[str] = None,
) -> Dict[str, Any]:
    url = f"{BASE_URL}/v3/music/generate"
python
    headers = _headers(api_key)
    _debug_request("POST", url, headers=headers, payload=data)
    try:
        r = requests.post(url, json=data, headers=headers, timeout=120)

Technical Analysis

The API client obtains TOPMEDIAI_BASE_URL directly from the process environment or project ...[truncated 1867 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove TOPMEDIAI_BASE_URL customization if alternate API hosts are not strictly required.
  • Otherwise, parse the value with urllib.parse.urlparse and require:
    • The https scheme.
    • The exact approved hostname api.topmediai.com.
    • No embedded username or password.
    • An approved port, normally 443.
  • Reject IP literals, unexpected subdomains, URL fragments, and malformed authorities.
  • Build endpoint paths relative to a trusted, hardcoded origin.
  • Before attaching x-api-key, verify that the final request URL still belongs to the approved origin.
  • Disable redirects for authenticated requests or validate every redirect destination before forwarding credentials.
  • Document that proxy and environment configuration must be trusted.
  • Rotate the API key if it may already have been used with an untrusted base URL.

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Dependencies Are Not Reproducibly Pinned or Integrity-Verified

Content
View full analysis

Vulnerability Details

File Location: requirements.txt:1-2
Vulnerability Type: Unbounded dependency resolution and missing package integrity verification
Risk Level: Medium

Vulnerable Code

text
requests>=2.31.0
python-dotenv>=1.0.1

The documented installation procedure in README.md:12 executes:

text
pip install -r requirements.txt

Technical Analysis

Both dependencies use open-ended minimum-version constraints. Consequently, an installation may resolve to any later release available from the configured package index rather than the versions reviewed with this Skill. No lock file or cryptographic hashes authenticate the selected distributions.

The package names are legitimate and no malicious dependency was confirmed in the audited artifact. The weakness is that future installation behavior is not reproducible and can change after this audit. A compromised upstream release, compromised package index, or unexpectedly incompatible future release could therefore enter the execution path without a source review.

Attack Path

  1. A future permitted dependency release is compromised, replaced, or introduces exploitable behavior.
  2. A user follows the documented pip install -r requirements.txt command.
  3. pip resolves the unbounded constraint to that unreviewed release.
  4. Package installation code or imported runtime code executes under the user's account.
  5. The compromised dependency gains access to the process environment and data available to the Skill, potentially including TOPMEDIAI_API_KEY.

Impact Assessment

Exploitation through a compromised dependency could execute code with the privileges of the account installing or running the Skill. This could expose environment variables, the TopMediai API key, prompts, lyrics, workspace files, and other resources accessible to that account.

The practical scope depends on the privileges of the Python environm ...[truncated 71 chars]

Remediation
View remediation

Remediation Suggestions

  • Pin each reviewed dependency to an exact version using ==.
  • Generate and commit a lock file containing cryptographic hashes, for example with pip-compile --generate-hashes.
  • Install with hash enforcement, such as pip install --require-hashes -r requirements.txt.
  • Use a dedicated virtual environment with only the permissions required by the Skill.
  • Periodically update dependencies through a controlled process that includes vulnerability scanning, source provenance checks, and regression testing.
  • Configure pip to use a trusted package index and avoid unreviewed extra indexes.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/topmediai_api.py:69
Finding

Debug Logging Exposes User Content and Partial API-Key Material

Content
View full analysis

Vulnerability Details

File Location: scripts/topmediai_api.py:69-82
Vulnerability Type: Sensitive information exposure through diagnostic output
Risk Level: Low

Vulnerable Code

python
def _mask_key(value: Optional[str]) -> str:
    if not value:
        return ""
    if len(value) <= 8:
        return "*" * len(value)
    return f"{value[:4]}***{value[-4:]}"


def _debug_request(method: str, url: str, headers: Dict[str, str], payload: Optional[Dict[str, Any]] = None, params: Optional[Dict[str, Any]] = None):
    if not DEBUG_MODE:
        return
    safe_headers = dict(headers)
    if "x-api-key" in safe_headers:
        safe_headers["x-api-key"] = _mask_key(str(safe_headers.get("x-api-key")))
    info: Dict[str, Any] = {"debug": {"method": method, "url": url, "headers": safe_headers}}
    if payload is not None:
        info["debug"]["payload"] = payload
    if params is not None:
        info["debug"]["params"] = params
    print(info)

Technical Analysis

When TOPMEDIAI_DEBUG is enabled, _debug_request() writes request metadata to standard output. The API key is only partially masked, revealing its first and last four characters when it is longer than eight characters. Request payloads and parameters are logged without redaction.

Depending on the operation, these values can contain complete prompts, lyrics, titles, task IDs, and song IDs. Standard output may be retained by the Agent platform, shell history capture, process supervisors, CI systems, or centralized logging services.

Debug mode is disabled by default, which limits exposure. Nevertheless, it can be enabled through an inherited environment variable without a separate privacy warning or payload-redaction control.

Attack Path

  1. TOPMEDIAI_DEBUG is intentionally enabled for troubleshooting or inherited from the execution environment.
  2. A user submits a prompt, lyrics, title, task ID, or so ...[truncated 766 chars]
Remediation
View remediation

Remediation Suggestions

  • Replace the API-key value with a constant such as [REDACTED]; do not expose prefixes or suffixes.
  • Do not log prompt, lyric, title, task-ID, or song-ID fields by default.
  • If payload diagnostics are required, add a separate explicit opt-in setting and redact or truncate sensitive fields.
  • Emit only non-sensitive metadata such as the HTTP method, approved endpoint path, response status, and a locally generated correlation identifier.
  • Warn users that debug output may contain sensitive data and should not be enabled in shared or production environments.
  • Apply restrictive retention and access controls to logs.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (21)

Tainted flow: 'url' from os.environ.get (line 283, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The request URL is derived from TOPMEDIAI_BASE_URL in the environment and is used directly for outbound requests while sending the x-api-key header. If an attacker can influence environment configuration, they can redirect requests to an attacker-controlled host and exfiltrate the API key and all submitted prompts/lyrics.

Content

Scanner excerpt · scripts/topmediai_api.py (reported line 118)May include surrounding context.

python
payload = {"prompt": prompt}
    _debug_request("POST", url, headers=headers, payload=payload)
    try:
        r = requests.post(url, json=payload, headers=headers, timeout=60)
        r.raise_for_status()
        j = r.json()
        return _extract_data_with_purchase_link(j)

Tainted flow: 'url' from os.environ.get (line 283, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

This POST also uses a URL built from the environment-controlled BASE_URL and includes the API key in headers plus user content in the body. A poisoned TOPMEDIAI_BASE_URL would send credentials and generated music prompts/lyrics to an unintended destination.

Content

Scanner excerpt · scripts/topmediai_api.py (reported line 155)May include surrounding context.

python
headers = _headers(api_key)
    _debug_request("POST", url, headers=headers, payload=data)
    try:
        r = requests.post(url, json=data, headers=headers, timeout=120)
        r.raise_for_status()
        j = r.json()
        return _extract_data_with_purchase_link(j)

Tainted flow: 'url' from os.environ.get (line 283, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The GET request target is built from the environment-supplied base URL and includes authenticated access via x-api-key. If the base URL is attacker-controlled, task IDs and the API key can be disclosed to a malicious service, and responses can be spoofed back into the application.

Content

Scanner excerpt · scripts/topmediai_api.py (reported line 267)May include surrounding context.

python
headers = _headers(api_key)
    _debug_request("GET", url, headers=headers)
    try:
        r = requests.get(url, headers=headers, timeout=60)
        r.raise_for_status()
        j = r.json()
        data = _extract_data_with_purchase_link(j)

Tainted flow: 'url' from os.environ.get (line 283, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The MP4 generation request sends the API key to a URL derived from the environment without endpoint validation. An attacker who can alter TOPMEDIAI_BASE_URL can capture credentials and influence downstream behavior by returning crafted API responses.

Content

Scanner excerpt · scripts/topmediai_api.py (reported line 288)May include surrounding context.

python
headers = _headers(api_key)
    _debug_request("POST", url, headers=headers, params=params)
    try:
        r = requests.post(url, params=params, headers=headers, timeout=300)
        r.raise_for_status()
        j = r.json()
        return _extract_data_with_purchase_link(j)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · .env (reported line 1)May include surrounding context.

text
# Copy to .env and fill your key
TOPMEDIAI_API_KEY=YOUR_KEY
TOPMEDIAI_BASE_URL=https://api.topmediai.com

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/topmediai_api.py (reported line 17)May include surrounding context.

python
# Resolve skill root dynamically (scripts/ -> skill root)
_SKILL_ROOT = Path(__file__).resolve().parents[1]
_ENV_PATH = _SKILL_ROOT / ".env"
if _ENV_PATH.exists():
    load_dotenv(_ENV_PATH.as_posix())

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README explicitly documents that user prompts, task IDs, and generated content are sent to TopMediai's external APIs, but it does not warn users that their inputs leave the local environment. This creates a real privacy and data-handling risk because users may supply sensitive prompts or identifiers under the assumption the skill operates locally.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill declares use of sensitive capabilities via its documented behavior: it reads an API key from environment configuration and makes outbound network requests to multiple external TopMediai endpoints, but it does not explicitly declare any tool scope such as permissions or allowed-tools. This creates a governance and review gap: a host may grant broader capabilities than intended, and users or automated policy systems cannot reliably assess or constrain the skill's access before execution.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest description advertises only music/lyrics generation and omits the separate MP4 generation capability. This can mislead users and reviewers about the skill's full behavior and external processing scope, reducing informed consent and making oversight harder, though it is primarily a transparency issue rather than direct code execution risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The manifest says the skill generates music via the TopMediai API but does not clearly warn users that prompts and related request data will be transmitted to a third-party service. Because prompts may contain sensitive or proprietary content, lack of disclosure undermines informed consent and can lead to unintentional data exposure outside the local environment.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This CLI forwards user-supplied prompts, lyrics, titles, and task identifiers directly to external TopMediai API functions without any user-facing disclosure at the point of transmission. While expected for the skill's purpose, it creates a real privacy and data-handling risk because users may provide sensitive creative text or identifiers without being explicitly warned that the content is sent to a third-party service.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/topmediai_api.py (reported line 118)May include surrounding context.

python
payload = {"prompt": prompt}
    _debug_request("POST", url, headers=headers, payload=payload)
    try:
        r = requests.post(url, json=payload, headers=headers, timeout=60)
        r.raise_for_status()
        j = r.json()
        return _extract_data_with_purchase_link(j)

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/topmediai_api.py (reported line 155)May include surrounding context.

python
payload = {"prompt": prompt}
    _debug_request("POST", url, headers=headers, payload=payload)
    try:
        r = requests.post(url, json=payload, headers=headers, timeout=60)
        r.raise_for_status()
        j = r.json()
        return _extract_data_with_purchase_link(j)

Tainted flow: 'data' from requests.get (line 270, network input) → requests.post (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/topmediai_api.py (reported line 155)May include surrounding context.

python
headers = _headers(api_key)
    _debug_request("POST", url, headers=headers, payload=data)
    try:
        r = requests.post(url, json=data, headers=headers, timeout=120)
        r.raise_for_status()
        j = r.json()
        return _extract_data_with_purchase_link(j)

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill requires an API key and performs credential-backed external operations, but the manifest does not clearly disclose this to end users. While use of an API key is normal for an integration skill, failing to communicate that invocations trigger authenticated third-party network activity can surprise users and obscure data handling and operational boundaries.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

The command description states 'One command' but the manifest exposes additional commands for task status queries and MP4 generation. This inconsistency can cause users, operators, or security reviewers to underestimate the accessible functionality, which weakens transparency and may conceal unexpected network-backed actions.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency is specified with a lower bound only (requests>=2.31.0), which allows future installs to pull different versions over time and prevents reproducible builds. This becomes a security issue because vulnerable or behavior-changing releases could be installed without review, and the separate advisory finding shows that the package has had security issues historically.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
requests>=2.31.0
python-dotenv>=1.0.1

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
88% confidence
Finding

The manifest does not pin requests, and the package has multiple known advisories across versions, so there is no way to verify from this file whether the installed release is safe. In a skill that calls an external API, requests is likely central to network communication, making dependency ambiguity more relevant because vulnerable HTTP client behavior could affect secrets, TLS handling, redirects, or credential exposure.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

python-dotenv>=1.0.1 is not version-pinned, so installations are not reproducible and may resolve to newer releases with unreviewed changes or vulnerabilities. Because this package can affect environment-variable loading and local file handling, uncontrolled upgrades can introduce security-relevant behavior into the skill runtime.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
requests>=2.31.0
python-dotenv>=1.0.1

Unverifiable Dependency: python-dotenv has 2 known advisory(ies) (CVE-2026-28684 (python-dotenv: Symlink following in set_key allows arbitrary file overwrite via ); CVE-2026-28684 (python-dotenv reads key-value pairs from a .env file and can set them as environ)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
84% confidence
Finding

Because python-dotenv is unpinned and has known advisories in some versions, the manifest cannot demonstrate that deployments avoid affected releases. While this dependency is not inherently dangerous in this context, skills commonly use .env files for API secrets, so a vulnerable dotenv version could have security consequences involving local file handling or secret management.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The raised RuntimeError message at L274 is hard-coded in Chinese ("权益不足,请购买后重试") with no fallback or user language selection. This creates a locale-policy concern because the skill imposes a specific language in a user-facing message without documented opt-in or justification.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.