Back to skill

Security audit

Insurance Renewal Reminder Talking Clips

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real insurance reminder video workflow, but it asks for broad Beatra account authority and can silently replace its installed code, so it should be reviewed before use.

Install only if you are comfortable giving this Beatra package a shared account credential with broad media, artifact, wallet, and task permissions. Turn off automatic updates if you need reviewed-version control, avoid submitting unnecessary personal policy details or unauthorized likeness or voice samples, and consider revoking the Beatra device authorization after use if you do not plan to keep using Beatra skills.

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

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/authorize.py:31
Finding
Overprivileged Device Authorization and Unrestricted MCP Tool Dispatch<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:31-34`; `scripts/mcp_client.py:1469-1489` **Vulnerability Type**: Excessive authorization scope and insufficient client-side tool restriction **Risk Level**: High ### Complete Code Snippets Authorization requests capabilities beyond those required for insurance-renewal talking clips: ```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 interface accepts an arbitrary MCP tool name and forwards it without a local 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}, ) ``` ### Technical Analysis The declared workflow needs asset upload, model and voice discovery, optional voice cloning, speech synthesis, image-to-video generation, task inspection, and limited billing queries. The authorization scope additionally grants generic image generation, music generation, broad artifact access, task cancellation, and wallet spending. The client also exposes a generic `call` command that forwards any supplied MCP tool name. It does not enforce an allowlist matching the Skill's documented workflow. Authorization is still enforced by th ...[truncated 1600 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the shared full-scope token with a package-specific, least-privilege authorization grant. 2. Remove capabilities not required by this Skill, particularly generic music generation, generic image generation, broad artifact reading, and unrestricted cancellation. 3. Add a local allowlist for accepted MCP tools. The allowlist should contain only the documented upload, model, voice, speech, video, task, wallet-read, and installation-registration operations. 4. Reject unknown tool names before opening an authenticated session. 5. Separate read-only, generation, cancellation, and wallet-spending privileges where supported. 6. Require an explicit user confirmation immediately before cancellation and every billable operation. 7. Have the server independently bind the credential to the package identity and enforce a server-side tool allowlist; client-side restrictions alone are not a sufficient security boundary. 8. Display the exact requested scopes during authorization so the user can make an informed decision. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/authorize.py:340
Finding
Unnecessary Collection and Transmission of Host Identification Telemetry<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:340-370`, `scripts/authorize.py:464-475`; `scripts/mcp_client.py:1148-1166`, `scripts/mcp_client.py:1215-1228`, `scripts/mcp_client.py:1382-1400` **Vulnerability Type**: Environment fingerprinting and unnecessary telemetry **Risk Level**: Medium ### Complete Code Snippets The authorization helper examines agent-related environment variables and reads 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] ``` The hostname is included in the remote Device 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, ...[truncated 3041 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove hostname collection unless it is strictly required for a user-requested device-management feature. 2. Use a generic device label or locally generated random identifier instead of the operating-system hostname. 3. Make installation telemetry and source attribution opt-in, with a clear explanation of every transmitted field. 4. Default the platform field to `unknown`; collect a specific platform only when the user explicitly enables diagnostics. 5. Separate authorization from telemetry so denying telemetry does not prevent use of the creative functions. 6. Minimize retention of `host.json` and provide a command to inspect and delete stored telemetry. 7. Document server-side retention, correlation, and deletion policies. 8. Avoid attaching telemetry to every business call when one consented registration event would be sufficient. ]]>

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/mcp_client.py:969
Finding
Default Silent Self-Update Permits Post-Audit Remote Code Replacement<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:516-523`, `scripts/mcp_client.py:969-1020`, `scripts/mcp_client.py:1517-1544` **Vulnerability Type**: Automatic retrieval and installation of mutable remote code **Risk Level**: High ### Complete Code Snippets Missing or invalid local state enables automatic updates by default: ```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 execution may download and replace package files without a separate update 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 ...[truncated 4526 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Change the default to `"auto_update": false`. 2. Require explicit user approval before downloading or installing each new version. 3. Show the current version, target version, publisher identity, changed-file list, and release notes before approval. 4. Verify discovery documents and release manifests with a digital signature rooted in a public key pinned in the audited package. 5. Keep archive hashes and transactional file protections, but do not treat hashes from the same mutable channel as independent publisher authentication. 6. Support a check-only mode that never modifies package files and make it the default background behavior, if background checks remain necessary. 7. Pin deployments to a reviewed version where reproducibility is required. 8. Require reauthorization or scope review if an update expands tool access. 9. Record an auditable local update log without credentials or sensitive user content. 10. Preserve the existing redirect rejection, safe extraction, ownership checks, backups, rollback, and recovery controls. ]]>
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
96% confidence
Finding
The skill declares no permissions while instructing use of shell execution, local file inspection/upload, network access, and package-managed update behavior. This creates a hidden capability gap that can mislead operators and policy enforcement layers, increasing the chance that sensitive local files, credentials, or system state are accessed without clear consent boundaries.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared purpose is narrowly about generating insurance reminder clips, but the documented behavior includes authentication flows, credential storage, arbitrary local file upload, telemetry/registration, and self-update/uninstall operations. That mismatch is dangerous because users and reviewers may authorize the skill for media generation without realizing it can manage credentials, communicate broadly with remote services, and alter local code or state.

