Back to skill

Security audit

Unit Map Page

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent Beatra-backed image-generation purpose, but it also grants broad shared account access and silently self-updates code, so it should go to Review before installation.

Install only if you are comfortable giving this package a shared Beatra device authorization with broad media, wallet, artifact, and task permissions, and if silent package self-updates are acceptable in your environment. Consider disabling automatic updates with scripts/mcp_client.py update --auto off and using the skill only in an account where Beatra credit spending and artifact access are intended.

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

Error
Location
scripts/authorize.py:34
Finding
Overprivileged Shared OAuth Token and Unrestricted MCP Tool Dispatch<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:34-37`; `scripts/mcp_client.py:1477-1488` **Vulnerability Type**: Excessive authorization scope and unrestricted privileged tool selection **Risk Level**: High ### Vulnerable Code ```python # scripts/authorize.py:34-37 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 # scripts/mcp_client.py:1477-1488 call = subparsers.add_parser("call", help="Call one tool with a JSON object on stdin") call.add_argument("tool_name") ... elif args.command in {"tools", "call"}: result = _run_command(args.command, getattr(args, "tool_name", None)) ``` ```python # scripts/mcp_client.py:1465-1474 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 classroom mind-map images from user-supplied content. Its legitimate requirements include image generation, optional reference-image upload, model discovery, task management, and billing operations. The authorization helper nevertheless requests permissions for unrelated capabilities, including: - Video generation - Music generation - Speech generation - Voice-resource reading and writing - General artifact access - Wallet spending - Task cancellation In addition, the bundled MCP client accepts an arbitrary `tool_name` from the command line and forwards it to the remote MCP server. It does not enforce a package-specific allowlist matching the operations documented in `SKILL.md`. Although the token is shared among Beatra packages, that architecture does not provide least privilege for this individual Skill. A compromised or incorrectly instructed Agent can use this package's generic client to invoke operations unrelated to unit-map image generation. ### ...[truncated 1561 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the shared full-scope token with a package-specific, least-privilege credential. 2. Request only the capabilities required by this Skill, such as: - Image generation and editing - Model-card lookup - Explicit reference-file upload - Necessary artifact reads - Task reads and user-requested cancellation - Minimum required billing or wallet operations 3. Remove video, music, speech, and voice-write scopes unless a separately installed Skill explicitly requires them. 4. Add a local allowlist in `mcp_client.py` for this package. Reject all tool names outside the documented set before reading or using the credential. 5. Separate read-only and billable permissions where supported. Do not grant wallet spending merely because wallet balance or ledger reads are required. 6. Require explicit user confirmation immediately before every billable tool invocation, independent of the Skill's natural-language instructions. 7. Bind authorization grants to the package identifier and enforce that binding server-side so another package cannot reuse the credential for unrelated operations. 8. Log non-secret authorization decisions and rejected tool names for auditability without logging prompts, bearer tokens, or sensitive user content. ]]>

T03 · Remote Payload Retrieval and Execution

Warning
Location
scripts/mcp_client.py:969
Finding
Silent Remote Replacement of Executable Package Files Without Independent Publisher Signatures<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:969-1018`; invocation at `scripts/mcp_client.py:1542-1544` **Vulnerability Type**: Automatically retrieved and installed remote executable payload **Risk Level**: Medium ### Vulnerable Code ```python # scripts/mcp_client.py:969-1018 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 3880 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Disable automatic installation by default. Update checking may remain automatic, but installation should require informed user approval. 2. Sign release manifests using an offline publisher key and embed the corresponding trusted public key or key identity in the reviewed package. 3. Verify a detached signature over the package name, channel, locale, version, archive hash, manifest hash, and complete file list. 4. Ensure TLS and SHA-256 checks remain in place as defense-in-depth rather than treating them as publisher authentication. 5. Implement secure signing-key rotation, including explicit trust transitions signed by an already trusted key. 6. Consider using a transparency log or reproducible package registry so clients can detect targeted or equivocal releases. 7. Display the current and proposed versions, publisher identity, and verified signature status before installation. 8. Preserve the existing path, symlink, size, ownership, transaction, and rollback protections. 9. Do not silently suppress all update exceptions. Record a concise, non-sensitive diagnostic so users can determine whether update verification or rollback failed. 10. Offer a pinned-version mode for security-sensitive deployments and document how administrators can centrally disable automatic replacement. ]]>
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (26)

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill declares itself as a simple classroom mind-map generator, yet the instructions explicitly require shell execution, filesystem access, network access, and use of a bundled client that can read/write local state and contact remote services. That undeclared capability expansion violates least privilege and increases the blast radius if the bundled tooling is compromised or misused.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The documented behavior substantially exceeds the stated purpose: in addition to generating images, it performs authentication, credential storage, arbitrary remote MCP invocation, uploads, telemetry/registration, uninstall actions, and self-update/package replacement. This mismatch can mislead users and reviewers into granting trust to a skill that can modify the host, persist secrets, and communicate with external services.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
Automatic self-update with package replacement is a system-modifying capability unrelated to the core classroom image-generation task. Even with claimed verification, silent updates expand supply-chain risk and can change code on disk without a contemporaneous user decision, which is especially risky inside a skill expected to be content-focused.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The manifest presents the skill as a simple classroom unit-map generator, yet it is wired to a remote MCP endpoint using authenticated access. This creates a capability/expectation mismatch: user-supplied educational content and session context may be sent off-device to an external service without the manifest clearly justifying that dependency, increasing data exposure and trust-boundary risk.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The skill accesses persisted credentials for an external service even though its stated function is generating classroom mind-map pages from user input. Using stored bearer credentials expands the blast radius of any misuse, compromise, or unintended invocation because the skill can act against an external account or service beyond the user's immediate expectations.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
The documentation describes a bundled client that silently checks for and automatically installs software updates, which is unrelated to the stated purpose of generating classroom unit mind maps. In a skill context, embedded self-update behavior expands the trust boundary and creates a supply-chain execution path that could modify local files outside the user’s expected task flow.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
Automatic package replacement capability is not justified for a classroom content-generation skill and introduces unnecessary ability to alter installed software. Even if integrity checks are described, the presence of self-modifying installation logic creates a powerful mechanism that could be abused through compromise of the update source, packaging pipeline, or surrounding client environment.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The document describes automatic outbound installation registration and local persistence behavior that is unrelated to the skill’s stated purpose of generating classroom unit mind maps. This creates an unexpected data flow and external contact path, which is risky because users are not likely to anticipate telemetry-like behavior from a local educational content tool.

