Back to skill

Security audit

TikTok Comment Reply Voice

Security checks for vulnerabilities and agentic risk

Overview

This skill does the advertised TikTok comment-to-speech work, but it also grants and uses broad Beatra account authority and silently self-updates executable code by default.

Review this before installing in managed or sensitive environments. Disable automatic updates with `python3 scripts/mcp_client.py update --auto off` if you require reviewed code to stay fixed, and only authorize it if you are comfortable with a shared Beatra credential that can spend credits and access broader Beatra media/task capabilities than this TikTok speech workflow needs.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/mcp_client.py:969
Finding
Silent Automatic Updates Permit Remote Replacement of Executable Skill Code<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:31-32, 969-1018, 1543` **Vulnerability Type**: Remote payload retrieval and execution **Risk Level**: High ### Vulnerable Code ```python PACKAGE_DISCOVERY_URL = "https://beatra.ai/skills/tiktok-comment-reply-voice/channels/clawhub/install.json" PACKAGE_CDN_BASE_TEMPLATE = "https://cdn.beatra.ai/agent-packages/tiktok-comment-reply-voice/channels/clawhub/v{version}" ``` ```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_b ...[truncated 3386 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Disable automatic updates by default and require explicit, informed approval before replacing executable files. 2. Sign each release manifest with a dedicated offline release-signing key. 3. Embed or securely provision the corresponding public verification key in the reviewed package. 4. Verify the signature before trusting version numbers, archive hashes, file hashes, or replacement instructions. 5. Keep rollback, archive path validation, file-count limits, size limits, and atomic replacement controls; these remain useful defense-in-depth. 6. Display the proposed version, source, signing identity, and changed executable files before installation. 7. Consider separating update checking from update installation so normal MCP operations never alter local executable code. 8. Log update success and failure without including credentials or user content. 9. Provide administrators with a policy mechanism to pin an approved version or disable all network-based package replacement. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/authorize.py:29
Finding
Device Credential Requests Capabilities Beyond the Skill’s Declared Functionality<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:29-32` **Vulnerability Type**: Excessive authorization scope and violation of least privilege **Risk Level**: High ### Vulnerable Code ```python SCOPE = ( "mcp:tools artifacts:write images:generate videos:generate music:generate " "speech:generate voices:read voices:write wallet:spend tasks:read artifacts:read tasks:cancel" ) ``` The requested scope is sent as part of Device Authorization: ```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, } ``` ### Technical Analysis The declared Skill workflow is limited to reading public TikTok video/comment information, optionally uploading and cloning an authorized voice sample, synthesizing speech, reading tasks/results, and checking billing information. The authorization request additionally includes capabilities for: - Image generation. - Video generation. - Music generation. - Broad artifact writing and reading. - General task cancellation. - Wallet spending. Image, video, and music generation are not required to produce spoken TikTok comment replies. The Skill documentation explicitly states that it does not animate a clip, which further demonstrates that video-generation privileges are outside its stated purpose. The credential is also shared through `~/.beatra/credentials.json`, rather than being narrowly bound to only this package’s required tools. Consequently, compromise of the client, credential file, or automatic update channel exposes every granted capability rather than only the minimal operations needed for this Skill. Although the authorization documentation states that approval covers image, video, music, speech, upload, model, and task tools, disclosure does not ...[truncated 1388 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the broad shared scope with a package-specific least-privilege scope. 2. Remove `images:generate`, `videos:generate`, and `music:generate` from this Skill. 3. Grant `tasks:cancel` only when cancellation is an explicit supported operation and only after user confirmation. 4. Restrict artifact permissions to the exact upload and result-access operations required by the workflow. 5. Separate read-only wallet access from credit-spending authority where supported. 6. Use incremental authorization for optional features: - Request upload and voice-cloning permissions only if the user chooses cloning. - Request speech-generation permission only immediately before the speech workflow. 7. Bind credentials to the package slug and an allowlist of MCP tool names on the server. 8. Avoid reusing a single broadly privileged credential across unrelated Skills. 9. Display the precise requested capabilities and their financial implications on the approval page. 10. Add server-side enforcement so this package cannot invoke image, video, or music tools even if a legacy credential contains those scopes. ]]>

other

Warning
Location
scripts/authorize.py:341
Finding
Authorization Collects and Transmits Hostname and Agent-Environment Information<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:341-370, 455-467, 560-566` **Vulnerability Type**: Environment reconnaissance and privacy exposure **Risk Level**: Medium ### Vulnerable 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" ``` ```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] ``` ```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 information is also persisted locally: ```python host_platform = detect_host_platform(platform) device_name = device_display ...[truncated 2486 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not collect or transmit the operating-system hostname by default. 2. Replace the hostname with a random local device identifier or a user-selected display label. 3. Make platform telemetry opt-in and explain why it is needed before collecting it. 4. If platform information is operationally necessary, use a coarse value such as `agent` rather than fingerprinting specific environment-variable signatures. 5. Clearly disclose all transmitted metadata in the authorization documentation and approval interface. 6. Provide a command-line option such as `--device-name` and transmit a name only when the user explicitly supplies one. 7. Minimize retention of `host.json`, protect it with the same private atomic-write controls used for other state files, and delete it during disconnection. 8. Define server-side retention limits and prevent hostname/platform data from being used for unrelated analytics. 9. Review authorization telemetry under applicable privacy and data-protection requirements. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (7)

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill clearly instructs use of shell commands, local file access, networked MCP calls, uploads, and package updates, yet it declares no permissions. This creates a transparency and least-privilege failure: operators and enforcement systems cannot accurately assess or constrain what the skill can do before use.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The advertised purpose is narrow audio generation from TikTok comments, but the skill also encompasses authentication, credential storage, arbitrary Beatra tool invocation, local file upload, self-update, installation registration, and uninstall/revocation behavior. That mismatch is dangerous because users may grant trust or provide inputs expecting a simple content tool while the skill performs broader system and account-affecting actions.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill states that the bundled client can automatically download and install newer releases without separate confirmation, replacing package-owned files. Even if signatures are verified, silent self-modification materially changes local code at runtime and increases supply-chain and trust risks, especially because the main description does not prominently warn users about this behavior.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The document states that the client performs silent network checks by default and automatically installs newer releases without separate confirmation. Even with integrity controls like fixed update sources, checksum verification, rollback, and path restrictions, this behavior changes local files and initiates background network activity without clear opt-in or prominent warning, which creates a meaningful transparency and trust-risk for users and can violate least-surprise expectations.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The documentation states that the client automatically performs an installation registration call and writes a local cache file, but it does not clearly warn users beforehand that telemetry-like metadata will be transmitted and that files will be created under the user's home directory. Even though the data is described as non-secret and non-billable, undisclosed automatic network activity and persistence can violate user expectations, privacy requirements, or enterprise policy.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The client performs silent automatic self-updates and then replaces installed package files on disk during normal execution. Although the updater includes several integrity checks, it still creates a remote code-delivery path that can change local executable behavior without an explicit user action at execution time, increasing supply-chain and trust-boundary risk for an agent skill.

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 exposed self-update capability enables the package to download and replace its own installed files, which is self-modification of executable code. Even with hash checks and host restrictions, this materially expands attack surface: a compromise of the update channel, signing/trust process, or origin infrastructure would directly convert into code execution in the agent environment.

Static analysis

No suspicious patterns detected.