Back to skill

Security audit

Wealth Open Calendar

Security checks for vulnerabilities and agentic risk

Overview

This skill can create the described calendar images, but it also asks for broad Beatra account access and silently updates its own code, so it needs review before installation.

Install only if you are comfortable giving this Beatra package a shared device token with broad media, wallet, artifact, and task permissions, plus local credential storage, install telemetry, and automatic code updates. Disable automatic updates before normal use if you want reviewed code to stay fixed, use a limited Beatra account where possible, and only upload files you intentionally want sent to Beatra.

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 Replacement of Executable Package Code<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:969-1013`, `scripts/mcp_client.py:1541-1544`, `SKILL.md:161-180`, `references/automatic-updates-and-safety.md:3-19` **Vulnerability Type**: Remote payload retrieval and execution **Risk Level**: Critical ### 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 3716 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Disable automatic updates by default and require explicit, informed user approval before each installation. 2. Separate update checking from update installation. A routine business command should not modify executable files. 3. Authenticate releases using an offline-pinned public key rather than relying only on hashes obtained from the release service. 4. Sign version, package identity, channel, manifest digest, and rollback metadata. 5. Require threshold signing or another independently controlled release authorization process for executable updates. 6. Display the current version, proposed version, changed executable files, signer identity, and release notes before approval. 7. Pin audited versions in the Skill manifest and require re-audit before executing a new version. 8. Preserve the existing path, archive, symlink, locking, ownership, and rollback protections as defense-in-depth. 9. Until redesigned, ship with automatic updates disabled and document `update --check` as the safe default. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/authorize.py:32
Finding
Excessive OAuth Scope Combined with Unrestricted MCP Tool Dispatch<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:32-38`, `scripts/mcp_client.py:1463-1483`, `scripts/mcp_client.py:1488-1491` **Vulnerability Type**: Least-privilege violation and unrestricted privileged tool selection **Risk Level**: High ### Vulnerable Code The authorization request asks for capabilities substantially broader than still-image calendar generation: ```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 client accepts any MCP tool name supplied on the command line and forwards it without a package-specific allowlist: ```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}, ) ``` ```python call = subparsers.add_parser("call", help="Call one tool with a JSON object on stdin") call.add_argument("tool_name") ``` ### Technical Analysis The declared purpose is to create and optionally edit still-image calendar assets. The implementation nevertheless requests authorization for video, music, speech, voice reading and writing, general artifact writing, wallet spending, task reading, and task cancellation. Some image-generation, artifact, task-read, and billing permissions are reasonably relat ...[truncated 2138 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Define a package-specific minimum scope containing only: - Required model discovery. - Image generation and approved image editing. - Narrow artifact upload/read access. - Task reads for jobs created by this package. - Read-only wallet pricing or billing access where necessary. 2. Remove video, music, speech, and voice-write scopes from this Skill. 3. Avoid a shared full-scope credential. Issue separate audience- and capability-bound credentials for each Skill or capability group. 4. Add an explicit local tool allowlist, for example: - `beatra.models.list` - `beatra.images.generate` - `beatra.images.edit` - `beatra.assets.upload` - `beatra.tasks.get` - `beatra.tasks.list` - `beatra.tasks.cancel` only after explicit user authorization - Required read-only wallet tools 5. Reject all unknown tool names before opening a network session. 6. Bind task reads and cancellation to task identifiers created by the same package or installation where the service supports that restriction. 7. Separate spending authorization from ordinary read operations and require a short-lived, operation-specific confirmation token for paid calls. 8. Enforce the same allowlist and scope restrictions server-side; do not rely solely on client checks. ]]>

other

