Back to skill

Security audit

Intern Onboarding Talks

Security checks for vulnerabilities and agentic risk

Overview

The skill’s onboarding-video purpose is real, but it asks for broad account authority and silently self-updates installed code by default.

Review this before installing in a managed or sensitive environment. The skill can perform billable Beatra operations, stores a shared bearer token locally, sends device/platform metadata to Beatra, and silently updates its own package by default. Disable automatic updates with the documented command before use if stable reviewed code is required, and only authorize it if the broad shared Beatra scopes are acceptable.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 Silent Self-Update Permits Remote Replacement of Executable Skill Code## Vulnerability Details **File Location**: `scripts/mcp_client.py:969-1017, 1512-1544`; supporting update-source logic at `scripts/mcp_client.py:31-32, 299-330, 334-349, 474-490` **Vulnerability Type**: Remote payload retrieval and execution without an independent cryptographic trust root **Risk Level**: High **Relevant Code**: ```python PACKAGE_DISCOVERY_URL = "https://beatra.ai/skills/intern-onboarding-avatar/channels/clawhub/install.json" PACKAGE_CDN_BASE_TEMPLATE = "https://cdn.beatra.ai/agent-packages/intern-onboarding-avatar/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 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_che ...[truncated 3660 chars]
Remediation
## Remediation Suggestions 1. Disable automatic updates by default and require an explicit user action before downloading or replacing code. 2. Sign every release manifest with a dedicated offline release key and pin the corresponding public key in the audited client. 3. Verify the signature before trusting any version, URL, checksum, or file list. 4. Consider key rotation metadata signed by the existing trusted key and maintain a revocation procedure. 5. Display the current version, proposed version, source, and affected files before installation. 6. Separate update execution from ordinary media commands so a generation request cannot implicitly modify local code. 7. Preserve the existing redirect rejection, path validation, size limits, ownership checks, transaction journal, and rollback safeguards as defense-in-depth.

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/authorize.py:34
Finding
Full-Scope Shared Token and Unrestricted Tool Dispatch Violate Least Privilege## Vulnerability Details **File Location**: `scripts/authorize.py:34-38`; unrestricted dispatch at `scripts/mcp_client.py:1465-1503` **Vulnerability Type**: Excessive OAuth scope combined with unrestricted remote tool selection **Risk Level**: High **Relevant 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" ) ``` ```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 Skill's declared workflow requires artifact upload, voice selection or cloning, speech synthesis, image-to-video generation, model discovery, task polling, and limited wallet reads. Nevertheless, authorization requests unrelated capabilities including generic image generation and music generation. It also obtains task cancellation and shared artifact/task read privileges under one reusable device token. The command dispatcher accepts any caller-supplied MCP tool name and forwards it without a package-level allowlist. Conse ...[truncated 1489 chars]
Remediation
## Remediation Suggestions 1. Issue package-specific credentials rather than one full-scope token shared by every Beatra Skill. 2. Remove `images:generate` and `music:generate` because they are not needed by the declared workflow. 3. Separate read-only model, wallet, and task permissions from billable generation permissions. 4. Add an explicit local allowlist for the precise tools required by this package, such as model listing, voice listing or cloning, speech synthesis, video animation, artifact upload, task lookup, and documented wallet reads. 5. Require a distinct, explicit user confirmation for billable calls and cancellation operations. 6. Enforce equivalent package-level restrictions on the server; a local allowlist alone is not a sufficient security boundary. 7. Use short-lived, audience-restricted tokens and support revocation per package installation.

other

Warning
Location
scripts/authorize.py:347
Finding
Authorization Transmits Unnecessary Hostname and Agent-Environment Fingerprints## Vulnerability Details **File Location**: `scripts/authorize.py:347-369, 446-468, 564-568`; related telemetry at `scripts/mcp_client.py:1147-1162, 1221-1229, 1354-1381` **Vulnerability Type**: Environment reconnaissance and device fingerprint telemetry **Risk Level**: Medium **Relevant Code**: ```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(DE ...[truncated 2418 chars]
Remediation
## Remediation Suggestions 1. Do not transmit the system hostname by default. 2. Use a random, locally generated device label or let the user explicitly choose a display name. 3. Make platform and installation telemetry opt-in and explain each transmitted field before authorization. 4. Avoid adding telemetry fields to every tool call when registration-level attribution is sufficient. 5. Minimize retention and correlation periods for installation metadata. 6. Provide a documented mechanism to inspect, disable, and delete telemetry. 7. If a stable identifier is operationally necessary, rotate it on reauthorization and prevent its use across unrelated packages.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/mcp_client.py:1044
Finding
Windows Credential File Protection Relies on Unverified Inherited ACLs## Vulnerability Details **File Location**: `scripts/mcp_client.py:1044-1080`; credential creation behavior at `scripts/authorize.py:114-156` **Vulnerability Type**: Inadequate access-control enforcement for a full-scope bearer credential **Risk Level**: Medium **Relevant Code**: ```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") 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.getui ...[truncated 2747 chars]
Remediation
## Remediation Suggestions 1. Store the token in Windows Credential Manager or another operating-system credential vault instead of a plaintext JSON file. 2. If file storage must remain supported, create an explicit DACL granting access only to the current user and required system administrators. 3. Verify the owner, file type, reparse-point status, and effective ACL before every credential read. 4. Fail closed with a clear remediation message when private access cannot be established. 5. Use atomic replacement while preserving the explicit restrictive ACL. 6. Update documentation to match actual guarantees and clearly distinguish intended defaults from enforced controls. 7. Consider narrowing and shortening the token's scopes and lifetime to reduce the consequences of local disclosure.
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 (19)

