Back to skill

Security audit

store-new-item-launch

Security checks for vulnerabilities and agentic risk

Overview

The image-generation workflow is coherent, but the package also grants broad shared account authority, exposes a generic remote tool caller, and silently self-updates without separate confirmation.

Review this before installing if you are comfortable giving this package a shared Beatra device credential with more authority than still-image generation and allowing default silent package updates. Disable automatic updates with the documented command if you install it, and use it only with an account where the broader Beatra scopes and wallet-spend exposure are acceptable.

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:33
Finding
Overprivileged shared credential permits unrelated paid operations<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:33-36`; `scripts/mcp_client.py:1459-1481` **Vulnerability Type**: Excessive OAuth scope and unrestricted MCP 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 generic command handler accepts any tool name supplied on the command line and forwards it to the MCP service: ```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 Skill functionality is limited to creating and editing still images for product-launch boards, uploading selected reference images, reading model information, polling tasks, and reporting billing information. The authorization scope nevertheless includes unrelated capabilities for video, music, speech, and voice creation or modification. The bearer credential is shared across Beatra Skill packages and also includes `wallet:spend`. Consequently, the unnecessary media scopes are not merely informational permissions: they can authorize unrelated billable operations. The bundled client compounds this excessive scope by accepting an ar ...[truncated 1980 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the shared full-scope credential with a package-specific, least-privilege credential. 2. Limit this Skill to the capabilities actually required, such as: - Image generation and image editing. - Explicitly selected asset upload. - Model-card reads. - Task reads and user-requested cancellation. - Necessary wallet balance, ledger, and spending permissions. 3. Remove unrelated video, music, speech, and voice scopes. 4. Separate read-only wallet access from wallet-spending authorization where supported. 5. Add a local allowlist before `tools/call`. Reject every tool not explicitly required by this package, including newly introduced server tools. 6. Consider separate commands or explicit user confirmation for billable calls and task cancellation. 7. Make hostname collection optional, disclose it before authorization, and use a user-provided device label when possible. 8. Add automated tests confirming that unrelated MCP tools are rejected locally even when the remote credential would authorize them. ]]>

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/mcp_client.py:969
Finding
Default silent updater can replace executable code without independent signature verification<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:969-1018`; invocation at `scripts/mcp_client.py:1542-1544` **Vulnerability Type**: Silent remote payload retrieval and local code replacement **Risk Level**: High ### Vulnerable Code The automatic updater is enabled by default, downloads a newer package, and applies it without user confirmation: ```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"] ...[truncated 4374 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Disable automatic installation by default. Make update checks read-only unless the user explicitly approves installation. 2. Sign the release manifest with a dedicated offline or tightly controlled publisher key. 3. Pin the corresponding public key, key identifier, and signature algorithm in the audited package. 4. Verify the detached signature before trusting the version, archive hash, file list, or per-file hashes. 5. Define and secure a key-rotation mechanism, such as signatures from both the old and new keys during rotation. 6. Preserve the existing HTTPS, redirect, archive, destination, ownership, rollback, and downgrade protections as defense in depth. 7. Display the current version, target version, release origin, and security-relevant changes before replacement. 8. Consider requiring re-review or explicit approval when executable files under `scripts/` change. 9. Record a local, non-sensitive update audit log containing the prior version, new version, verified signing-key identifier, and timestamp. 10. Fail closed for signature or trust-chain failures: continue using the current package, but never install an unauthenticated update. ]]>
Vulnerability Patterns
  • 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
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (25)

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill declares no permissions while instructing use of shell execution, local file inspection, uploads, network access, and package updates. This creates a transparency and consent failure: a user selecting an image-board skill would not reasonably expect broad local and network capabilities, increasing the risk of unintended file access, remote data transfer, and code changes.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The documented purpose is generating store launch images, but the skill also introduces credential handling, arbitrary remote MCP tool invocation, local file upload, telemetry/registration, uninstall behavior, and automatic package updates. That mismatch is dangerous because it hides materially broader trust boundaries and operational behavior than the user was told to expect, enabling data exposure and code execution pathways unrelated to the advertised task.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
The skill includes self-updating package installation logic even though its core purpose is creating launch boards and still packs. Any built-in updater that can replace local package files expands the attack surface from content generation to software modification, which can be abused through supply-chain compromise, misconfiguration, or user confusion.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The documentation describes automatic installation registration, platform collection, and persistent identifier handling that go beyond the skill's stated purpose of generating launch boards and image packs. Even if framed as non-billable and best-effort, this is unnecessary telemetry for the declared functionality and creates avoidable privacy and supply-chain trust risk.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The file documents automatic backend communication on first use plus periodic re-registration, which constitutes telemetry unrelated to the creative-production purpose of the skill. This increases privacy exposure and expands the attack surface by introducing remote data transmission and backend dependency into an otherwise local content-production workflow.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The requested OAuth scope is far broader than needed for a skill whose stated purpose is generating launch boards and matching still/image packs. It includes unrelated capabilities such as wallet spending, task access, video/music/speech generation, and voice management, so compromise or misuse of this credential would grant materially more access than the user would reasonably expect.

Context-Inappropriate Capability

Critical
Confidence
94% confidence
Finding
Granting `tasks:read` and `tasks:cancel` gives this skill visibility into and control over broader task activity beyond its stated launch-board workflow. Even if not directly used here, those permissions could leak operational data or let a compromised skill disrupt unrelated user jobs.

