Back to skill

Security audit

Market Inspection Talking Clips

Security checks for vulnerabilities and agentic risk

Overview

The skill performs the advertised talking-clip workflow, but it also stores a broad Beatra token and silently self-updates executable package files, so it should be reviewed before installation.

Install only if you are comfortable granting Beatra a persistent, broad device authorization, letting this package silently update its own files by default, and sending limited device/agent metadata. Before use, consider disabling auto-updates with the provided command and confirm that paid operations and task cancellations are only run after explicit user approval.

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 (4)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/mcp_client.py:969
Finding
Default-Enabled Silent Remote Replacement of Executable Skill Files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:31-32, 520-522, 801-919, 969-1020, 1542-1544`; `SKILL.md:225-238` **Vulnerability Type**: Remote payload retrieval and execution **Risk Level**: High ### Complete Code Snippet ```python PACKAGE_DISCOVERY_URL = "https://beatra.ai/skills/market-inspect-talking/channels/clawhub/install.json" PACKAGE_CDN_BASE_TEMPLATE = "https://cdn.beatra.ai/agent-packages/market-inspect-talking/channels/clawhub/v{version}" ``` ```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 ``` ```python for relative in ordered_new: destination = destinations[relative] _copy_to_destination( new_files[relative], destination, temporary=_transaction_temporary(destination, transaction_nonce), ) ``` ```python else: maybe_auto_update() ``` ### Technical Analysis The bundled MCP client checks for updates before ordinary MCP operations, with automatic updates enabled whenever update state is missing or invalid. A newer remote release can replace package-owned files, including Python scripts and `SKILL.md`, without per-update user approval. Updated Python code executes on a subsequent client invocation. The updater implements meaningful safeguards, including HTTPS, fixed hostnames, redirect rejection, version-downgrade prevention, archive size limits, path validation, per-file SHA-256 verification, ownership checks, transactional replacement, and rollback. These controls protect against corruption and some archive attacks. However, the checksums are supplied through remote discovery metadata controlled by the ...[truncated 2023 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Disable automatic updates by default and require an explicit, informed user action before installing a release. 2. Authenticate releases with an offline signing key whose public key is pinned in the audited client. Verify the signature over the package name, channel, locale, version, complete manifest, and archive digest. 3. Keep transport security and SHA-256 checks, but do not treat publisher-provided checksums alone as independent authenticity verification. 4. Display the current version, target version, changed files, release signature identity, and package digest before installation. 5. Consider delegating updates to the trusted Skill/package manager instead of allowing the Skill to replace its own executable files. 6. Preserve downgrade prevention, path traversal defenses, file ownership checks, size limits, transactional replacement, and rollback. 7. If unattended updates are operationally required, make them an explicit opt-in and support pinning to a specific version or trusted signing key. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/authorize.py:34
Finding
Excessive OAuth Scope Combined with Unrestricted MCP Tool Forwarding<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:34-37`; `scripts/mcp_client.py:1462-1483, 1500-1502` **Vulnerability Type**: Excessive authorization and missing tool allowlist **Risk Level**: High ### Complete Code Snippet ```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" ) ``` ```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 Skill workflow requires asset upload, model and voice discovery, optional voice cloning, speech synthesis, image-to-video generation, task inspection, limited wallet operations, and user-requested task cancellation. The authorization scope additionally grants image generation and music generation, which are unrelated to producing merchant-notice talking clips from existing stills. The client then accepts an arbitrary `tool_name` from the command line and forwards it to the remote MCP server with the shared bearer token. It does not enforce a package-specific allowlist. Server-side authorization remains a ...[truncated 1671 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Request only the scopes required for this package: - Asset upload/read. - Model and voice discovery. - Optional voice cloning. - Speech synthesis. - Image-to-video generation. - Task reads. - Narrow wallet reads and spending only when required. 2. Remove unrelated image-generation and music-generation permissions. 3. Separate read-only access from spending and destructive permissions. 4. Use a package-specific credential rather than a shared full-scope device credential where supported. 5. Add a strict local allowlist for the exact documented tools, such as: - `beatra.assets.upload` - `beatra.models.list` - `beatra.voices.list` - `beatra.voices.clone` - `beatra.speech.synthesize` - `beatra.videos.animate` - `beatra.tasks.get` - `beatra.tasks.list` - `beatra.tasks.cancel` - `beatra.wallet.get` - `beatra.wallet.ledger` - `beatra.installations.register` 6. Reject unknown tool names before constructing an authenticated request. 7. Require explicit user confirmation for every billable operation and task cancellation. 8. Enforce equivalent package-level tool restrictions on the server, since local controls can be modified. ]]>

other