Lp3

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding
The skill exercises powerful capabilities including shell, filesystem, environment access, and network operations, but does not declare permissions or present those capabilities in a constrained way. That makes review, policy enforcement, and user consent weaker, and increases the chance that a seemingly narrow media-generation skill can access local data or perform remote actions beyond user expectations.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The stated purpose is a narrow onboarding-video workflow, but the skill also performs credential handling, remote tool invocation, telemetry/registration, upload of local files, uninstall cleanup, and package self-management. This mismatch is dangerous because users and reviewers may authorize the skill for benign media generation while overlooking broader behaviors that can expose credentials, local content, and system state to a third party.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
The skill contains a self-updating mechanism unrelated to the business function of producing onboarding clips, which introduces a software supply-chain risk into an otherwise content-processing workflow. Even if updates are signed and verified, the feature enables remote code changes on the local installation and materially expands the trust boundary beyond the declared task.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The OAuth scope requests capabilities far beyond the skill’s stated purpose of generating onboarding talking clips from still images and notes. In particular, unrelated permissions such as wallet spending, music generation, broad artifact/task access, and voice management violate least privilege and would let a compromised or abusive skill perform actions unrelated to onboarding video creation.

Context-Inappropriate Capability

Critical
Confidence
93% confidence
Finding
Task cancellation is not obviously required for a simple content-generation flow and adds control over user jobs beyond the stated onboarding use case. While less severe than wallet spending, it could still be abused to disrupt unrelated work or interfere with other queued tasks on the shared account.

Context-Inappropriate Capability

High
Confidence
93% confidence
Finding
Task cancellation is not obviously required for a simple content-generation flow and adds control over user jobs beyond the stated onboarding use case. While less severe than wallet spending, it could still be abused to disrupt unrelated work or interfere with other queued tasks on the shared account.

Context-Inappropriate Capability

High
Confidence
93% confidence
Finding
Task cancellation is not obviously required for a simple content-generation flow and adds control over user jobs beyond the stated onboarding use case. While less severe than wallet spending, it could still be abused to disrupt unrelated work or interfere with other queued tasks on the shared account.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
Task cancellation is not obviously required for a simple content-generation flow and adds control over user jobs beyond the stated onboarding use case. While less severe than wallet spending, it could still be abused to disrupt unrelated work or interfere with other queued tasks on the shared account.

Description-Behavior Mismatch

High
Confidence
95% confidence
Finding
The file implements a full self-update channel that discovers, downloads, validates, and later installs replacement package content, even though the skill's declared purpose is generating onboarding avatar clips. While the update path includes checksum and manifest validation, it still gives the skill code the ability to change its own installed bytes outside the user-expected business function, materially expanding the trust boundary and creating a supply-chain/self-modification risk if the update infrastructure or signing/distribution process is compromised.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
The skill fingerprints its execution environment using environment variables and local host metadata to derive a platform identity, then injects that into outbound tool requests. For an intern onboarding video skill, that collection is not necessary for core functionality and increases privacy and tracking risk, especially because environment signatures can reveal which agent framework or execution context the user is operating in.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
The code maintains a local inventory of installed skills and performs installation-registration telemetry on use, sending package/version/platform/reference data unrelated to producing onboarding clips. This broadens data collection beyond the stated purpose and can support cross-skill tracking or asset inventorying on the device, which is especially concerning because it is best-effort background behavior rather than a user-requested feature.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The uninstall routine manages a shared ~/.beatra credential store, can revoke a device authorization, and can delete shared local state for all Beatra skills. That behavior is outside the declared purpose of an intern-onboarding video skill, so installing this package grants it influence over broader platform authentication state than a user would reasonably expect.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
When this skill believes it is the last installed skill, it can revoke the shared device token and remove shared files such as credentials.json, host.json, and skills.json from ~/.beatra. Even though the code is cautious, compromise or misuse of this script could disconnect other functionality or erase shared state unrelated to intern-onboarding clip generation.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The skill states that it installs newer versions automatically without separate confirmation, which permits code on the local system to change after initial review or approval. This is dangerous because it defeats stable-review assumptions, can introduce new capabilities or regressions silently, and amplifies the impact of any compromise in the update channel or publisher pipeline.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The document states that the client performs silent update checks by default and automatically installs newer versions without separate confirmation. Even with strong integrity controls described later, default background network activity and local binary/file replacement can violate user expectations, create compliance or change-management issues, and expand the blast radius if the trusted update infrastructure is ever compromised.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
The document states that the client automatically makes a network registration call on first use and writes a local cache file, but it does not clearly warn users about this telemetry-like behavior or file creation before use. Even though the data is described as non-secret and non-billable, undisclosed automatic outbound communication and persistence can violate user expectations, privacy requirements, or enterprise policy.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill supports best-effort automatic silent updates that can replace installed package files during normal command execution without a user-facing prompt. Even with integrity checks, silent code replacement is dangerous in this context because it allows the behavior of a media-generation skill to change over time without informed approval, increasing supply-chain and persistence risk.

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
82% confidence
Finding
The code reads ~/.beatra/credentials.json to obtain an access token and uses it to call the revocation endpoint. Although this appears intended for legitimate uninstall behavior rather than theft, it still gives this skill direct access to a shared authentication token, which exceeds the narrow business purpose of generating onboarding videos and increases the blast radius if the skill is modified or abused.

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
97% confidence
Finding
The exposed CLI advertises and enables package self-updates, confirming that self-modification is an intentional feature available from the installed skill. In the context of a narrowly scoped onboarding-video tool, that is a risky capability because it lets the package alter its own code footprint, undermining predictability and increasing the blast radius of any compromise in the update path.

Static analysis

No suspicious patterns detected.