Back to skill

Security audit

product-launch-opening-film

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a disclosed Beatra media-generation skill, but it uses broad shared account authority and default-on self-updating behavior that should be reviewed before installation.

Install only if you are comfortable giving Beatra a shared device credential with broad media, wallet, artifact, and task authority, and with this package using Beatra network services and local ~/.beatra state. Review the requested authorization carefully, disable automatic updates with `python3 scripts/mcp_client.py update --auto off` if you want explicit update control, and upload only files you intentionally selected as brand references.

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)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/authorize.py:31
Finding
Overprivileged Shared Device Authorization<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:31-35` **Related Documentation**: `references/installation-and-auth.md:73-74`, `references/mcp-connection.md:9-10` **Vulnerability Type**: Excessive OAuth scope and violation of least privilege **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" ) ``` ### Technical Analysis The Skill’s declared workflow requires image generation, video generation, asset upload, model and task reads, billing reads, and optional task cancellation. However, the device authorization also requests unrelated capabilities: - Music generation - Speech generation - Voice resource reads - Voice resource writes - Broad wallet spending - General MCP tool access These permissions are not necessary to create three still images and one opening-film clip. The documentation also states that this full-scope token is shared among installed Beatra Skills and has a sliding 15-day idle lifetime. The broad authorization substantially increases the consequences of a compromised package, malicious prompt, local process, or other Skill using the same credential. Credential file permissions protect against access by other local users on POSIX systems, but they do not restrict code running as the authorized user. ### Attack Path 1. The user runs `scripts/authorize.py`. 2. The authorization request asks for all permissions in the hardcoded `SCOPE`. 3. Beatra issues a bearer token containing unrelated music, speech, voice, wallet, artifact, and task capabilities. 4. The token is stored in the shared `~/.beatra/credentials.json` file. 5. A compromised Skill process, injected instruction, malicious update, or another process running as the same user invokes an unrelated MCP operation through the shared credential. 6. The remote service acc ...[truncated 715 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the shared full-scope authorization with package-specific, least-privilege credentials. 2. Remove permissions unrelated to this Skill, particularly: - `music:generate` - `speech:generate` - `voices:read` - `voices:write` 3. Replace broad `wallet:spend` access with image- and video-specific spending authorization if the service supports granular scopes. 4. Separate read-only operations from billable and state-changing operations. 5. Avoid sharing one high-privilege token among unrelated Skills. Use per-package credentials or server-enforced package capability policies. 6. Clearly display the requested permissions on the device approval page so the user can make an informed decision. 7. Add automated tests that compare the requested scopes against an explicit list of capabilities required by the declared workflow. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/mcp_client.py:1463
Finding
Unrestricted MCP Tool Dispatch Using a Privileged Bearer Token<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:1463-1481`, `scripts/mcp_client.py:1497-1499` **Vulnerability Type**: Missing local tool allowlist **Risk Level**: High ### Vulnerable Code ```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 client accepts an arbitrary tool name from the command line and forwards it directly to the remote MCP endpoint. There is no local allowlist restricting calls to the tools needed by the Product Launch Opening Film workflow. The bearer token used by the session has broad scopes, including wallet spending, music and speech generation, voice modification, task cancellation, and artifact access. Therefore, the lack of a tool allowlist combines with the overprivileged credential to create a general-purpose authenticated MCP dispatcher. The instructions in `SKILL.md` recommend particular Beatra tools, but documentation is not an enforceable security boundary. A malicious or prompt-injected instruction can call a different tool directly if it is exposed by the server and authorized by the bearer token. ### Attack Path 1. The Skill has an active broad-s ...[truncated 1087 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Implement a strict local allowlist of tools required by this Skill, such as: - `beatra.models.list` - `beatra.images.generate` - `beatra.videos.generate` - `beatra.videos.generate_from_references` - `beatra.assets.upload` - `beatra.tasks.get` - `beatra.tasks.list` - `beatra.tasks.cancel` - Required read-only wallet operations - Installation registration 2. Reject unknown tool names before initializing an authenticated session. 3. Maintain separate allowlists for read-only, billable, upload, and cancellation operations. 4. Require explicit user confirmation for billable or state-changing operations, independent of prompt instructions. 5. Enforce the same package-specific tool restrictions on the server; a local allowlist alone is not sufficient against modified clients. 6. Couple each credential to a server-side package identity and permitted tool set. 7. Add tests proving that unrelated and newly introduced MCP tool names are rejected by default. ]]>

T03 · Remote Payload Retrieval and Execution