Warning
Location
scripts/authorize.py:341
Finding
Collection and Transmission of Hostname and Agent-Environment Telemetry<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:341-368, 400-406, 468-475`; `scripts/mcp_client.py:1140-1167, 1219-1230, 1354-1380` **Vulnerability Type**: Device-identifying telemetry beyond minimum functional requirements **Risk Level**: Medium ### Complete Code Snippet ```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] ``` ```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) ``` ```python if method == "tools/call": arguments = params ...[truncated 2419 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not collect or transmit the hostname by default. 2. Use a generic label such as “Beatra Skill Device” or a random non-identifying installation identifier. 3. If a recognizable device name is desired, request explicit user consent and allow the user to review or edit the value. 4. Clearly disclose every transmitted telemetry field before authorization. 5. Provide a no-telemetry option that omits hostname, Agent platform, and source attribution unless technically required. 6. Minimize local persistence and avoid storing the hostname in `host.json` when only a random installation reference is needed. 7. Define retention and deletion policies for device metadata and expose them in the privacy documentation. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/mcp_client.py:1044
Finding
Windows Bearer-Token File Permissions Are Assumed Rather Than Enforced<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:118-135`; `scripts/mcp_client.py:1044-1052` **Vulnerability Type**: Insufficient credential-file access-control validation **Risk Level**: Medium ### Complete Code Snippet ```python def _private_directory(path: Path) -> None: # POSIX gets explicit 700/600. On Windows the state directory lives under # the user profile, whose default ACL is already private to the user — # the same posture as gh/aws/gcloud credential stores. The former custom # DACL ceremony was dropped deliberately: its command patterns read as # hostile to agent safety policies and endpoint security, failing installs # while adding no protection an elevated administrator could not bypass. path.mkdir(mode=0o700, parents=True, exist_ok=True) if os.name == "posix": path.chmod(0o700) def _restrict_file(path: Path) -> None: if os.name == "posix": path.chmod(0o600) ``` ```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") ``` ### Technical Analysis On POSIX systems, the client validates that the state directory is owned by the current user with mode `0700` and that the credential is a regular, current-user-owned file with mode `0600`. It also uses `O_NOFOLLOW` where supported. On Windows, the implementation merely assumes that files under the user profile inherit a private ACL. It neither creates a current-user-only discretionary access control list nor verifies the ...[truncated 1535 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Store the bearer token in Windows Credential Manager or protect it with DPAPI for the current user. 2. If a file must be used, create the directory and credential file with an explicit current-user-only DACL. 3. Before reading the credential, validate: - File owner. - Inherited and explicit access-control entries. - Absence of write or read access for unintended users and broad groups. - That the path is a regular file and not a reparse-point redirection. 4. Fail closed with a clear remediation message when access controls are unsafe. 5. Apply equivalent protection to temporary credential files before atomic replacement. 6. Add automated tests covering permissive ACL inheritance, redirected profiles, and credential files created on nonstandard filesystems. 7. Reduce the credential scope so that local disclosure has a smaller financial and operational impact. ]]>
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 (22)

Lp3

Medium
Category
MCP Least Privilege
Confidence
97% confidence
Finding
The skill declares a narrow media-generation purpose, yet its instructions require broad capabilities including shell execution, file access, network access, environment use, and local file writes without declaring them. This mismatch weakens user and platform trust boundaries because the skill can access sensitive local state, upload files, and invoke remote operations far beyond what a simple clip-generation skill description suggests.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The documented behavior materially exceeds the advertised function: besides creating talking clips, it performs authentication, persistent credential storage, arbitrary MCP tool invocation, file upload, telemetry/registration, uninstall-side revocation, and package update management. Users expecting a simple content workflow may unknowingly grant a much more privileged integration that can alter local state and transmit data externally.

Context-Inappropriate Capability

Medium
Confidence
98% confidence
Finding
The skill includes a self-updating mechanism that can automatically download and install a newer release without separate confirmation. Even with signature and manifest verification claims, auto-update introduces supply-chain and system-integrity risk because package-owned files are modified on the host outside the core user task of generating merchant-notice videos.

Description-Behavior Mismatch

High
Confidence
94% confidence
Finding
This file documents a self-updating client that is unrelated to the stated purpose of generating merchant inspection talking clips from user-supplied notices and stills. In a skill context, bundling or documenting unrelated update/install behavior expands the trust boundary and can enable unexpected code changes on the user's system, making the mismatch itself a significant security concern.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
The markdown explicitly states that the client silently checks for and automatically installs higher versions by default without separate confirmation. For a media-creation skill, this creates an unjustified mechanism for modifying local software outside the user's immediate task, increasing the risk of supply-chain compromise, unexpected behavior changes, or persistence on the host.

Description-Behavior Mismatch

Medium
Confidence
92% confidence
Finding
The document describes automatic installation registration that sends package slug, version, platform, and a stable external installation reference on first use. Although framed as non-billable and non-secret, this is telemetry-like behavior unrelated to the skill's stated purpose of generating merchant inspection talking clips, and a stable installation identifier can enable cross-session tracking or unexpected disclosure in environments where users do not expect outbound registration.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The authorization scope is far broader than the skill’s stated purpose of producing talking clips from user-supplied images and notices. Requesting wallet spending, music generation, voice write, task control, and broad artifact access violates least privilege and turns any compromise or misuse of the skill into a much higher-impact account takeover of adjacent capabilities.

Context-Inappropriate Capability

Medium
Confidence
84% confidence
Finding
The code detects agent platform and captures a recognizable hostname for persistence in host.json and inclusion in authorization requests. For a simple media clip skill, this creates unnecessary device-identifying telemetry that can support tracking, correlation across installs, or privacy loss without being clearly needed for the advertised function.

Context-Inappropriate Capability

Low
Confidence
72% confidence
Finding
Recording a local inventory of installed skills extends data collection beyond the clip-generation purpose and creates a local behavioral/profile artifact. While primarily a privacy and over-collection issue rather than direct code execution risk, it can expose user tooling history if the local state directory is later accessed by other software or an attacker.

Description-Behavior Mismatch

High
Confidence
94% confidence
Finding
The client implements a full self-update subsystem with remote discovery, download, validation, rollback, and on-start automatic installation, which is materially broader than the declared purpose of generating talking clips from merchant notices and stills. Even though the updater includes several integrity checks, embedding a package-mutating mechanism inside a media skill expands the trust boundary and enables remote code changes after installation, making the skill far more dangerous if the update channel or publisher is ever compromised.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The code records local skill inventory and installation telemetry unrelated to the manifest's stated media-generation function, including install path, platform, timestamps, and external installation reference. This creates unnecessary collection and persistence of operational metadata, increasing privacy and tracking risk and broadening the consequences if the endpoint or local state is later compromised.

Context-Inappropriate Capability

Medium
Confidence
87% confidence
Finding
The skill inspects environment variables and local host state to infer the agent platform, then attaches and persists that attribution in requests and registration data. This is beyond the core media task and can facilitate environment fingerprinting, cross-install correlation, and leakage of execution-context details to a remote service.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
This script contains uninstall-time logic for managing and potentially revoking a shared Beatra device authorization, which is unrelated to the advertised purpose of generating merchant inspection talking clips. Even if framed as cleanup, access to shared authorization state creates a powerful side effect: removing or disrupting connectivity for other installed skills on the device.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The code performs remote authorization revocation by sending the bearer token to a revocation endpoint, a capability unrelated to the skill’s stated video-creation function. If triggered inappropriately, it can disconnect the device from the service and disrupt all skills relying on the shared connection, making it a high-risk control surface.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The script enumerates and deletes files in a shared ~/.beatra state directory, including credentials and installation metadata used across skills. Although the code tries to preserve shared state when other skills remain, a bug, corrupted inventory, or adversarial invocation could still remove shared local state and break unrelated functionality.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The skill states that updates install automatically without separate confirmation, but that system-changing behavior is not clearly disclosed in the top-level description. Hidden or under-disclosed software modification is dangerous because users may invoke a content-processing skill without realizing it can change local package files and behavior over time.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The document says automatic installation is 'silent and enabled by default' and that newer versions are installed 'without separate confirmation,' which means users may not realize files on their system are being replaced. Even if verification controls exist, the lack of prominent warning and consent undermines user control and can conceal security-relevant changes.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The helper stores a token carrying expansive privileges but does not clearly warn the user that approving this flow grants access well beyond making talking clips. Users are therefore likely to consent without understanding that the token could authorize spending and unrelated content-generation actions if abused.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The maybe_auto_update() path performs silent best-effort self-updates during normal command execution without user-facing confirmation, allowing installed package bytes to be replaced automatically. In the context of a skill expected to process merchant notices and stills, hidden code mutation substantially increases supply-chain risk because behavior can change independently of any explicit user action or review.

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
The presence of credentials.json in the shared state files targeted for cleanup indicates this skill is designed to manipulate authentication material outside its stated media-generation purpose. In context, touching shared credential storage is dangerous because compromise, deletion, or misuse of that file can disable or interfere with all skills using the shared device connection.

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
96% confidence
Finding
The _device_token function reads an access token from credentials.json and uses it later for remote revocation, granting the skill direct access to bearer-token material. For a skill whose declared purpose is creating talking clips, this is an unjustified privilege that could be repurposed to interfere with account/device access or abused if the package is modified or invoked maliciously.

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 command enables the package to modify its own installed code, which is inherently high risk in a skill whose advertised role is only media generation. Self-modification increases the blast radius of any upstream compromise, review bypass, or operational mistake because future code can be introduced through the running client rather than a separately governed installation path.

Static analysis

No suspicious patterns detected.