Back to skill

Security audit

game-script-voice-pack

Security checks for vulnerabilities and agentic risk

Overview

This voice-pack skill mostly matches its stated media workflow, but it requests broader account powers and silently updates its own code by default.

Review this carefully before installing. It can spend or use Beatra account capabilities beyond voice generation, stores a shared bearer credential locally, sends device and installation metadata to Beatra, and may replace its own package files automatically unless you disable automatic updates with the documented command.

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:984
Finding
Silent Remote Retrieval and Replacement of Executable Skill Code Without Independent Signature Verification<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:31`, `scripts/mcp_client.py:480-489`, `scripts/mcp_client.py:984-1015`, and `scripts/mcp_client.py:1541-1543` **Vulnerability Type**: Remote payload retrieval and execution **Risk Level**: High ### Vulnerable Code ```python PACKAGE_DISCOVERY_URL = "https://beatra.ai/skills/game-script-voice-pack/channels/clawhub/install.json" ``` ```python if _sha256(manifest_content) != discovery["manifest_sha256"]: raise RuntimeError("Beatra update manifest checksum does not match discovery") manifest = _json_object(manifest_content, "Beatra update manifest") manifest_files = _manifest_files(manifest, discovery=discovery) archive = get_bytes( archive_url, UPDATE_DOWNLOAD_TIMEOUT_SECONDS, MAX_UPDATE_ARCHIVE_BYTES, ) if _sha256(archive) != discovery["archive_sha256"]: raise RuntimeError("Beatra update archive checksum does not match discovery") ``` ```python 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_bytes) _apply_update( install_root=resolved_root, update_home=update_home, discovery=discovery, manifest=manifest, new_files=new_files, ) return True ``` ```python else: maybe_auto_update() ``` ### Technical Analysis The client checks for updates before ordinary Beatra commands and automatically replaces package-owned files when a higher version is advertised. Package-owned files include executable Python scripts such as `scripts/mcp_client.py`. The implementation performs substantial integrity and archive-safety validation, including HTTPS-only fixed hosts, redirect rejection, SHA-256 checks, version checks, path traversal prevention, file-size limits, ownership tracking, transactional replacement, ...[truncated 2440 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Disable automatic update installation by default. Perform checks without changing files and require explicit user approval before replacement. 2. Sign each release manifest with an offline or otherwise strongly protected publisher key. 3. Pin the corresponding verification public key or trust root in the reviewed package. 4. Verify the signature before trusting the advertised version, archive hash, manifest hash, or file list. 5. Ensure compromise of the discovery web origin alone cannot produce a valid signed release. 6. Consider integrating with a package manager or transparency log that provides signed metadata, rollback protection, and release provenance. 7. Retain the existing redirect rejection, immutable CDN path checks, archive limits, path validation, transaction journal, and rollback controls as defense in depth. 8. Display the source version, target version, signature identity, and changed executable files before installation. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/authorize.py:34
Finding
Overbroad Device Authorization and Unrestricted MCP Tool Dispatch<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:34-37` and `scripts/mcp_client.py:1463-1480` **Vulnerability Type**: Excessive authorization scope and unrestricted privileged tool selection **Risk Level**: High ### Vulnerable Code ```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" ) ``` ```python def _run_command(command: str, tool_name: str | None = None) -> dict[str, Any]: session = _session_with_registration( state_dir=Path.home() / ".beatra", post_json=_default_post_json, ) if command == "tools": return session.request(2, "tools/list", {}) try: arguments = json.load(os.sys.stdin) except json.JSONDecodeError as exc: raise RuntimeError("Tool arguments on stdin must be one JSON object") from exc if not isinstance(arguments, dict): raise RuntimeError("Tool arguments on stdin must be one JSON object") assert tool_name is not None return session.request( 2, "tools/call", {"name": tool_name, "arguments": arguments}, ) ``` ### Technical Analysis The declared functionality is a multi-character speech pack with optional voice cloning. Necessary capabilities include speech generation, voice listing, optional voice creation, model and pricing reads, relevant artifact upload/read operations, wallet reads, and task status operations. The authorization request additionally includes unrelated capabilities such as: - `images:generate` - `videos:generate` - `music:generate` - General `artifacts:write` - `tasks:cancel` - `wallet:spend` The client also accepts an arbitrary `tool_name` from the command line and forwards it directly in a `tools/call` request. There is no package-specific allowlist limiting dispatch to the tools required by the voice-pack workflow. The documentation explicitly ...[truncated 1862 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Issue package-specific credentials instead of sharing one full-scope token among all Beatra Skills. 2. Request only scopes required for this Skill, separating optional voice-cloning permission from ordinary TTS access where possible. 3. Remove image, video, and music generation scopes from this package. 4. Separate wallet-read operations from credit-spending authority. 5. Add a strict local allowlist covering only documented tools, such as: - Voice listing and explicitly consented cloning. - TTS model and pricing discovery. - Speech synthesis. - Required artifact upload and reads. - Task listing and status reads. - Wallet balance and ledger reads. 6. Require explicit user confirmation immediately before task cancellation or any unexpected paid operation. 7. Enforce the same package/tool restrictions server-side; a local allowlist alone is not a sufficient security boundary. 8. Record auditable package attribution server-side and reject operations outside the package’s declared capability set. ]]>

