Back to skill

Security audit

Restock Talking Clips

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent restock-video workflow, but it stores a broad Beatra token and silently self-updates executable package code, so users should review it carefully before installing.

Install only if you are comfortable giving this package a shared Beatra device token with paid-generation and wallet-spend authority, selected-media upload capability, local ~/.beatra state, and default silent package updates. Consider disabling automatic updates with scripts/mcp_client.py update --auto off and using a dedicated Beatra account or credential scope if available.

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
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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
Findings (6)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/mcp_client.py:969
Finding
Default Silent Updates Permit Remote Replacement of Executable Skill Code<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:969-1021` **Additional Locations**: `scripts/mcp_client.py:31-32, 334-357, 469-491, 801-920`; `SKILL.md:222-234` **Vulnerability Type**: Remote payload retrieval and execution without independent publisher authentication **Risk Level**: High ### 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_ ...[truncated 2889 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Disable silent automatic replacement by default and require explicit user approval before installing a new version. 2. Sign each release manifest with a dedicated offline package-signing key. 3. Embed or securely provision the corresponding public key in the reviewed client and reject unsigned or incorrectly signed releases. 4. Bind the signature to the package slug, channel, locale, version, complete file list, file hashes, and archive hash. 5. Consider a transparency log or reproducible-build metadata so unauthorized publication can be detected. 6. Keep the existing path, downgrade, archive, size, lock, rollback, and ownership checks as defense-in-depth. 7. Surface update success and the installed version to the user instead of performing replacement silently. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/authorize.py:35
Finding
Device Authorization Requests Capabilities Beyond the Declared Workflow<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:35-39` **Vulnerability Type**: Excessive OAuth authorization scope **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 declared Skill workflow requires artifact upload, voice operations, speech generation, image-to-video generation, model discovery, task inspection or cancellation, and billing-related operations. It does not declare a need to generate standalone images or music. Nevertheless, the authorization requests `images:generate` and `music:generate`, along with a generic `mcp:tools` capability and wallet-spending access. The resulting token is described as shared across installed Beatra Skills, increasing the blast radius beyond this package. This violates least privilege because a restock talking-clip workflow can operate without unrelated image-generation and music-generation authority. ### Attack Path 1. The user runs `scripts/authorize.py` for the restock talking-clip Skill. 2. The device authorization requests the complete hardcoded scope set. 3. The user approves the authorization, and the broad bearer token is stored in `~/.beatra/credentials.json`. 4. A compromised Skill, another Skill sharing the credential, or an unintended MCP tool invocation uses unrelated generation scopes. 5. The account incurs unauthorized operations or credit expenditure outside the restock-clip workflow. ### Impact Assessment The bearer credential can authorize more capabilities than this Skill legitimately requires. Misuse may create unrelated paid image or music generation tasks and consume account credits. Because the token is shared, compromise of one participating Skill can affect the authority available to all Skills using the same connection. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `images:generate` and `music:generate` unless a documented restock-clip requirement is introduced. 2. Replace generic tool authority with an allowlisted package-specific scope where the service supports it. 3. Issue separate least-privilege credentials per Skill rather than sharing a full-scope device token across unrelated packages. 4. Separate read-only model, task, wallet, and artifact permissions from billable generation permissions. 5. Present the exact requested capabilities during approval and identify which ones can spend credits. 6. Add automated tests that compare declared workflow operations against requested authorization scopes. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/mcp_client.py:1463
Finding
Generic Tool Dispatcher Does Not Restrict Calls to Declared Beatra Operations<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:1463-1481` **Vulnerability Type**: Unrestricted remote tool dispatch using a broad bearer credential **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}, ) ``` The command parser accepts an arbitrary tool name: ```python call = subparsers.add_parser("call", help="Call one tool with a JSON object on stdin") call.add_argument("tool_name") ``` ### Technical Analysis The bundled client forwards any caller-supplied tool name to `tools/call`. It does not enforce an allowlist corresponding to the operations described in `SKILL.md`. Server-side authorization may reject some tools, but the client uses a broad device token with generic MCP and wallet-spending authority. Therefore, any tool exposed by the server and accepted under that credential may be invoked, including tools unrelated to restock talking clips. This weakens the intended security boundary between a narrowly declared Skill and a general-purpose account client. ### Attack Path 1. An attacker-controlled instruction or agent error supplies an unrelated MCP tool name to `scripts/mcp_client.py call`. 2. The client reads attacker-influenced JSON arguments from standard input. 3. `_run_command()` forwards t ...[truncated 692 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Add a fixed allowlist containing only the Beatra tools required by this Skill. 2. Reject unknown tool names before creating an authenticated session. 3. Split read-only and billable commands into separate explicit subcommands. 4. Require an explicit confirmation token or approved operation record before forwarding billable calls. 5. Validate input arguments locally against per-tool schemas where feasible. 6. Narrow the server-side OAuth scopes so client-side validation is not the sole control. 7. Log only non-sensitive operation identifiers and never log tool payloads containing private media or prompts. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/mcp_client.py:231
Finding
Media Upload Grants Permit Arbitrary HTTPS Destination Hosts<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:231-265` **Vulnerability Type**: Insufficient destination validation for sensitive file uploads **Risk Level**: High ### Vulnerable Code ```python def _complete_upload( result: dict[str, Any], *, mime_type: str, content: bytes, put_bytes: PutBytes, ) -> dict[str, str]: structured = result.get("structuredContent") instruction = structured.get("upload") if isinstance(structured, dict) else None if not isinstance(instruction, dict) or instruction.get("method") != "PUT": raise RuntimeError("Beatra upload instructions are invalid") url = instruction.get("url") headers = instruction.get("headers") if not isinstance(url, str) or not isinstance(headers, dict): raise RuntimeError("Beatra upload instructions are invalid") parsed = urllib.parse.urlsplit(url) if ( parsed.scheme != "https" or not parsed.hostname or parsed.username is not None or parsed.password is not None or parsed.fragment ): raise RuntimeError("Beatra upload instructions are invalid") if not all(isinstance(key, str) and isinstance(value, str) for key, value in headers.items()): raise RuntimeError("Beatra upload instructions are invalid") content_type = _header_value(headers, "Content-Type") content_length = _header_value(headers, "Content-Length") if content_type != mime_type or content_length != str(len(content)): raise RuntimeError("Beatra upload instructions are invalid") response = put_bytes(url, dict(headers), content) artifact_id = response.get("artifact_id") if not isinstance(artifact_id, str) or not artifact_id: raise RuntimeError("Beatra upload returned an invalid response") return {"type": "artifact", "artifact_id": artifact_id} ``` ### Technical Analysis The function requires HTTPS and rejects credentials or fragments in the URL, but it accep ...[truncated 1471 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Define and enforce an exact allowlist of approved Beatra storage hosts or narrowly scoped domain suffixes. 2. Reject IP-literal hosts, unexpected ports, nonstandard schemes, and Unicode hostname ambiguities. 3. Resolve and validate the normalized hostname before upload where infrastructure permits. 4. Ensure upload authorization headers are limited to the expected set and reject dangerous or unnecessary headers. 5. Bind the server's upload instruction cryptographically to the artifact grant, expected host, MIME type, byte length, and expiration. 6. Document the approved storage providers and disclose that selected media will be uploaded to them. 7. Preserve redirect rejection and regular-file, size, stability, and content-length checks. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/mcp_client.py:1044
Finding
Windows Credential Privacy Is Assumed Without ACL Enforcement or Verification<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:1044-1082` **Additional Location**: `scripts/authorize.py:116-130` **Vulnerability Type**: Inadequate local access control for bearer credentials on Windows **Risk Level**: Medium ### Vulnerable Code ```python def _read_private_credentials(state_dir: Path, path: Path) -> str: if os.name == "nt": # The state directory lives under the user profile, whose default # ACL is already private to the user (the gh/aws/gcloud posture). # The former custom DACL verification was dropped deliberately: its # command patterns read as hostile to agent safety policies and # endpoint security, failing installs while adding nothing an # elevated administrator could not bypass. return path.read_text(encoding="utf-8") if os.name != "posix": raise RuntimeError("Beatra credential permissions are unsupported on this platform") try: directory_stat = os.lstat(state_dir) if ( not stat.S_ISDIR(directory_stat.st_mode) or stat.S_IMODE(directory_stat.st_mode) != 0o700 or directory_stat.st_uid != os.getuid() ): raise RuntimeError("Beatra credential permissions are unsafe; authorize again") flags = os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0) descriptor = os.open(path, flags) try: file_stat = os.fstat(descriptor) if ( not stat.S_ISREG(file_stat.st_mode) or stat.S_IMODE(file_stat.st_mode) != 0o600 or file_stat.st_uid != os.getuid() ): raise RuntimeError("Beatra credential permissions are unsafe; authorize again") with os.fdopen(descriptor, encoding="utf-8") as handle: descriptor = -1 return handle.read() finally: if descriptor >= 0: os.close(descriptor) except RuntimeEr ...[truncated 1828 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create `~/.beatra` and `credentials.json` with an explicit ACL granting access only to the current user and required system administrators. 2. Disable inheritance on the credential file where appropriate. 3. Verify the effective owner and ACL before every credential read. 4. Reject credentials readable by broad groups such as `Users`, `Authenticated Users`, or `Everyone`. 5. Use Windows security APIs directly rather than shelling out to permission-management commands. 6. Store the token in Windows Credential Manager or DPAPI-protected storage where practical. 7. Preserve the existing POSIX ownership, mode, regular-file, and no-follow protections. ]]>