Context-Inappropriate Capability

Medium
Confidence
97% confidence
Finding
The skill includes an automatic self-update mechanism that downloads and replaces local package code, which is unrelated to the core task of producing renewal reminder clips. Any auto-update channel expands supply-chain risk: if the update path, signing, CDN, or discovery process is compromised, new code can be introduced onto the host without a workflow-specific approval step.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The documentation describes automatic outbound installation registration telemetry that is unrelated to the skill’s stated insurance reminder clip-generation purpose. Even if the data is framed as non-secret and non-billable, it still collects and transmits installation metadata without clear necessity, expanding the skill’s data handling and attack surface beyond user expectations.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The file describes resolving the real agent environment from environment signatures or host metadata and sending platform-linked registration data. For a skill whose purpose is generating insurance renewal talking clips, host/environment fingerprinting and outbound registration are not justified by business need and can enable tracking, correlation of installations, and privacy-invasive profiling.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The OAuth scope string requests a very broad set of capabilities, including artifacts, images, videos, music, speech, voice management, wallet spending, and task control, while the skill is described only as generating insurance renewal reminder talking clips from photos and dates. This violates least privilege and means that if the skill, its backend workflow, or the stored token is abused, an attacker gains materially more access than the user would reasonably expect from this skill.

Context-Inappropriate Capability

High
Confidence
95% confidence
Finding
The tasks:cancel scope is unrelated to the stated clip-creation purpose and grants control over task lifecycle beyond generation itself. In the event of token compromise or misuse, this could be used to interfere with other legitimate user operations sharing the same credential.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The tasks:cancel scope is unrelated to the stated clip-creation purpose and grants control over task lifecycle beyond generation itself. In the event of token compromise or misuse, this could be used to interfere with other legitimate user operations sharing the same credential.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The tasks:cancel scope is unrelated to the stated clip-creation purpose and grants control over task lifecycle beyond generation itself. In the event of token compromise or misuse, this could be used to interfere with other legitimate user operations sharing the same credential.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The tasks:cancel scope is unrelated to the stated clip-creation purpose and grants control over task lifecycle beyond generation itself. In the event of token compromise or misuse, this could be used to interfere with other legitimate user operations sharing the same credential.

Description-Behavior Mismatch