other

Note
Location
scripts/authorize.py:343
Finding
Undisclosed Hostname Collection and Transmission During Authorization<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:343-370` and `scripts/authorize.py:454-467` **Vulnerability Type**: Environment reconnaissance and device telemetry **Risk Level**: Low ### Vulnerable Code ```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] ``` ```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 status, created = post_form(DEVICE_AUTHORIZATION_URL, form) ``` ### Technical Analysis The authorization helper inspects environment-variable signatures to identify the Agent environment and ...[truncated 1918 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not collect or transmit the operating-system hostname by default. 2. Generate a random, non-identifying device label or use the existing opaque installation reference. 3. Allow the user to provide an optional display name explicitly. 4. Clearly disclose every telemetry field sent during authorization, including hostname, Agent platform, package version, and stable installation reference. 5. Provide an opt-out mechanism for nonessential platform and device-name telemetry. 6. Minimize retention and avoid using these values for purposes unrelated to device management and security. 7. If a hostname must be retained, consider hashing it with a service-specific salt only after determining that the resulting stable identifier is necessary and privacy-appropriate. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (21)

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill declares no permissions while instructing use of shell execution, filesystem access, network access, environment/credential handling, and package modification. This mismatch prevents informed consent and undermines security boundaries, especially because the documented workflow includes remote calls, local file handling, and updater behavior that can materially affect the host system.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The documented behavior substantially exceeds the advertised purpose of generating a voice pack: it includes authentication flows, credential storage, arbitrary MCP tool invocation, remote uploads, telemetry/registration, uninstall cleanup, and self-updating package replacement. That kind of description-behavior mismatch is dangerous because users may authorize a creative-media skill without realizing it can alter software, handle secrets, and communicate broadly with remote services.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The skill includes automatic self-update and package replacement functionality unrelated to the stated task of script-to-voice-pack generation. Even with integrity checks described, silent update logic increases the attack surface and creates a supply-chain risk path where routine skill use can cause local code changes without a dedicated installation/update trust decision.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
A manifest for a media-generation skill should not silently perform software update checks and installation during ordinary use. This broadens trust from 'generate audio' to 'modify local package code,' which is a materially different capability and can be abused through supply-chain compromise or misconfiguration even if the stated intent is maintenance.

Description-Behavior Mismatch

High
Confidence
96% confidence
Finding
The file describes a bundled client that silently checks for and automatically installs software updates before normal commands, which is unrelated to the skill's stated purpose of generating game voice packs. Even though the document claims verification and rollback protections, an auto-update mechanism introduces code-changing behavior and supply-chain risk that is unnecessary in this context and increases the attack surface of the skill.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
Silent automatic software updates are unjustified for a voice-pack generation skill and can be abused to replace local files or deliver altered code without meaningful user awareness. The mismatch between the advertised purpose and the presence of an updater makes the behavior more suspicious, because users would not reasonably expect a script-to-audio tool to modify its own installation automatically.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The requested OAuth scope set is far broader than the advertised purpose of converting game scripts into multi-character voice packs. It includes unrelated capabilities such as image, video, music generation, artifact/task control, and wallet spending, violating least-privilege and allowing misuse of the granted token well beyond voice synthesis.

Context-Inappropriate Capability

Critical
Confidence
99% confidence
Finding
The skill asks for image, video, and music generation permissions even though its manifest describes a script-to-voice-pack workflow. Unrelated generative scopes materially expand the blast radius of token abuse and suggest overcollection of privileges without user need.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The skill asks for image, video, and music generation permissions even though its manifest describes a script-to-voice-pack workflow. Unrelated generative scopes materially expand the blast radius of token abuse and suggest overcollection of privileges without user need.

Context-Inappropriate Capability

Medium
Confidence
79% confidence
Finding
The code derives and persists host platform and device name data, and elsewhere maintains an inventory of installed skill paths, none of which are necessary for the core user-facing voice-pack function. This creates avoidable local metadata collection that can expose environment details and installation layout to other local processes or future components reading the state directory.

Description-Behavior Mismatch

Medium
Confidence
90% confidence
Finding
The client embeds a full self-update and package state-management mechanism unrelated to the stated voice-pack generation purpose. In skill context, this is more dangerous because the package can modify its own installed codebase and persistence state, substantially expanding trust and attack surface beyond a simple content-generation tool.

Description-Behavior Mismatch

Medium
Confidence
85% confidence
Finding
The code records local skill inventory and sends installation-registration telemetry that are not justified by the declared voice-pack functionality. Even if not overtly malicious, hidden persistence and telemetry increase privacy risk and create undocumented data flows from the user's environment.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
The client fingerprints the execution environment using environment variables and local host metadata to classify the host platform. For a voice-pack skill this is unnecessary and increases privacy and tracking capability, especially when coupled with registration telemetry and per-request source tagging.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill states that newer releases install without separate confirmation, but the description does not prominently disclose that normal operation may modify local package files. This weak transparency is dangerous because users cannot meaningfully consent to the security implications of code replacement, and administrators may not realize routine use triggers software changes.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The documentation states that update checks are silent, enabled by default, and lead to automatic installation when a newer version is found, but it does not present a prominent warning at the point of use that local package files may be replaced. This weakens informed consent and increases the risk that users unknowingly execute modified code during ordinary operations.

Missing User Warnings

Medium
Confidence
78% confidence
Finding
The documentation describes an automatic network registration call on first use that transmits package slug, version, platform, and a stable external installation reference, but it does not present an explicit privacy warning or opt-in/opt-out guidance. Because this occurs automatically and includes persistent installation metadata, users may be unaware that identifiable environment information is sent off-host, creating a transparency and privacy risk.

Missing User Warnings

Low
Confidence
71% confidence
Finding
`write_host_config` silently persists host metadata without any user-facing disclosure or consent. While not an immediate compromise by itself, undisclosed persistence of platform and device information weakens transparency and can contribute to privacy and trust issues.

Missing User Warnings

Low
Confidence
74% confidence
Finding
The skill records a local inventory including slug, platform, and absolute installation path without clearly warning the user. Even if intended for uninstall bookkeeping, silently storing this inventory collects extra local telemetry unrelated to producing voice packs.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
maybe_auto_update() performs silent code updates in the background and explicitly 'never block[s]' the requested command, meaning package files can change without clear user awareness at execution time. In this skill context, silent self-modification is especially risky because the expected function is script-to-voice conversion, not autonomous code replacement.

Missing User Warnings

Low
Confidence
80% confidence
Finding
The skill sends platform and external installation reference data as telemetry without obvious user-facing disclosure in this client. While the data volume is limited, it enables device/installation correlation that is unrelated to core voice-pack generation behavior.

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
94% confidence
Finding
The exposed self-update command gives the package the ability to replace its own installed files, which is a self-modification capability. Even with integrity checks, this is a powerful behavior misaligned with the advertised voice-pack purpose and increases supply-chain and persistence risk if the update channel or trust assumptions fail.

Static analysis

No suspicious patterns detected.