Warning
Location
scripts/authorize.py:344
Finding
Unnecessary Collection and Transmission of Host and Installation Identifiers<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:344-370`, `scripts/authorize.py:443-466`, `scripts/mcp_client.py:1148-1168`, `scripts/mcp_client.py:1360-1389` **Vulnerability Type**: Environment reconnaissance and persistent device telemetry **Risk Level**: Medium ### Vulnerable Code The authorization helper fingerprints the Agent environment and obtains the local hostname: ```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] ``` Those values are included in the device authorization request together with a stable installation reference: ```python external_reference = _installation_reference(state_dir) form: dict[str, str] = { "client_id": CLIENT_ID, "resource": MCP_URL, "scope": SCOPE, "platform": host_platform, "client_name": PACKAGE_DISPLAY_NAME, ...[truncated 3115 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove hostname collection and transmission unless it is strictly required for a user-requested device-management feature. 2. If a device label is useful, ask the user to provide one explicitly and explain that it will be sent to Beatra. 3. Make installation telemetry opt-in rather than automatic. 4. Avoid inspecting Agent-specific environment variables unless the behavior depends on them. 5. Replace the stable installation reference with a rotating, purpose-bound pseudonymous identifier where long-term correlation is unnecessary. 6. Clearly document every transmitted field, its purpose, retention period, and deletion mechanism. 7. Minimize telemetry server-side and prevent its use for unrelated profiling. 8. Provide a configuration option that disables registration telemetry without disabling image-generation functionality. 9. Ensure uninstall or device revocation also deletes associated telemetry according to a documented retention policy. ]]>
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 (24)

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill advertises only a calendar-generation workflow, yet its instructions require shell execution, network access, local file access, and file writes via a bundled client. This creates a materially larger execution and data-exposure surface than the manifest discloses, so a host or user could invoke a capability-rich package without informed consent or appropriate sandboxing.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
There is a strong description-behavior mismatch: a seemingly narrow content-production skill also performs authentication, credential persistence, remote service calls, uploads, telemetry/registration, uninstall/state deletion, and self-update. Users and hosts may trust and approve the skill for low-risk media generation while unknowingly granting a much broader operational footprint capable of handling credentials, exfiltrating files, and changing local code.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The skill includes automatic self-update and installation replacement logic unrelated to its stated task. Any mechanism that downloads and installs code can become a supply-chain execution path; even if verification is claimed, this materially expands risk and enables post-installation behavior changes outside the user's original review.

Description-Behavior Mismatch

Medium
Confidence
90% confidence
Finding
The file’s guidance is materially misaligned with the declared skill purpose: instead of instructions for generating wealth open calendar stills, it provides generic Beatra asynchronous task-handling behavior. That mismatch can cause an agent to invoke or continue unrelated remote tasks, exposing task metadata, artifacts, billing details, or operational state outside the user’s intended workflow.

Context-Inappropriate Capability

Medium
Confidence
86% confidence
Finding
The billing and video-usage instructions are unjustified for a skill that is supposed to create still-image calendar outputs. Including guidance for video-seconds accounting and prepaid billing can steer an agent toward processing unrelated task types or disclosing sensitive usage and billing fields from other work on the same connection, increasing the chance of cross-task data exposure and unintended cost-related actions.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The authorization flow requests a very broad OAuth scope set, including artifacts write/read, image/video/music/speech generation, voice read/write, wallet spending, and task operations, while the skill is described only as generating wealth/open calendar stills. This violates least privilege and materially increases blast radius if the credential is misused, leaked, or if the skill later invokes capabilities outside user expectations.

Context-Inappropriate Capability

Critical
Confidence
94% confidence
Finding
`tasks:read` and `tasks:cancel` allow visibility into and interference with user task activity that is not justified by the skill description. While less severe than wallet access, these permissions still create unnecessary confidentiality and integrity risks if the token is abused.

Context-Inappropriate Capability

High
Confidence
94% confidence
Finding
`tasks:read` and `tasks:cancel` allow visibility into and interference with user task activity that is not justified by the skill description. While less severe than wallet access, these permissions still create unnecessary confidentiality and integrity risks if the token is abused.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
`tasks:read` and `tasks:cancel` allow visibility into and interference with user task activity that is not justified by the skill description. While less severe than wallet access, these permissions still create unnecessary confidentiality and integrity risks if the token is abused.

Description-Behavior Mismatch

High
Confidence
92% confidence
Finding
The client does far more than the declared calendar-generation purpose: it can self-update, register installations, upload local files, and act as a generic remote tool invoker. In a skill context, this materially expands the attack surface and grants a remote service broad influence over local behavior, including replacing package files and brokering arbitrary backend tool calls unrelated to the advertised function.

Context-Inappropriate Capability