Context-Inappropriate Capability

Medium
Confidence
97% confidence
Finding
The skill performs best-effort installation registration to an external service, sending package metadata, platform, and an installation reference despite the skill’s educational map-generation function not requiring this behavior. Even if described as non-billable and non-secret, the automatic telemetry introduces privacy, trust, and supply-chain risk because it expands the attack surface beyond the user’s requested task.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The OAuth scope string requests many powerful capabilities far beyond what a unit-map generation skill should need, including wallet spending, task control, and generation across multiple media types. Over-scoped tokens increase blast radius: if the credential is misused or stolen, an attacker could perform unrelated actions with the user's Beatra account.

Context-Inappropriate Capability

Medium
Confidence
86% confidence
Finding
The code fingerprints the host agent platform from environment variables and captures the device hostname, then persists that metadata locally for later use. For a classroom unit-map skill, this data collection is not clearly necessary and creates avoidable privacy exposure and system profiling information that could aid tracking or targeting.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The authorization flow writes a local skills inventory containing package slug, platform, and resolved install path. This exceeds the stated purpose of generating unit maps and exposes local filesystem structure and installed-skill history, which can leak sensitive operational context if read by other software or attackers.

Description-Behavior Mismatch

High
Confidence
95% confidence
Finding
The client contains extensive self-update, package download, archive validation, rollback, and on-disk replacement logic that is unrelated to a classroom unit-map skill's stated purpose. Even though the implementation includes multiple integrity checks, it still grants the package the ability to silently fetch and replace its own code, materially expanding the trust boundary and enabling remote code change if the update channel or publisher is ever compromised.

Description-Behavior Mismatch

Medium
Confidence
92% confidence
Finding
The code records a local skill inventory and sends installation telemetry such as package slug, version, platform, and external installation reference to remote services, none of which is necessary to generate unit mind-map pages. This creates avoidable data collection and expands the attack surface for tracking, correlation, and privacy leakage beyond the declared skill purpose.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
The skill fingerprints the host environment using environment variables and local state to classify the agent platform, then attaches that metadata to requests. For a unit-map creation skill, this collection is unrelated to core functionality and can be used for environment profiling and cross-context tracking.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The script’s purpose is to manage shared Beatra credentials and installation inventory during uninstall, which is unrelated to the advertised classroom unit-map functionality. That mismatch expands the skill’s privilege footprint and creates an unnecessary trust boundary crossing into credential and device-management operations.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
This code performs a network POST to revoke a shared OAuth device token, giving the skill the ability to affect account/device authorization beyond its stated educational purpose. Even if intended for cleanup, embedding credential revocation in a content-generation skill creates a dangerous capability that could disrupt other installed skills or be repurposed to interfere with access.

Context-Inappropriate Capability

High
Confidence
96% confidence
Finding
The script enumerates and later deletes shared local state files including credentials and installation metadata under ~/.beatra. For a skill whose stated role is generating unit map pages, direct access to shared credential storage is unnecessary and increases the risk of unauthorized deletion, disruption of other skills, or future abuse of sensitive local state.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill states that newer versions install automatically without separate confirmation, but this system-modifying behavior is not clearly disclosed up front in the skill description. Hidden or insufficiently disclosed code replacement undermines informed consent and materially increases supply-chain and persistence risk.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The client is documented to install higher versions automatically without separate confirmation, which means local file replacement can occur without a clear user prompt at the time of change. Silent modification of installed code reduces user awareness and control, increasing the risk of unintended execution changes and making socially engineered or supply-chain attacks harder to detect.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The documentation indicates automatic registration and writes to `~/.beatra/registrations.json`, but the skill description does not warn users that using the skill may trigger a network request and local filesystem modification. This lack of upfront disclosure undermines informed consent and can surprise users operating in restricted, privacy-sensitive, or policy-controlled environments.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
maybe_auto_update() performs best-effort silent self-updates that can modify installed package files during normal command execution without an immediate user-facing warning. Silent code replacement is dangerous because it changes the software trust base outside the user's direct awareness, and a compromised update source would turn this into transparent remote code deployment.

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
97% confidence
Finding
Referencing a local credential file for device-bearer authentication gives the skill a path to reusable secrets that authorize access to an external service. In a skill whose purpose appears unrelated to account management, this is especially sensitive because compromise, overbroad permissions, or prompt-induced misuse could expose or abuse external-service capabilities under the user's identity.

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
94% confidence
Finding
Referencing credentials.json as part of the files this skill can remove indicates the package is designed to handle shared authentication material. Access paths to credential stores are highly sensitive, and in this context they are not justified by the unit-map feature set, making the capability itself dangerous.

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
98% confidence
Finding
The _device_token function reads an access token directly from credentials.json, exposing the shared bearer token to skill-controlled code. Direct token access enables misuse of the credential for unauthorized API actions and is especially risky because the token is shared across skills rather than scoped to this package alone.

Static analysis

No suspicious patterns detected.