High
Confidence
95% confidence
Finding
The client exposes generic remote MCP operations including tools/list, arbitrary tools/call from stdin, upload, verification, telemetry, and self-update behavior, which is much broader than the advertised purpose of generating insurance-renewal talking clips. In skill context, this is dangerous because a seemingly narrow media skill becomes a general remote command broker to a backend service, expanding attack surface and enabling unexpected data transfer or capability abuse if the backend, tool catalog, or calling environment is compromised or misused.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
The code records local skill inventory and performs installation telemetry unrelated to the user-facing insurance reminder generation function. This creates unnecessary collection and persistence of environment metadata, increasing privacy and surveillance risk and giving the remote service visibility into installs and usage patterns that users may not expect from this skill.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
The code fingerprints the host environment using environment variables and host.json to derive source_platform and registration platform values. In this skill context, host attribution is not necessary to create talking renewal clips, so it increases privacy risk and can aid cross-environment tracking or profiling without being essential to core functionality.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
This uninstall script handles shared device credentials, inventory, and remote token revocation even though the skill is presented as an insurance reminder video-generation tool. That mismatch expands the skill's privilege boundary beyond its stated purpose and gives the package authority over shared authentication state for other skills, which is dangerous if the package is compromised, misused, or installed unexpectedly.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The code can submit a bearer token to a remote revocation endpoint, allowing this skill package to invalidate the device's shared authorization. Because the token is shared across skills, this creates a denial-of-service risk against other installed skills and gives a content-oriented skill unjustified control over account/session state.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The script reads access tokens from credentials.json and deletes shared state files under ~/.beatra, including credential and installation metadata used by multiple skills. A media skill should not access or destroy cross-skill authentication material, because that can break other skills, erase auditability, and expose sensitive tokens to any code path within the package.

Missing User Warnings

Medium
Confidence
79% confidence
Finding
The manifest explicitly describes handling policy renewal dates and user-supplied photos, which can contain sensitive personal or insurance-related data, but provides no privacy, consent, retention, or handling warnings. In a skill centered on insurance reminders, this omission increases the risk of users sharing regulated or highly identifying information without appropriate safeguards or disclosure.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The document states that update checks are silent, enabled by default, and will automatically install newer versions without separate confirmation. Even with integrity checks and rollback protections, this creates a security and trust risk because software can perform network activity and replace local files without an explicit opt-in or prominent warning, which can surprise users and expand the blast radius if the update channel or signing process is ever compromised.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The markdown states that registration occurs automatically on first use, but it does not mention any user-facing warning, consent prompt, or prominent disclosure. Silent telemetry undermines informed consent and may violate privacy expectations or organizational policy, especially because the skill’s advertised function does not suggest any network registration behavior.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill can silently self-update and replace installed package files during normal execution without an interactive warning in the auto-update path. Even though the code includes integrity checks, silent code replacement materially changes trust boundaries: compromise of the update channel, signing/discovery infrastructure, or publisher account could push new behavior into an installed skill without informed user review.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The upload path reads a local file and sends its bytes to a remote service after requesting upload instructions, with no disclosure in the function itself about destination, retention, or scope of transfer. For a media-processing skill, uploads may be expected, but the lack of user-facing transparency still creates data exfiltration and privacy risk, especially if sensitive local files are supplied or if the calling environment is less trusted.

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
95% confidence
Finding
The presence of credentials.json in the managed shared-state set indicates this package is designed to manipulate authentication artifacts. In the context of an insurance reminder video skill, touching credential storage is unnecessary and increases the risk of credential exposure, deletion, or misuse against the broader Beatra environment.

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
This function explicitly reads an access token from a shared credentials.json file so it can be used for revocation. Accessing bearer tokens from within a skill package violates least privilege and creates a direct credential-access path unrelated to the skill's declared insurance reminder clip functionality.

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
94% confidence
Finding
The presence of built-in self-update/package modification capability means the skill can alter its own installed codebase after deployment. In a narrowly described insurance reminder skill, self-modification is especially risky because it enables post-install capability drift and makes later behavior depend on remote infrastructure rather than only the reviewed package contents.

Static analysis

No suspicious patterns detected.