Back to skill

Security audit

exam-mnemonic-song

Security checks for vulnerabilities and agentic risk

Overview

The skill can perform its advertised mnemonic-song workflow, but it asks for much broader Beatra account access and silently updates its own local code.

Review this skill carefully before installing. It is not just a lyric helper: it connects to Beatra, stores a reusable local credential, can spend credits through generation tools, and can silently update its package files. Disable automatic updates if you install it, and only authorize it if you are comfortable granting broad Beatra media/account permissions beyond mnemonic music generation.

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

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/authorize.py:34
Finding
Mnemonic-song authorization grants unrelated cross-media and account privileges<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:34-37`; unrestricted tool dispatch at `scripts/mcp_client.py:1465-1480` **Vulnerability Type**: Excessive authorization scope and missing local tool allowlist **Risk Level**: Medium ### 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 generic command dispatcher accepts any MCP tool name supplied to it: ```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 generate exam mnemonic songs. Its legitimate requirements include music generation, relevant model and task reads, billing access, and user-requested task cancellation. The authorization scope additionally grants: - Image generation - Video generation - Speech generation - Voice reading and modification - Broad artifact read and write access - Wallet spending - General MCP tool access These permissions are not required to create mnemonic songs. The broad scope is particularly significant because `mcp_client.py call` does not restrict the supplied tool name to the operations documented by this Skill. Consequently ...[truncated 1838 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the shared cross-media scope with a package-specific, least-privilege scope containing only: - Music generation - Required model metadata reads - Task reads - User-requested task cancellation - Minimum billing or wallet operations required by the documented workflow 2. Remove image, video, speech, and voice privileges from this Skill's authorization request. 3. Separate artifact permissions into narrowly scoped operations and grant them only if this Skill actually needs artifact transfer. 4. Avoid a general `wallet:spend` capability where the service can instead authorize only approved music-generation operations. 5. Add a local allowlist in `_run_command` and reject all other tool names. The allowlist should include only documented operations such as: - `beatra.models.list` - `beatra.music.generate` - `beatra.tasks.get` - `beatra.tasks.list` - `beatra.tasks.cancel` - Required read-only wallet operations - Installation registration, if retained 6. Enforce the same package-level restrictions on the server so bypassing the local client cannot recover the broader capabilities. 7. Display the exact requested privileges on the authorization page in user-understandable terms. 8. Use separate credentials for separate Skills rather than sharing one full-scope token across unrelated media packages. ]]>

T03 · Remote Payload Retrieval and Execution

Warning
Location
scripts/mcp_client.py:969
Finding
Default silent updater can retrieve and install mutable remote executable code without independent signature verification<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:31-32`, `scripts/mcp_client.py:969-1020`, and `scripts/mcp_client.py:1523-1525` **Vulnerability Type**: Automatic remote payload retrieval and executable replacement **Risk Level**: Medium ### Vulnerable Code The update metadata and package are obtained from vendor-controlled remote locations: ```python PACKAGE_DISCOVERY_URL = "https://beatra.ai/skills/exam-mnemonic-song/channels/clawhub/install.json" PACKAGE_CDN_BASE_TEMPLATE = "https://cdn.beatra.ai/agent-packages/exam-mnemonic-song/channels/clawhub/v{version}" ``` Ordinary commands invoke the updater silently: ```python else: maybe_auto_update() ``` The complete automatic-update decision path is: ```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_h ...[truncated 3894 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Sign the discovery document or release manifest with an offline release key. 2. Embed only the corresponding public verification key in the reviewed client. 3. Verify the signature before trusting version numbers, URLs, hashes, manifests, archives, or file lists. 4. Use key rotation metadata signed by an already trusted key; do not obtain replacement trust keys from the same unsigned discovery response. 5. Consider recording releases in a verifiable transparency log and rejecting releases without a valid inclusion proof. 6. Make automatic executable installation opt-in rather than enabled by default. 7. Prefer checking automatically but require explicit user approval before replacing Python scripts or Skill instruction files. 8. Display the current version, target version, publisher identity, affected files, and signature status before installation. 9. Preserve the existing fixed-origin, redirect, archive-safety, ownership, size-limit, rollback, and downgrade protections; these remain valuable defense-in-depth controls. 10. Separate update checking from billable operations so update failure or user refusal can never trigger replay of a paid request. ]]>
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 (16)

Lp3

