Back to skill

Security audit

Xiaohongshu Hall FAQ Stills

Security checks for vulnerabilities and agentic risk

Overview

This skill has a coherent image-generation workflow, but it asks for broad account permissions and silently installs its own updates by default.

Install only if you are comfortable giving this Beatra package a shared device credential with permissions beyond still images and allowing default silent package updates. Review the approval page carefully, consider disabling auto-updates with the documented command before normal use, and avoid using it in environments where shared credentials, telemetry, or unattended code replacement are not 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
  • 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 (2)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/authorize.py:34
Finding
Device Authorization Requests Privileges Beyond the Skill’s Declared Functionality<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:34-36` **Vulnerability Type**: Excessive OAuth/device-token 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" ) ``` The breadth of this authorization is also disclosed in `references/installation-and-auth.md:71-74`: ```text The helper opens no local listener and requires no inbound connection. One approval covers image, video, music, speech, upload, model, and task tools. ``` ### Technical Analysis The Skill’s declared purpose is to read public Xiaohongshu complaints and create still-image material cards. Its legitimate operations include social-content lookup, image generation or editing, selected-file upload, model discovery, billing access, and task-result retrieval. The requested token additionally grants capabilities for: - Video generation - Music generation - Speech generation - Reading and writing voices - Broad artifact access - Wallet spending - Task cancellation Video, music, speech, and voice-writing permissions are not necessary for the declared still-image workflow. Broad cancellation and artifact permissions may also affect tasks or assets created by other packages because the credential is shared through `~/.beatra/credentials.json`. This violates the principle of least privilege. Although the audit found no code that intentionally abuses these permissions, the unnecessarily broad token increases the consequences of credential theft, future code compromise, or misuse by an automatically installed update. ### Attack Path 1. The user runs `scripts/authorize.py`. 2. The authorization request asks the user to approve the complete scope defined by `SCOPE`. 3. Beatra returns a bearer token containing permissions unrelated to the still-image workflow. 4. The ...[truncated 1091 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the shared broad scope with a package-specific least-privilege scope. 2. Remove at least the following permissions unless a documented workflow explicitly requires them: - `videos:generate` - `music:generate` - `speech:generate` - `voices:read` - `voices:write` 3. Restrict `tasks:cancel` to tasks created by this package, or request it only when the user explicitly initiates cancellation. 4. Restrict artifact access to artifacts uploaded or generated by this package. 5. Separate read-only discovery and account operations from credit-spending operations where the authorization service supports granular scopes. 6. Bind wallet spending to explicit operation families and package identity on the server. 7. Display the exact requested permissions on the approval page, emphasizing paid and destructive capabilities. 8. Add server-side authorization tests confirming that this package cannot invoke unrelated media-generation or cross-package task-management operations. 9. Rotate existing credentials after narrowing the scope so previously issued broad tokens no longer remain valid. ]]>

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/mcp_client.py:969
Finding
Default Silent Auto-Update Replaces Executable Skill Files Without Per-Update Approval<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:969-1018` **Vulnerability Type**: Automatic retrieval and installation of mutable remote code **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_update(discovery, get_bytes=get_bytes) _apply_update( install_root=resolved_root, u ...[truncated 4588 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Disable automatic installation by default. Update checks may remain enabled, but installation should require explicit user approval. 2. Show the proposed version, release metadata, changed files, and publisher identity before installation. 3. Sign release manifests with a dedicated offline signing key and embed or securely provision the corresponding public key in the reviewed package. 4. Verify a cryptographic signature independently of HTTPS and publisher-controlled checksum fields. 5. Support release-key rotation through a separately authenticated and auditable process. 6. Pin updates to an approved major or exact version where reproducibility is required. 7. Separate update checking from ordinary paid business operations so a normal generation command never implicitly changes executable code. 8. Preserve the existing `update --auto off` control, but make opt-in installation the default. 9. Record update events in a user-visible local log containing the previous version, new version, verified signer, and file list without recording credentials. 10. Narrow the bearer-token permissions so compromise of a future update has less account-level impact. 11. Consider requiring a new security review or explicit trust decision whenever executable scripts change. ]]>
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
95% confidence
Finding
The skill advertises no declared permissions, yet its instructions clearly require shell execution, network access, file reads/writes, environment use, and local uploads. This creates a transparency and least-privilege failure: operators may approve or run the skill without understanding that it can access local files, invoke external services, and modify local package state.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The documented behavior goes far beyond generating FAQ stills: it includes browser-based auth, persistent credential storage, shared credential management, telemetry/registration, remote tool invocation, artifact upload, uninstall cleanup, and automatic package updates. This mismatch is dangerous because users and security reviewers may grant trust based on a narrow stated purpose while the skill actually introduces broad account, filesystem, network, and supply-chain exposure.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
Embedding automatic self-update behavior inside a content-generation skill adds an unnecessary supply-chain and persistence mechanism unrelated to the user-facing task. Even if intended for maintenance, it expands trust from the installed package to future remote-delivered code, increasing the blast radius of server compromise, signing failure, or policy bypass.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
Automatic download and installation is unjustified for a FAQ-stills workflow and gives the package the ability to replace its own code outside normal review. That creates a strong supply-chain risk: a compromised update endpoint or signing process could turn a benign graphics skill into arbitrary code execution with the same local file, shell, network, and credential access already described elsewhere in the document.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The authorization scope is far broader than the skill's stated purpose of generating still FAQ materials. Requesting unrelated permissions such as video, music, speech, voice management, task cancellation, and artifact access violates least privilege and materially increases blast radius if the token is misused, compromised, or the skill later performs actions outside user expectations.

Context-Inappropriate Capability

Critical
Confidence
98% confidence
Finding
Requesting videos:generate is inconsistent with a stills-only workflow and grants unnecessary capability. In a compromise or misuse scenario, this broadens what an attacker or buggy component can do with the user's authorization beyond the intended static-materials use case.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
Requesting videos:generate is inconsistent with a stills-only workflow and grants unnecessary capability. In a compromise or misuse scenario, this broadens what an attacker or buggy component can do with the user's authorization beyond the intended static-materials use case.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
Requesting videos:generate is inconsistent with a stills-only workflow and grants unnecessary capability. In a compromise or misuse scenario, this broadens what an attacker or buggy component can do with the user's authorization beyond the intended static-materials use case.

Description-Behavior Mismatch

High
Confidence
95% confidence
Finding
The client includes a full self-update mechanism that downloads manifests and archives from remote infrastructure and replaces local installation files, even though the advertised skill purpose is FAQ-to-stills generation. Although there are integrity checks and path-safety controls, this still grants the remote service ongoing authority to change executable local code, expanding trust far beyond the skill's declared function and creating a supply-chain compromise path.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The code records installation telemetry and a local skill inventory, including platform and install path metadata, which is unrelated to converting public FAQ complaints into still assets. This increases privacy and tracking surface, and in a creative skill context such host-level persistence and telemetry are unexpected, making the behavior more suspicious and potentially harmful if aggregated or abused.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
The skill inspects environment variables and host identity to classify the agent platform, which is not needed to transform FAQ content into still materials. In this context, environment fingerprinting broadens host reconnaissance capability and can aid tracking, targeting, or adaptive behavior across runtimes.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
Maintaining a device-local inventory of installed skills and install paths exceeds the expected scope of a FAQ-stills generator and creates unnecessary local surveillance data. Such inventories can reveal user tooling, filesystem layout, and usage patterns, and become sensitive if exposed to other components or later exfiltrated.

Description-Behavior Mismatch

High
Confidence
95% confidence
Finding
This uninstall script makes an outbound revocation call to Beatra infrastructure using a bearer token and is part of a skill whose stated purpose is generating FAQ still materials. Even if intended for lifecycle management, that capability is unrelated to the advertised content function and gives the package authority over shared device credentials, creating a high-trust side effect that could disrupt other skills or be repurposed if the package is compromised.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
The code deletes multiple files under ~/.beatra, including credentials and installation metadata, which are explicitly described as shared across skills. Although the script tries to preserve state when other skills remain, any bug, stale inventory, or manipulated state could cause loss of shared authentication and break unrelated installed skills on the device.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The package reads global skill inventory and device credentials to decide whether to revoke shared access, which exceeds what is needed for an FAQ-to-stills skill. This broad host introspection increases attack surface and trust requirements because the skill can enumerate installation state and act on shared authentication material.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
Installing updates without separate confirmation removes an important human review checkpoint and allows trust boundaries to change silently after initial approval. In the context of a skill that already uses shell commands, remote APIs, persistent state, and local uploads, silent code changes materially increase the risk of unnoticed malicious or unsafe behavior.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The document states that the client silently checks for updates and automatically installs newer versions without separate confirmation. Even with checksum and source validation controls, unattended code replacement changes installed executables by default and expands the trust boundary, creating supply-chain and change-management risk if the update channel or signing/discovery process is ever compromised or misconfigured.

Missing User Warnings

Medium
Confidence
84% confidence
Finding
The documentation states that the client automatically performs an installation registration call and writes a local cache containing package and environment identifiers, but it does not clearly warn users about this telemetry or local persistence. Even if the data is described as non-secret and non-billable, undisclosed outbound registration and host/environment recording can create privacy, transparency, and compliance issues in enterprise or regulated environments.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The client performs silent automatic self-updates during normal execution, modifying installed package files without a contemporaneous user-facing warning or approval step. Even with checksum validation, silent code replacement is dangerous because it normalizes hidden behavior changes and magnifies the impact of release-channel or infrastructure compromise.

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
88% confidence
Finding
Listing credentials.json among files the script owns signals that the package is designed to handle and potentially remove shared credential material. In the context of a content-generation skill, direct interaction with shared credentials is unnecessary and dangerous because compromise or misuse can affect all skills tied to the same Beatra 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
94% confidence
Finding
The _device_token function reads an access token from ~/.beatra/credentials.json and uses it for network revocation. Reading bearer tokens from disk inside a skill package creates credential exposure risk and violates least privilege, especially since the skill’s declared purpose does not require any credential handling.

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
95% confidence
Finding
Exposing self-update functionality in the skill CLI confirms that this package can modify its own installed codebase. In a skill whose declared purpose is content transformation, self-modification is an unjustified high-risk capability because it enables persistence and turns any compromise of the update channel or publisher account into local code execution on future runs.

Static analysis

No suspicious patterns detected.