Back to skill

Security audit

Game UI Voice Pack

Security checks for vulnerabilities and agentic risk

Overview

This skill is not clearly malicious, but it should be reviewed carefully because a voice-clip skill requests broad Beatra account access and silently self-updates local code.

Install only if you trust Beatra with a shared, broad device authorization for media generation, artifact access, wallet spending, and task control. Consider disabling silent updates immediately with python3 scripts/mcp_client.py update --auto off, use an account where that scope is acceptable, and revoke the device from the Beatra Console if you stop using these skills.

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

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/authorize.py:31
Finding
Authorization Requests Capabilities Beyond the Skill's Declared Functionality<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:31-38`; related unrestricted dispatch at `scripts/mcp_client.py:1463-1480` **Vulnerability Type**: Excessive OAuth scope and unrestricted remote tool dispatch **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" ) ``` The MCP client also allows the caller to supply an arbitrary remote tool name: ```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 Skill's declared purpose is to create game UI voice clips. Its legitimate requirements include speech synthesis, optional voice cloning and sample upload, voice/model lookup, task status reads, and limited billing visibility. The requested authorization scope additionally includes: - Image generation - Video generation - Music generation - Broad artifact read and write access - Wallet spending - Task cancellation - General MCP tool access These permissions are not all necessary to generate UI voice clips. In addition, the bundled client does not enforce a local allowlist of tools appropriate to this package. Any tool name supplied through ...[truncated 1690 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Define a package-specific OAuth scope containing only the operations required for UI voice generation. 2. Remove image, video, and music generation permissions from this Skill. 3. Separate optional voice cloning and asset upload permissions from baseline speech synthesis, requesting them only when the user chooses those features. 4. Replace unrestricted wallet spending with a narrowly scoped permission limited to explicitly confirmed speech or cloning operations, if the service supports it. 5. Enforce a local allowlist in `mcp_client.py`, such as: - `beatra.models.list` - `beatra.voices.list` - `beatra.voices.clone` - `beatra.speech.synthesize` - `beatra.assets.upload` - `beatra.tasks.get` - `beatra.tasks.list` - `beatra.tasks.cancel` only after explicit user authorization - Required read-only wallet operations 6. Reject any tool name outside the allowlist before reading or forwarding arguments. 7. Use separate credentials per Skill where practical so compromise of one package cannot affect every Beatra package installed on the device. 8. Display the exact requested scopes on the approval page in user-readable terms. ]]>

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/mcp_client.py:969
Finding
Default Silent Updates Can Replace Executable Skill Code Without Per-Update Consent<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:969-1018`; automatic invocation at `scripts/mcp_client.py:1542-1544` **Vulnerability Type**: Automatic retrieval and installation of remotely controlled executable content **Risk Level**: High ### Vulnerable Code ```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_bytes) ...[truncated 3953 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Default `auto_update` to `False`. 2. Require explicit, informed user confirmation before downloading or installing each new version. 3. Keep automatic update checks separate from automatic installation; checking may be silent, but replacement should require consent. 4. Sign release manifests with an offline release key and embed only the corresponding public verification key in the package. 5. Verify the signature before trusting any version, file list, or SHA-256 digest from discovery metadata. 6. Display the current version, target version, source, changed files, and security-relevant changes before installation. 7. Offer a check-only mode as the default behavior. 8. Preserve and display an audit log recording update time, source version, destination version, manifest digest, and signature identity. 9. Consider platform-managed immutable package updates instead of self-modifying executable code. 10. Retain the existing archive validation, ownership checks, lock, rollback, and recovery controls as defense-in-depth. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/mcp_client.py:1044
Finding
Windows Credential Storage Relies on Unverified Inherited ACLs<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:1044-1051`; related credential creation behavior at `scripts/authorize.py:115-129` **Vulnerability Type**: Missing Windows ACL enforcement for a broad bearer credential **Risk Level**: Medium ### Vulnerable Code ```python def _read_private_credentials(state_dir: Path, path: Path) -> str: if os.name == "nt": # The state directory lives under the user profile, whose default # ACL is already private to the user (the gh/aws/gcloud posture). # The former custom DACL verification was dropped deliberately: its # command patterns read as hostile to agent safety policies and # endpoint security, failing installs while adding nothing an # elevated administrator could not bypass. return path.read_text(encoding="utf-8") ``` Credential file restriction is only implemented for POSIX: ```python def _restrict_file(path: Path) -> None: if os.name == "posix": path.chmod(0o600) ``` The authorization process writes the bearer credential through this cross-platform helper: ```python def _atomic_json(path: Path, value: dict[str, Any]) -> None: _private_directory(path.parent) temporary = path.parent / f".{path.name}.{secrets.token_hex(8)}.tmp" descriptor = os.open(temporary, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600) try: with os.fdopen(descriptor, "w", encoding="utf-8") as stream: json.dump(value, stream, ensure_ascii=False, separators=(",", ":")) stream.write("\n") stream.flush() os.fsync(stream.fileno()) _restrict_file(temporary) os.replace(temporary, path) _restrict_file(path) if os.name == "posix": directory_fd = os.open(path.parent, os.O_RDONLY) try: os.fsync(directory_fd) finally: os.close(directory_fd) finally: temporary.unlink(missing_ok=Tru ...[truncated 2338 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Store the Device Token in Windows Credential Manager or another operating-system-protected secret store. 2. If a file must be used, create `~/.beatra` and `credentials.json` with an explicit DACL granting access only to: - The current user - `SYSTEM`, if operationally required 3. Disable inheritance or remove unrelated inherited access-control entries from the credential file. 4. Verify the file owner and effective ACL before every credential read. 5. Reject the credential with a clear recovery message if any unrelated principal has read access. 6. Apply equivalent protection to temporary credential files before writing token content. 7. Ensure ACL-safe atomic replacement does not replace a protected destination with a temporary file carrying weaker inherited permissions. 8. Add automated Windows tests covering permissive parent ACLs, restored files, redirected profiles, and unauthorized local principals. 9. Update the documentation only after implementation and documented guarantees are consistent. ]]>
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 (20)

Lp3

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding
The skill exposes broad operational capabilities—environment access, filesystem read/write, shell execution, and network use—without declaring permissions or constraining them in the manifest. That creates a transparency and containment failure: users are told this is a voice-pack skill, but it can also execute local commands, touch local state, and communicate externally, which increases the chance of unauthorized data access or system changes.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The documented behavior substantially exceeds the advertised purpose by including authentication, persistent credential storage, generic remote tool invocation, file upload, telemetry/registration, uninstall, and self-update logic. This mismatch is dangerous because users may grant trust based on a narrow audio-production description while the skill performs broader actions that affect the host, credentials, and local files.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The skill includes automatic package update and replacement logic unrelated to its primary audio-generation function. Self-updating code materially expands supply-chain and host-modification risk because the package can change after review, and updates are installed without a separate approval step at the moment of change.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The manifest frames the skill as producing game UI voice clips, but the documentation also authorizes installation management, package replacement, rollback, and recovery operations. Even if those mechanisms are intended to be safe, they are outside the expected scope and increase the attack surface by enabling local software modification from within a content-production skill.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The file documents telemetry-like installation registration that sends package slug, version, platform, and a stable external installation reference on first use, which is outside the skill's stated purpose of generating game UI voice clips. Even if described as non-billable and non-blocking, this creates undisclosed environment and installation tracking that can leak metadata and expand the trust boundary without a user need tied to the skill's function.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
The described behavior includes platform resolution from environment signatures or persisted host metadata and transmits that along with a stable installation reference. For a game voice-pack generation skill, this is unrelated data collection and mild host fingerprinting, which increases privacy risk and could support cross-session tracking or backend profiling if abused or combined with other data.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The authorization scope requests a very broad set of capabilities, including wallet spending, task control, artifact access, image/video/music generation, and voice management, far beyond what a game UI voice-pack skill should need. If the issued token is compromised or the skill later uses those permissions unexpectedly, the user's account and billable resources could be abused well outside the advertised purpose.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
The skill persists host-identifying metadata such as platform and device name and also records a local inventory of installed skills, which is not clearly necessary for generating game UI voice clips. This expands privacy exposure and creates additional local tracking data that could be sensitive if the workstation is shared, inspected, or later accessed by another process.

Description-Behavior Mismatch

High
Confidence
95% confidence
Finding
The package includes broad network update/discovery capabilities and remote service interaction that go beyond the stated purpose of producing game UI voice clips. In this skill context, hidden self-update and extra network behavior materially increase supply-chain and privacy risk because the component can fetch and apply new code or contact external infrastructure unrelated to the user-visible task.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The skill records local inventory and installation/registration metadata unrelated to generating voice clips, including install paths and timestamps. In a creative voice-pack skill, this extra data collection expands device telemetry and can reveal local environment details without clear necessity or user awareness.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The code fingerprints the host environment using agent-specific environment variables and persisted host data, then attaches platform attribution to requests. For a voice-clip generation skill, this is unnecessary context gathering that can support tracking, profiling, or differential targeting across agent environments.

Description-Behavior Mismatch

Medium
Confidence
92% confidence
Finding
The uninstall script manages shared device authorization and revocation, which is outside the stated purpose of a game UI voice-pack skill. Even if intended for cleanup, coupling a content-generation skill to account/device credential lifecycle introduces privileged behavior that can affect other installed skills and expands the blast radius if the script is invoked unexpectedly or modified.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
This code reads an access token from a shared credentials store and uses it to call a remote revocation endpoint. Accessing bearer tokens from disk is a sensitive credential-handling capability not justified by the skill’s voice-generation function, and compromise or misuse of this path could disrupt all skills sharing the device connection or enable token abuse if the code were altered.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill describes automatic updates that install without separate confirmation but does not present a prominent warning that this modifies local software. In context, that makes the voice-generation skill more dangerous because users may not expect host changes from a media-production workflow, reducing informed consent around system modification.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The document explicitly states that the client silently checks for and automatically installs newer releases before ordinary commands, without separate confirmation. Even with integrity checks and rollback protections, silently modifying installed code changes the user's system state and trust boundary without an explicit just-in-time warning or consent, which can surprise users and increase supply-chain risk if the update channel is ever compromised.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The code performs silent automatic self-updates that modify installed package files during normal operation without an explicit user-facing confirmation at execution time. Even with checksum and manifest validation, this creates a supply-chain risk surface where future code can be introduced under the guise of a voice-pack skill, making the context more dangerous because the declared functionality does not require self-modifying behavior.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
Installation telemetry is sent best-effort to a remote service during session setup without a clear user-facing disclosure in the runtime flow. This is risky because it quietly transmits package/version/platform/installation reference data unrelated to the immediate task of generating voice clips, increasing privacy and tracking concerns.

Credential Access

High
Category
Privilege Escalation
Content
#: these and then removes the directory only if it is empty — the script
#: never recursively deletes a directory it does not fully understand.
_STATE_FILES = (
    "credentials.json",
    "installation.json",
    "host.json",
    "skills.json",
Confidence
86% confidence
Finding
Referencing and planning deletion of credentials.json indicates the skill is aware of and operates on shared credential material. In this context, direct interaction with shared auth artifacts by a voice-pack skill is an unnecessary privileged capability that increases risk of credential loss, unintended logout, or future abuse if the package is tampered with.

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
96% confidence
Finding
The function opens credentials.json and extracts an access token, which is direct credential access. Reading bearer tokens in skill code is dangerous because any compromise of the skill, supply-chain tampering, or logging/exception leakage could expose reusable authentication material, and here the token also controls shared device authorization used by other skills.

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
97% confidence
Finding
The package exposes self-update functionality that downloads archive/manifests and replaces installed files, which is self-modification behavior. In the context of a simple voice-pack skill, this is disproportionately dangerous because it creates a built-in mechanism for changing executable behavior after installation, increasing supply-chain and trust-boundary risks.

Static analysis

No suspicious patterns detected.