Back to skill

Security audit

short-drama-voice-pack

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real voice-pack skill, but it asks for broader Beatra account powers than the voice task needs and can silently update its own code.

Review this carefully before installing. Install only if you are comfortable with a shared Beatra bearer credential, broad media and wallet permissions, installation metadata being sent to Beatra, and automatic package-file updates. For predictable reviewed code, disable automatic updates with `python3 scripts/mcp_client.py update --auto off` before routine use.

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
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/mcp_client.py:969
Finding
Silent Automatic Updates Permit Post-Audit Code Replacement<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:969-1018`, `scripts/mcp_client.py:1539-1543`; behavior documented in `SKILL.md:138-153` **Vulnerability Type**: Remote payload retrieval and execution through a default-enabled self-updater **Risk Level**: High ### Code Snippet ```python def maybe_auto_update( *, state_dir: Path | None = None, install_root: Path | None = None, get_bytes: GetBytes = _default_get_bytes, now: float | None = None, ) -> bool: """Best-effort silent update. Never block the requested MCP command.""" resolved_state = state_dir or Path.home() / ".beatra" try: resolved_root = (install_root or _current_install_root()).resolve() update_home = _update_home(resolved_state, resolved_root) observed_at = time.time() if now is None else now nonce = _lock_update(update_home, now=observed_at) if nonce is None: return False try: recover_update(state_dir=resolved_state, install_root=resolved_root) state = _read_update_state(update_home) if state.get("auto_update", True) is False: return False last_checked = state.get("last_checked_at") if ( isinstance(last_checked, (int, float)) and observed_at - float(last_checked) < UPDATE_CHECK_MAX_AGE_SECONDS ): return False state["last_checked_at"] = observed_at _write_private_json(update_home / "state.json", state) checked = check_update(get_bytes=get_bytes) if not checked["update_available"]: return False _ensure_owned_baseline( install_root=resolved_root, update_home=update_home, get_bytes=get_bytes, ) discovery = checked["discovery"] manifest, new_files = download_update(discovery, get_bytes=get_byte ...[truncated 3168 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Default `auto_update` to `False` for new installations. 2. Require explicit, informed user confirmation before downloading and applying a release. 3. Sign discovery metadata and release manifests with an offline release key, and pin the corresponding public key in the audited client. 4. Verify signatures independently of TLS and CDN-provided hashes. 5. Display the current version, target version, changed file list, and release identity before replacement. 6. Provide a version-pinning option so security-sensitive installations can remain on an audited release. 7. Separate update checking from update installation; an automatic check must not imply automatic replacement. 8. Consider distributing updates through the host platform's reviewed package mechanism rather than implementing in-process self-modification. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/authorize.py:34
Finding
Device Authorization Requests Permissions Beyond the Voice-Pack Function<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:34-37` **Vulnerability Type**: Overbroad OAuth/device-token scope violating least privilege **Risk Level**: High ### Code Snippet ```python SCOPE = ( "mcp:tools artifacts:write images:generate videos:generate music:generate " "speech:generate voices:read voices:write wallet:spend tasks:read artifacts:read tasks:cancel" ) ``` ### Technical Analysis The Skill declares a short-drama voice-pack function. Its legitimate workflow needs speech generation, voice listing and optional voice creation, relevant artifact upload/read access, task-status access, and the minimum billing permission needed to pay for those operations. The requested device authorization also includes explicit permissions for image generation, video generation, music generation, broad wallet spending, and task cancellation. Those capabilities are unrelated to producing labeled speech clips. The documentation also states that one shared token covers multiple media categories, meaning compromise of this package can expose capabilities well beyond its declared function. This is a least-privilege failure rather than an operating-system privilege escalation. The token does not grant root or local administrator access, but it does grant excessive service-account capabilities and paid-operation authority. ### Attack Path 1. The user runs `scripts/authorize.py`. 2. The helper requests the complete hardcoded `SCOPE` set. 3. The user approves the device authorization. 4. The resulting bearer token is written to `~/.beatra/credentials.json`. 5. A malicious future update, compromised bundled client, or other code able to use that shared credential invokes image, video, or music generation, spends wallet credits, or cancels account tasks. 6. The remote API accepts those operations because the token was authorized for capabilities unrelated to the voice-pack task. ### Impact Assessment The excessive scope can expose the ...[truncated 534 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Define a package-specific scope containing only the capabilities required by this voice-pack workflow. 2. Remove `images:generate`, `videos:generate`, and `music:generate`. 3. Exclude `tasks:cancel` unless cancellation is explicitly requested and separately authorized. 4. Replace broad `wallet:spend` authority with a constrained speech/voice billing permission where the service supports it. 5. Use incremental authorization for optional voice cloning rather than granting voice-write permission to every installation. 6. Bind paid permissions to tool categories, spending limits, or per-operation user confirmation. 7. Avoid sharing one full-scope bearer token across unrelated Skill packages. Use package-bound credentials or attenuated child tokens. 8. Show the exact requested permissions and their consequences on the approval page. ]]>

other

Warning
Location
scripts/authorize.py:340
Finding
Authorization Collects and Transmits Hostname and Stable Installation Metadata<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:340-367`, `scripts/authorize.py:458-468`; related registration at `scripts/mcp_client.py:1209-1247` **Vulnerability Type**: Unnecessary environment identification and installation telemetry **Risk Level**: Medium ### Code Snippet ```python def detect_host_platform(explicit: str | None = None) -> str: """The agent environment this process runs inside (docs/device-model.md). Order: explicit agent self-report > environment signatures > unknown. Detection reads the process environment only — nothing else runs, nothing reaches the network. """ if explicit: candidate = explicit.strip().lower().replace(" ", "-") if _PLATFORM_VALUE.fullmatch(candidate): return candidate env = os.environ if env.get("CLAUDECODE") == "1" or "CLAUDE_CODE_ENTRYPOINT" in env: return "claude-code" if any(key.startswith("CODEX_") for key in env): return "codex" ai_agent = env.get("AI_AGENT", "").lower() matched = re.match(r"([a-z0-9-]+)_", ai_agent) if matched and _PLATFORM_VALUE.fullmatch(matched.group(1)): return matched.group(1) return "unknown" def device_display_name() -> str | None: """A hostname the user will recognise in the console device list.""" try: name = socket.gethostname().strip() except OSError: return None if not name or not name.isprintable(): return None return name[:120] ``` The collected hostname is included in the authorization request: ```python form: dict[str, str] = { "client_id": CLIENT_ID, "resource": MCP_URL, "scope": SCOPE, "platform": host_platform, "client_name": PACKAGE_DISPLAY_NAME, "external_installation_ref": external_reference, "package_version": PACKAGE_VERSION, "package_slug": PACKAGE_SLUG, } if device_name: form["device_name"] = device_name ``` ...[truncated 1953 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Make hostname transmission opt-in and explain its purpose before collection. 2. Use a random, non-identifying device label by default. 3. Allow the user to provide a display name explicitly instead of automatically reading the hostname. 4. Make installation registration telemetry independently configurable. 5. Minimize transmitted registration fields and avoid stable identifiers unless operationally necessary. 6. Document the purpose, retention period, access controls, and deletion procedure for device metadata. 7. Ensure disabling telemetry does not prevent authentication or normal speech-generation operations. 8. Retain the current narrow platform detection rather than expanding it to arbitrary environment-variable collection. ]]>
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
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (25)

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill declares itself as a voice-pack generator, but its documented operation includes shell, file, environment, and network-capable helper tooling without an explicit permissions declaration or user-facing capability boundary. This increases the chance that users or downstream systems will authorize a skill without understanding that it can access local state, invoke commands, and communicate externally.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The documented behavior substantially exceeds the stated purpose: beyond generating voice packs, it performs OAuth login, token persistence, arbitrary file upload, generic remote tool invocation, telemetry/registration, uninstall-side credential actions, and self-updating code replacement. That mismatch is dangerous because users may grant trust based on a narrow description while the skill actually has a much broader and more sensitive operational surface.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The skill includes a silent self-update mechanism that can download and replace package files during normal use, even though that behavior is unrelated to generating a short-drama voice pack. Any code path that modifies installed code from the network expands the supply-chain attack surface, and doing so silently removes an important user review and approval barrier.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The manifest presents a focused media-generation skill, but the runtime behavior includes automatic update checks and installs during standard command execution. Even if integrity checks exist, introducing network-driven code changes into routine operation violates least surprise and can expose users to unanticipated behavior changes or compromise if the update channel is abused.

Description-Behavior Mismatch

Medium
Confidence
87% confidence
Finding
The changelog explicitly mentions adding read-only balance and ledger calls, which are unrelated to converting scripts into labeled voice clips. Even if read-only, exposing financial/account interfaces in a media-production skill broadens the accessible data surface and can enable unnecessary account reconnaissance or privacy leakage.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
The manifest metadata describes a short-drama voice pack generator, but the package also appears to request MCP-backed account/ledger access with no functional justification in the user-facing description. This mismatch is dangerous because users and reviewers may consent to a creative tool while unintentionally granting access to financial/account information.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
This documentation describes a bundled client that silently checks for and installs software updates, behavior that is unrelated to a short-drama voiceover skill and materially expands the skill's operational scope. Even if the text claims verification and rollback protections, a hidden updater introduces a software modification path on the user's system that could be abused or could violate user expectations about what this skill should do.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
Silently auto-installing updates without separate confirmation gives the package an undocumented mechanism to change local code after installation. In the context of a voiceover skill, this is especially dangerous because users would not reasonably expect it to modify software on disk, and any compromise of the update channel or logic could lead to unauthorized code changes.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The OAuth scope request is far broader than the skill’s stated purpose of producing short-drama voice packs. In addition to speech and voice permissions, it requests images, videos, music, artifacts, task control, and wallet spending, so a granted token could be used for unrelated operations and financial actions if the service or downstream tooling is abused or compromised.

Context-Inappropriate Capability

Medium
Confidence
87% confidence
Finding
The code derives the host platform from environment variables and collects the device hostname, then persists that metadata locally. For a voiceover skill, this is extra host-identifying data that is not clearly necessary for core functionality and increases privacy exposure, especially in agent or enterprise environments where hostnames and platform markers may reveal deployment details.

Context-Inappropriate Capability

Medium
Confidence
84% confidence
Finding
The authorization helper maintains a shared local inventory of installed skills under ~/.beatra/skills.json, which goes beyond authorizing this specific voice-pack skill. Cross-skill inventory creates unnecessary visibility into other installed packages and usage patterns, expanding privacy and trust boundaries without an obvious need tied to the advertised functionality.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
The file implements broad self-update, package replacement, and telemetry behavior that is unrelated to the declared voice-pack purpose. In the context of a creative audio skill, this materially expands trust and attack surface by allowing remote code/package changes and background networked behavior that users would not reasonably expect from the advertised functionality.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The code fingerprints the host environment using environment variables and local host metadata, then uses that platform value in outbound requests. That collection is not necessary for generating voice packs, and in this skill context it creates avoidable privacy leakage and environment enumeration that could aid targeting or profiling.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The skill persists a local inventory of installed skills and sends installation-registration telemetry during normal operation. For a voice-pack tool, that behavior is outside expected scope and discloses local software usage metadata that can be sensitive, especially when done silently and repeatedly.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
This uninstall script is for a short-drama voice pack, but it contains logic to manage shared device state and potentially revoke a remote Beatra authorization. That capability is outside the skill’s stated media-generation purpose and creates security-sensitive side effects during uninstall, increasing the blast radius from simple package removal to shared account/device access changes.

Context-Inappropriate Capability

Medium
Confidence
97% confidence
Finding
The code performs a network POST to revoke device authorization using a bearer token read from local state. Even if intended for cleanup, a content-generation skill should not independently hold logic that can disable shared authorization for other skills or the host environment, especially because uninstall-time network actions are powerful and difficult for users to validate.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
Automatic updates are enabled by default and newer releases install without separate confirmation, but the skill does not clearly warn users in its confirmation flow. This undermines informed consent and can allow security-relevant behavior changes to occur under the guise of a normal voice-generation action.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
Enabling automatic updates by default without a clear upfront warning weakens user consent and transparency around local file modification. While not inherently remote code execution by itself, it creates a risky trust boundary in an unrelated skill and makes unexpected system changes more likely to occur unnoticed.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The documentation states that the bundled client automatically performs an installation registration call and writes a local cache file, but it does not present any user-facing warning, consent, or clear disclosure about outbound metadata transmission and filesystem changes. Even though the transmitted data is described as non-secret and non-billable, silent network calls and persistent local writes can violate user expectations, privacy requirements, or enterprise policy, especially in creative tooling that users may assume works purely locally.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The authorization request sends platform, package, installation reference, and optionally device hostname to the remote authorization service before any explicit user warning about that metadata. This undermines informed consent and can leak environment-identifying information from agent-hosted systems where such identifiers may be sensitive.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
maybe_auto_update() performs best-effort silent package updates before normal commands, modifying installation files without a user-facing prompt in the execution path. Even with checksum and path checks, silently replacing local code increases the risk of supply-chain compromise and violates least surprise for a content-generation skill.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The code registers installation telemetry during ordinary session setup, and the code path contains no user-facing notice or consent gate. Silent metadata transmission is risky in a voice-pack skill because it exposes operational details unrelated to the requested audio task.

Credential Access

High
Category
Privilege Escalation
Content
},
  "mcp": {
    "authentication": "device-bearer",
    "credential_file": "~/.beatra/credentials.json",
    "name": "beatra",
    "transport": "streamable-http",
    "url": "https://mcp.beatra.ai/mcp"
Confidence
84% confidence
Finding
Referencing a local credential file means the skill is configured to use bearer-backed credentials for remote MCP access. In a skill whose purpose is unrelated to account data, this is risky because any overbroad tool access or downstream misuse could leverage the user's existing authenticated context to query sensitive services without a clear business need.

Credential Access

High
Category
Privilege Escalation
Content
def _device_token(state_dir: Path) -> str | None:
    path = state_dir / "credentials.json"
    try:
        value = json.loads(path.read_text(encoding="utf-8"))
    except (OSError, ValueError):
Confidence
94% confidence
Finding
The function reads an access token from ~/.beatra/credentials.json and uses it to authenticate a revocation request. Accessing shared credentials from within a skill-specific uninstall script violates least privilege and gives this package direct capability over shared authorization state unrelated to its short-drama functionality.

Self-Modification

High
Category
Rogue Agent
Content
)
    update = subparsers.add_parser(
        "update",
        help="Check, install, or configure Beatra package self-updates",
    )
    update.add_argument(
        "--check",
Confidence
96% confidence
Finding
The skill includes self-modification capability through its update command and supporting package replacement logic. In a voice-pack skill, this is unusually powerful and dangerous because it permits remote-origin code changes to the installed package, turning any upstream compromise or logic flaw into local code replacement.

Static analysis

No suspicious patterns detected.