Warning
Location
scripts/mcp_client.py:969
Finding
Default-On Silent Retrieval and Installation of Remote Executable Code<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:515-522`, `scripts/mcp_client.py:969-1021`, `scripts/mcp_client.py:1541-1544` **Related Documentation**: `SKILL.md:218-236`, `references/automatic-updates-and-safety.md:3-19` **Vulnerability Type**: Automatic remote payload retrieval and code replacement **Risk Level**: Medium ### Vulnerable Code The updater defaults to enabled when update state is missing or invalid: ```python def _read_update_state(update_home: Path) -> dict[str, Any]: path = update_home / "state.json" try: value = json.loads(path.read_text(encoding="utf-8")) except (OSError, json.JSONDecodeError): return {"schema_version": 1, "auto_update": True} if not isinstance(value, dict) or value.get("schema_version") != 1: return {"schema_version": 1, "auto_update": True} return value ``` Ordinary commands trigger the silent updater: ```python else: maybe_auto_update() ``` When a newer version is found, remote package files are downloaded and written into the installation: ```python 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) _apply_update( install_root=resolved_root, update_home=update_home, discovery=discovery, manifest=manifest, new_files=new_files, ) return True ``` ### Technical Analysis Before ordinary Beatra commands, the client checks for updates and silently installs a higher version without separate confirmation. The replacement can include executa ...[truncated 2473 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Disable automatic installation by default. Update checks may remain optional, but code replacement should require explicit informed user approval. 2. Verify update metadata and archives using a pinned offline publisher public key rather than relying only on hashes supplied through the update service. 3. Consider a threshold-signature or transparency-log design so compromise of one publishing component is insufficient to authorize executable code. 4. Display the current version, target version, source, and changed files before installation. 5. Preserve a user-selected disabled state even if the update state file is malformed; invalid state should fail closed rather than reverting to automatic updates. 6. Prefer updates delivered through the host’s trusted package or Skill management mechanism instead of a self-modifying runtime client. 7. Keep the existing path, size, ownership, rollback, and redirect protections as defense-in-depth. 8. Record verifiable update provenance and expose an audit command that confirms the installed files match a signed release manifest. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (17)

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill exposes powerful capabilities including shell, file access, environment access, and network operations, yet it declares no permissions. That mismatch prevents informed consent and makes it easier for a user or host to invoke a package that can read local files, store state, and contact remote services without clear visibility into its privileges.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill is presented as a content-generation workflow, but it also performs credential handling, persistent state management, local file upload, telemetry/registration, arbitrary MCP client use, uninstall/token revocation flows, and automatic updates. This broad hidden behavior materially expands the trust boundary and attack surface beyond what a user would reasonably expect from a launch-film skill.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The skill includes a self-updating installation mechanism unrelated to its core purpose of generating stills and films. Any self-update path that downloads and replaces local package files increases supply-chain risk and can be abused to introduce unexpected code changes on the host system.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
The authorization helper fingerprints the host platform, captures the device hostname, and records a local inventory of installed skill paths, even though the skill is presented as a product-launch film generator. That data collection exceeds what is reasonably necessary for the advertised function, creating unnecessary privacy and trust risk and expanding the blast radius if the local state is later exposed.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The requested OAuth scope is far broader than the skill's stated purpose, including wallet spending plus image, video, music, speech, and voice permissions. For a film-opening skill, this violates least privilege and could let the skill or any compromise of its token perform unrelated paid actions and access capabilities the user would not expect.

Description-Behavior Mismatch

High
Confidence
95% confidence
Finding
This client can silently fetch remote manifests and archives, validate them, and replace files in its own installation tree, which is unrelated to the skill’s stated product-launch film purpose. Even with integrity checks, any compromise of the update source, signing pipeline, or package publisher enables code modification on the user’s machine and materially expands the trust boundary.

Description-Behavior Mismatch

Medium
Confidence
89% confidence
Finding
The code records local skill inventory and sends installation registration telemetry, including package identity, install path, platform, and external installation reference, none of which are necessary for generating launch-film content. This broadens data collection and creates privacy and tracking risk, especially because it runs best-effort on normal use paths rather than as an explicit opt-in workflow.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
The skill fingerprints the host environment via environment variables and a local host.json file to derive a platform label, which is not justified by the described creative function. Environment fingerprinting increases privacy exposure and can aid downstream targeting or behavioral differentiation across agent environments.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The client exposes a general local file upload primitive that reads an arbitrary user-specified file path and uploads its bytes after obtaining a remote grant. For a film-opening skill, broad filesystem upload capability exceeds the stated purpose and could be abused to exfiltrate sensitive local files if a caller or surrounding workflow passes attacker-chosen paths.

Description-Behavior Mismatch

High
Confidence
96% confidence
Finding
This skill is advertised as generating product-launch visuals, but the file contains uninstall logic that manages shared device authorization and can revoke a remote OAuth device token. That is a privileged capability unrelated to the stated purpose, which increases the chance of hidden or unnecessary access to shared credentials and can disrupt other installed skills if invoked unexpectedly.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
The code performs a POST to a revocation endpoint using a bearer token from shared local state and later deletes files in ~/.beatra, including credential-related state. In the context of a media-generation skill, this is overprivileged behavior that can cause denial of service against the user's broader Beatra environment and unnecessarily exposes credential-handling code in an unrelated package.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The package states that newer versions install automatically without separate confirmation. Silent modification of local executable/package files is dangerous because it bypasses user review, can change runtime behavior unexpectedly, and magnifies the impact of any compromise in the update pipeline.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The document states that the client silently checks for and automatically installs newer releases without separate confirmation, which can change local installation state unexpectedly. Even though the text describes integrity checks and rollback protections, automatic file replacement without an explicit up-front warning or opt-in increases supply-chain and operational risk because users may not realize their installed code can change before normal command execution.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
maybe_auto_update() performs silent best-effort update checks and package replacement during ordinary command execution without a user-facing warning at runtime. Silent code changes reduce user agency and make it harder to detect unwanted behavior, especially in an agent skill whose expected role is content generation rather than software maintenance.

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
88% confidence
Finding
Referencing credentials.json as part of a skill package indicates the skill is aware of and participates in handling shared credential material. Even though this instance appears aimed at cleanup rather than exfiltration, unnecessary credential access expands attack surface and is unjustified for a product-launch film skill.

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
This function reads an access token from credentials.json and uses it for remote revocation logic. Direct access to bearer tokens inside an unrelated creative-content skill creates unnecessary exposure of sensitive authentication material and enables actions against the user's shared device authorization.

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 capability enables the skill to modify its own installation files, which is a powerful persistence and code-execution primitive outside the normal expectations of a product-launch film tool. In this skill context, self-modification is especially risky because the capability is operationally unrelated to the advertised creative workflow and can change future behavior without separate installation review.

Static analysis

No suspicious patterns detected.