Medium
Category
MCP Least Privilege
Confidence
97% confidence
Finding
The skill exposes and instructs use of powerful capabilities (environment access, file read/write, network, and shell) without declaring them, which prevents informed consent and weakens platform policy enforcement. In this skill, those capabilities are used to invoke a bundled Python client, persist local state, communicate with remote services, and modify package-owned files, all of which materially exceed a simple lyric-generation workflow.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The advertised purpose is exam mnemonic song generation, but the documented behavior also includes OAuth authorization, credential storage, remote tool invocation, file upload, telemetry/registration, uninstall logic, and automatic update/install behavior. This mismatch is dangerous because users may invoke the skill expecting content creation while unknowingly authorizing persistent system and account actions that expand the attack surface and trust boundary.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The skill includes automatic self-update and installation behavior unrelated to its core mnemonic-song task. Any mechanism that downloads and replaces local files introduces a supply-chain and local integrity risk; even with stated verification, silent updates increase the blast radius of compromise or implementation mistakes and are especially risky when embedded in an unrelated end-user skill.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The manifest presents a benign study-song generator, but the runtime instructions document package update, download, verification, and file replacement operations. This hidden system-modifying behavior is dangerous because it conditions users and hosts to approve a low-risk content skill that actually performs privileged maintenance actions outside the expected scope.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The OAuth scope string requests a very broad set of capabilities, including artifacts, images, videos, speech, voices, task control, and wallet spending, far beyond what an exam mnemonic song skill appears to need. Over-scoped tokens violate least privilege and materially increase blast radius if the credential is abused, leaked, or the skill later performs actions outside the user's expected purpose.

Context-Inappropriate Capability

Critical
Confidence
96% confidence
Finding
The requested scopes include voices:read and voices:write, which allow voice management capabilities that are not clearly necessary for generating simple mnemonic songs from user-provided study facts. Excess voice permissions can expose or modify voice assets and substantially exceed user expectations for an exam helper skill.

Context-Inappropriate Capability

High
Confidence
96% confidence
Finding
The requested scopes include voices:read and voices:write, which allow voice management capabilities that are not clearly necessary for generating simple mnemonic songs from user-provided study facts. Excess voice permissions can expose or modify voice assets and substantially exceed user expectations for an exam helper skill.

Context-Inappropriate Capability

High
Confidence
96% confidence
Finding
The requested scopes include voices:read and voices:write, which allow voice management capabilities that are not clearly necessary for generating simple mnemonic songs from user-provided study facts. Excess voice permissions can expose or modify voice assets and substantially exceed user expectations for an exam helper skill.

Context-Inappropriate Capability

Medium
Confidence
83% confidence
Finding
The script collects local host metadata such as detected platform and hostname, and records a local inventory of installed skills and install paths. While stored locally, this behavior is not obviously necessary for a mnemonic-song skill and creates privacy-sensitive metadata that could reveal environment details or usage patterns if the local state directory is later accessed by other software.

Description-Behavior Mismatch

High
Confidence
93% confidence
Finding
The file implements broad remote capabilities—self-update, installation registration/telemetry, generic tool listing/calling, and artifact upload—that materially exceed the stated purpose of generating mnemonic songs for exams. In a skill context, this creates an unnecessarily large trust boundary: the package can fetch and replace its own code and invoke arbitrary backend tools, increasing the chance of abuse or compromise far beyond the advertised user function.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
The code fingerprints the runtime environment via environment variables and host files, then records installation telemetry and registration state. That data collection is not justified by the skill's stated educational/music purpose, so it introduces unnecessary privacy risk and expands the impact of any backend misuse or breach.

Context-Inappropriate Capability

Medium
Confidence
87% confidence
Finding
The skill exposes a generic local file upload path that can send arbitrary regular files to a remote service after obtaining upload instructions. For an exam mnemonic song studio, this is broader than expected and could enable accidental exfiltration of sensitive local content if another component or prompt steers a user toward uploading the wrong file.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The skill states that updates install automatically without separate confirmation, but this is not clearly surfaced up front in the description. Silent system modification without prominent disclosure undermines informed consent and can lead users to run code that changes local files and behavior over time without realizing it.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The documentation states that the bundled client automatically performs an installation registration call and writes a local cache, but it does not clearly warn users that metadata is transmitted and persisted. Even if the data is described as non-secret and non-billable, silent telemetry can create privacy, compliance, and trust issues, especially in enterprise or regulated environments where outbound data collection requires disclosure and consent.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The package performs silent automatic self-updates and can replace installed files during normal execution without a contemporaneous user warning. Even with checksum validation, this gives a remote distribution channel the ability to change local code behavior after installation, which is especially risky when the advertised skill function is simple mnemonic generation.

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 exposed self-update command enables the package to modify its own installed code, which is a self-modification capability. In this skill context, that is more dangerous because the declared purpose does not require code replacement, yet the feature gives the remote publisher ongoing ability to alter local behavior and expand future capabilities.

Static analysis

No suspicious patterns detected.