other

Note
Location
scripts/authorize.py:358
Finding
Authorization Transmits Hostname and Stable Environment Fingerprints Beyond Core Generation Needs<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:358-370` **Additional Locations**: `scripts/authorize.py:338-356, 420-447`; `scripts/mcp_client.py:1139-1167, 1209-1218, 1354-1397` **Vulnerability Type**: Environment fingerprinting and installation telemetry **Risk Level**: Low ### Vulnerable Code ```python 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] ``` The value is added to the authorization request: ```python form: dict[str, str] = { "client_id": CLIENT_ID, "resource": MCP_URL, "scope": SCOPE, "platform": host_platform, "client_name": PACKAGE_DISPLAY_NAME, "external_installation_ref": external_reference, "package_version": PACKAGE_VERSION, "package_slug": PACKAGE_SLUG, } if device_name: form["device_name"] = device_name status, created = post_form(DEVICE_AUTHORIZATION_URL, form) ``` The client also appends source telemetry to business calls: ```python arguments.setdefault("source_package_slug", PACKAGE_SLUG) arguments.setdefault("source_platform", host_platform()) ``` ### Technical Analysis The code reads environment signatures to identify the agent platform and obtains the local hostname. During authorization, it sends the platform, package identity, package version, stable external installation reference, and hostname to Beatra. Subsequent registration and business calls continue to send package and platform attribution. The platform and package telemetry are documented in the installation-registration reference. The hostname is useful as a device-list label, but it is not required to authenticate the device or generate restock clips. Hostnames frequently reveal a person's name, employer, department, asset number, role, or internal naming co ...[truncated 1086 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not collect or transmit the operating-system hostname by default. 2. Generate a random, non-identifying device label or ask the user to provide an optional display name. 3. Obtain explicit consent before transmitting hostname or detailed environment metadata. 4. Clearly disclose every transmitted telemetry field and its retention purpose. 5. Permit users to disable package and platform attribution without blocking core media generation. 6. Rotate or scope the stable installation reference where long-term cross-package correlation is unnecessary. 7. Continue avoiding broader reconnaissance such as IP-address, interface, user, process, or network enumeration. ]]>
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 (19)

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill exercises broad capabilities including shell, network, file read/write, and environment access, yet it declares no permissions up front. That creates a transparency and consent failure: users may invoke a seemingly narrow media-generation skill without realizing it can access local files, persist state, and perform remote operations. In this context the risk is amplified because the skill also handles uploads, credentials, and package updates, so under-declared capabilities materially increase surprise and misuse potential.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared skill purpose is limited to generating restock talking clips, but the documented behavior also includes OAuth/device login, persistent credential storage, arbitrary authenticated MCP tool calling, telemetry/registration, remote uploads, uninstall/revocation flows, and self-updating package replacement. This is a significant description-behavior mismatch that undermines informed consent and broadens the attack surface far beyond media creation; notably, 'arbitrary tool listing/calling' and in-place updates introduce powerful capabilities users would not reasonably expect from the description alone.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
This documentation introduces an auto-updating client mechanism that is unrelated to the declared purpose of the skill, which is generating restock talking clips. Capability drift like this is dangerous because it normalizes software installation and file replacement behavior in a context where users would not expect system-modifying operations, increasing the risk of hidden supply-chain or unauthorized update activity.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The file describes silent default update checks and automatic installation/package replacement, which are unjustified for a media-generation skill. Even if framed as 'safe,' silent self-modifying behavior creates a supply-chain risk and can be abused to introduce new code or alter client behavior without informed user consent.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The authorization helper collects host platform and device hostname and persists them locally even though the skill is presented as a clip-generation tool. That is a scope expansion beyond the stated purpose and increases privacy exposure by tying media-generation activity to a specific device and agent environment without clear necessity or disclosure.

Context-Inappropriate Capability

Medium
Confidence
97% confidence
Finding
The code maintains a persistent local inventory of installed skills and absolute install paths in ~/.beatra/skills.json, which is unrelated to the advertised restock clip function. This creates unnecessary tracking of user environment details and software usage that could expose sensitive filesystem layout and tool inventory to other local processes or future components.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The requested OAuth scope is far broader than the skill's stated purpose of generating talking restock clips, including wallet spending, music generation, voice management, artifact read/write, and task control. Overbroad authorization violates least privilege and, if the credential is misused or stolen, enables actions well beyond video creation, including account spending and access to unrelated resources.

Description-Behavior Mismatch

Medium
Confidence
92% confidence
Finding
This client embeds substantial functionality unrelated to generating restock talking clips, including package discovery, download, installation, rollback, lock management, telemetry, and registration. Expanding a creative skill into a package manager materially increases attack surface and creates a path for remote code changes that are outside the skill's stated purpose.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
The code fingerprints the host agent environment by inspecting environment variables and local host metadata, then uses that value in outbound requests. While not directly exploitable on its own, this collects and transmits host-identifying information unrelated to clip generation, increasing privacy risk and enabling environment-specific targeting if the backend or update channel is compromised.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The client persistently records a local inventory of installed skills and sends installation registration telemetry to a remote service, despite this being unrelated to restock clip generation. This broadens local surveillance and remote tracking capabilities, and in combination with host-platform detection creates an unnecessary inventorying mechanism that could aid profiling or targeted abuse.

Description-Behavior Mismatch

Medium
Confidence
89% confidence
Finding
The uninstall script performs shared credential and device-authorization management, which is materially broader than the skill’s advertised purpose of generating talking restock clips. Even if framed as cleanup logic, handling shared auth state introduces a privileged control path that could disable other installed skills or alter device access outside user expectations.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
This code can make an authenticated HTTP POST to revoke device authorization, a sensitive remote action unrelated to the stated media-generation functionality. Because it uses a bearer token from local state, compromise or misuse of this path could remotely disconnect the device and impact other skills sharing the same authorization.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The skill states that the bundled client silently installs newer releases automatically without separate confirmation, yet this system-modifying behavior is not prominently disclosed in the main skill description. Silent in-place replacement of package files increases supply-chain and integrity risk because future code can change behavior after initial trust, and users are not given a clear up-front chance to consent to or disable that behavior before use.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The markdown states that update checks are silent, enabled by default, and can automatically install newer versions without separate confirmation. That is dangerous because users are not clearly warned that invoking ordinary commands may trigger system modifications, undermining consent and making unexpected code changes harder to detect.

Missing User Warnings

Low
Confidence
83% confidence
Finding
The skill writes host configuration data to disk as a best-effort side effect without informing the user. While the data is limited, undisclosed persistence of environment metadata undermines transparency and can contribute to privacy issues when combined with other collected state.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill performs automatic silent self-updates that can replace installed package files without a user-facing warning at execution time. Even with integrity checks, this is a dangerous capability in a content-generation skill because it permits remote code changes on the host, expanding the consequences of any compromise of the vendor, CDN, manifest pipeline, or signing/distribution process.

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
87% confidence
Finding
The code stores a bearer access token for a highly privileged scope set in a plaintext JSON file on disk. Even with restrictive filesystem permissions, compromise of the user account, backups, logs, or local malware could expose a reusable token that grants broad access including wallet spending and unrelated Beatra capabilities.

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
90% confidence
Finding
The function reads an access token from credentials.json and later uses it to perform remote revocation. Accessing bearer tokens inside a content-generation skill is dangerous because it grants the skill control over shared device authorization, extending its privileges beyond its declared purpose.

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 skill client that can self-modify is inherently high risk because it can change its future behavior after installation, outside the narrow media-generation purpose described to the user. In the context of an agent skill, this is especially dangerous because the client also has access to local state and credentials, so a compromised update path could turn a benign integration into credential abuse, telemetry expansion, or arbitrary backend-directed behavior.

Static analysis

No suspicious patterns detected.