Context-Inappropriate Capability

High
Confidence
94% confidence
Finding
Granting `tasks:read` and `tasks:cancel` gives this skill visibility into and control over broader task activity beyond its stated launch-board workflow. Even if not directly used here, those permissions could leak operational data or let a compromised skill disrupt unrelated user jobs.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
Granting `tasks:read` and `tasks:cancel` gives this skill visibility into and control over broader task activity beyond its stated launch-board workflow. Even if not directly used here, those permissions could leak operational data or let a compromised skill disrupt unrelated user jobs.

Context-Inappropriate Capability

Medium
Confidence
84% confidence
Finding
The script detects agent platform characteristics, captures the device hostname, and records a local inventory of installed skills, none of which is clearly necessary for creating launch posters. This expands data collection beyond the advertised purpose and can expose environmental metadata useful for profiling, targeting, or correlation if read by other local processes or later exfiltrated.

Description-Behavior Mismatch

High
Confidence
95% confidence
Finding
The file implements a full remote self-update and installation-management subsystem that can download manifests and archives and replace local package files, behavior unrelated to a creative launch-board skill. Even with checksum and path checks, this materially expands the trust boundary: compromise of the vendor update channel or misuse of this capability can alter executable code on disk without the user invoking a dedicated installer.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The client records local skill inventory, installation references, platform, and registration telemetry on normal use, despite the skill being described as a creative asset generator. This creates unnecessary collection and persistence of local metadata, increasing privacy risk and making the skill behavior less transparent than its stated purpose suggests.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The code fingerprints the host environment from environment variables and host metadata, then propagates that platform value into registration and tool-call attribution. For a launch-board/image-pack skill, that collection is not obviously necessary and can be used to profile execution context or segment users without clear user awareness.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
The CLI supports arbitrary remote MCP tool invocation by passing a caller-supplied tool name and JSON arguments directly to tools/call. That exceeds the narrow purpose of this skill and turns the package into a general remote procedure client, which can expose far more backend functionality than users would expect from a new-item launch studio.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The script contains logic to revoke a shared device authorization and remove shared state under ~/.beatra, which is capability far beyond the skill's declared purpose of generating launch boards and image assets. Even though this is framed as uninstall behavior and includes safety checks, it still grants the package control over credentials and shared cross-skill state, creating an unnecessary trust boundary violation if the script is triggered by an agent or user.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
This code reads device credentials and performs an authenticated POST to revoke the device token, which is account/device authorization management unrelated to a content-creation skill. Such access is dangerous because any compromise, misuse, or unexpected invocation can disconnect other installed skills or interfere with the user's account linkage.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The script unlinks shared files including credentials.json, installation.json, host.json, skills.json, and registrations.json from ~/.beatra. Because these files represent shared platform state rather than package-local artifacts, deleting them from within a single skill risks breaking other skills, erasing inventory, and disrupting recovery or auditability.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill explicitly states that newer versions install automatically without separate confirmation, meaning local executable/package content can change outside a distinct consent event. Even with stated verification, silent code replacement is risky because it weakens user control and makes any upstream compromise or update error far more consequential.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
The document states that the client silently checks for and automatically installs newer releases by default without separate confirmation. Even with integrity checks and rollback protections, unattended modification of local executable/package files increases supply-chain and change-management risk because users may be unaware that code on their system is being replaced.

Missing User Warnings

Low
Confidence
88% confidence
Finding
The documentation notes outbound registration and writes to `~/.beatra/registrations.json` but does not present these side effects as a clear user-facing warning or consent point. Hidden network transmission and local filesystem modification can undermine user expectations, especially for a skill presented as a simple image-production tool.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
Normal command execution invokes maybe_auto_update(), enabling silent package modification before carrying out the requested operation. Silent self-modification is especially risky in a skill whose declared function is unrelated to software maintenance, because it changes local code without an explicit user action at time of change.

Credential Access

High
Category
Privilege Escalation
Content
scope = _required_string(polled, "scope")
            if set(scope.split()) != set(SCOPE.split()):
                raise RuntimeError("Beatra authorization returned an unsupported scope")
            credential_path = state_dir / "credentials.json"
            _atomic_json(
                credential_path,
                {
Confidence
79% confidence
Finding
The script persists a bearer access token with very broad privileges to `credentials.json` in the user's home directory. Although POSIX permissions are tightened, this is still a high-value local secret in plaintext JSON, and theft of that file would expose extensive capabilities including artifact access and, notably, wallet spending.

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
92% confidence
Finding
Referencing credentials.json as part of the uninstall-managed state indicates the skill is aware of and participates in handling shared credentials. In the context of a launch-board generation skill, access to credential material is unnecessary and broadens the damage possible from script execution or later code changes.

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
99% confidence
Finding
The _device_token function reads an access token from ~/.beatra/credentials.json so it can be used for revocation requests. Direct token access by an image/launch-board skill is unjustified and dangerous because bearer tokens are sensitive secrets; any misuse, logging, exfiltration bug, or unintended reuse could affect the user's device authorization across 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
96% confidence
Finding
A self-update feature gives the package the capability to replace its own installed files, which is a high-risk behavior in an end-user skill. In this context, self-modification is especially concerning because the skill's advertised purpose is creative media generation, so code-replacement capability is unexpected and broadens the consequences of any supply-chain or service-side compromise.

Static analysis

No suspicious patterns detected.