Medium
Confidence
82% confidence
Finding
The code fingerprints the host environment from process environment variables and local state, then sends that platform identifier upstream. That collection is not necessary to transform user-supplied open windows into calendar outputs, so it creates avoidable metadata leakage and environment profiling risk.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
The client maintains a local inventory of installed skills and performs installation telemetry unrelated to the skill's declared calendar purpose. This broadens local data collection and remote reporting, creating privacy and trust concerns while adding code paths that are unnecessary for the user-facing function.

Description-Behavior Mismatch

High
Confidence
95% confidence
Finding
This uninstall script performs networked device-token revocation for a shared Beatra connection, which is functionality unrelated to the skill’s stated purpose of generating wealth calendar stills. Even if intended as lifecycle management, it reaches into shared authentication state and can affect other installed skills if the inventory is wrong, corrupted, or manipulated, making the blast radius much larger than this package alone.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
The main uninstall flow reads shared inventory, decides whether other skills remain, may revoke the device token, and deletes shared local state under ~/.beatra. This is dangerous because compromise or logic errors in a single skill package can alter or remove credentials and installation metadata used by other skills, creating denial of service and expanding trust beyond the skill’s documented calendar functionality.

Context-Inappropriate Capability

High
Confidence
96% confidence
Finding
The code defines a remote revocation endpoint and sends the bearer access token over the network to revoke device authorization. That capability is unnecessary for a calendar-generation skill and materially increases risk because a skill-supplied script can invalidate shared authentication, causing service disruption across the device and creating a sensitive network action outside the advertised scope.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The script enumerates shared files in ~/.beatra including credentials, host, inventory, and registration state, which are unrelated to producing calendar stills. Direct inspection and deletion of shared per-device state broadens the skill’s privileges and creates an opportunity for unintended credential handling or disruption if the files are modified or removed incorrectly.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The documentation states that newer versions install automatically without separate confirmation, but users are not clearly warned near normal invocation that executing the skill may later change the local code. This undermines reviewability and trust boundaries, because the security posture of the package can shift after approval through an update path not reaffirmed by the user.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The document states that the client silently checks for updates and automatically installs newer releases by default before ordinary commands, without explicit per-update consent. Even with integrity checks and fixed update sources, this behavior modifies local files automatically and expands supply-chain risk, especially if the trusted update infrastructure or signing process is compromised.

Missing User Warnings

Medium
Confidence
72% confidence
Finding
The skill documents an automatic first-use network registration that transmits package, version, platform, and a stable external installation reference without any explicit privacy notice or opt-in. While the transmitted fields are not described as secrets, stable identifiers and environment metadata can enable tracking, fingerprinting, and unexpected telemetry, especially because the behavior happens automatically.

Missing User Warnings

Medium
Confidence
82% confidence
Finding
The script sends `platform`, `client_name`, `external_installation_ref`, `package_version`, `package_slug`, and optionally a hostname-derived `device_name` to remote authorization endpoints without prominently disclosing that metadata sharing to the user. Although some metadata is normal for device authorization, the hostname/device name can reveal identifying environment information and should be clearly disclosed and minimized.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The skill can silently perform automatic self-updates that download content and overwrite installed package files during normal execution. Even with integrity checks and path validation, executing code that mutates itself without a user-visible prompt is risky in an agent skill, especially when the skill's declared purpose is simple calendar generation.

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
90% confidence
Finding
Referencing credentials.json in the set of files to remove shows the skill is aware of and designed to manipulate credential-bearing shared state. In the context of a non-authentication, calendar-focused skill, touching credential files is unjustified and dangerous because it grants this package influence over device authentication and other skills’ availability.

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 _device_token function reads an access token from credentials.json so the skill can use it for remote revocation. This is credential access by skill code and is especially risky here because the skill’s declared purpose gives no legitimate reason to access bearer tokens, enabling unauthorized use or disruption if abused or modified.

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
91% confidence
Finding
Exposing self-update/self-modification capability in a skill advertised for calendar generation is a significant trust and integrity concern. The code is careful about checksums and safe extraction, but it still permits the package to replace its own installed files from the network, which is a high-risk capability if the update channel or backend governance is ever compromised.

Static analysis

No suspicious patterns detected.