Back to skill

Security audit

Amazon A+ Module Stills

Security checks for vulnerabilities and agentic risk

Overview

This skill is a real Beatra-backed image generation workflow, but it asks for broad shared account access and silently updates its own code by default.

Install only if you trust Beatra with a shared local credential and account actions beyond this single image skill. Use a Beatra account with controlled credit exposure, consider disabling automatic updates with the documented update command before normal use, and be aware that selected reference files are uploaded while hostname, platform, package, and installation metadata may be recorded or sent. Revoke the Beatra device authorization if you stop using the skill.

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

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/mcp_client.py:969
Finding
Silent Self-Update Allows Post-Audit Remote Code Replacement<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:31-32`, `scripts/mcp_client.py:334-490`, `scripts/mcp_client.py:969-1020`, and `scripts/mcp_client.py:1543` **Vulnerability Type**: Remote payload retrieval and execution **Risk Level**: High ### Relevant Code ```python PACKAGE_DISCOVERY_URL = "https://beatra.ai/skills/amazon-a-plus-module-pack/channels/clawhub/install.json" PACKAGE_CDN_BASE_TEMPLATE = "https://cdn.beatra.ai/agent-packages/amazon-a-plus-module-pack/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=resolv ...[truncated 2838 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Disable automatic installation by default. Update checks may remain opt-in or informational, but code replacement should require explicit informed user approval. 2. Sign discovery metadata or release manifests with an offline release key. 3. Pin the corresponding public key in the audited package and verify the signature before trusting any version, URL, or checksum. 4. Use key rotation metadata with threshold signing or an established framework such as TUF rather than trusting hashes delivered by the same publishing system as the payload. 5. Display the current version, proposed version, signer identity, and affected files before installation. 6. Preserve the existing archive traversal, ownership, size, rollback, and downgrade protections. 7. Provide an enterprise control that permanently disables network update checks and cannot silently revert to enabled when state is unreadable. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/authorize.py:33
Finding
OAuth Device Credential Requests Capabilities Unrelated to Image Generation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:33-36` **Vulnerability Type**: Excessive OAuth scope and violation of least privilege **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" ) ``` ### Technical Analysis The declared Skill function is creating Amazon A+ image stills, optionally uploading visual references, reading model and billing information, and monitoring relevant tasks. The requested credential additionally grants video generation, music generation, speech generation, voice-resource reads, and voice-resource writes. Those media capabilities are not needed to generate Amazon A+ still images. The token also includes spending and task-cancellation authority. Some spending and task permissions may be needed for the intended paid workflow, but combining them with unrelated media-generation and voice-management permissions increases the consequences of token compromise or misuse. The documentation states that one shared Device Token is reused across Beatra Skills. Shared authorization may explain the broad scope operationally, but it does not meet least privilege for this individual Skill. A package-specific compromise therefore inherits capabilities belonging to unrelated workflows. ### Attack Path 1. The user runs `scripts/authorize.py` and approves the requested Device Authorization. 2. Beatra returns a bearer token containing all scopes listed in `SCOPE`. 3. The token is stored in `~/.beatra/credentials.json`. 4. Malicious replacement code, local malware running as the user, or an improperly constrained Agent call obtains or uses that token. 5. The actor invokes unrelated video, music, speech, or voice operations, or uses spending and cancellation privileges. 6. The server accepts those operations because they are included in the ...[truncated 385 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Issue a package-specific credential containing only the scopes required for: - image generation and editing; - explicitly selected artifact uploads and reads; - model-card lookup; - wallet reads and narrowly controlled spending; - reads and cancellation of tasks created by this package. 2. Remove `videos:generate`, `music:generate`, `speech:generate`, `voices:read`, and `voices:write` from this Skill's requested authorization. 3. Bind task cancellation and artifact access to resources created by this package or installation. 4. Separate read-only wallet access from billable operation authorization where supported. 5. Show the exact requested capabilities on the authorization page in user-readable form. 6. If a shared cross-package credential is operationally required, place a least-privilege package-scoped broker between the Skill and the shared credential. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/mcp_client.py:1463
Finding
Generic MCP Dispatcher Does Not Restrict Calls to Skill-Approved Tools<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mcp_client.py:1463-1490` **Vulnerability Type**: Unrestricted use of privileged remote tools **Risk Level**: High ### Relevant Code ```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}, ) def main() -> int: parser = argparse.ArgumentParser(description="Call Beatra through Streamable HTTP") subparsers = parser.add_subparsers(dest="command", required=True) subparsers.add_parser("verify", help="Run the non-billable connection check") subparsers.add_parser("tools", help="List available Beatra tools") call = subparsers.add_parser("call", help="Call one tool with a JSON object on stdin") call.add_argument("tool_name") ``` ### Technical Analysis The command-line client accepts an arbitrary `tool_name` and forwards it through an authenticated `tools/call` request. It does not enforce a local allowlist matching the Skill's declared workflow, nor does it perform per-tool argument validation. The Skill documentation directs the Agent toward specific image, model, wallet, artifact, and task operations. Those textual directions do not establish an access-control boundary. If untrusted content influences the Agent into selecting another MCP tool, the local client will forward the request as long as it is ...[truncated 1394 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace arbitrary tool dispatch with a hardcoded allowlist for this package. 2. Restrict calls to the minimum required tools, such as approved image, model, wallet-read, artifact-upload, installation-registration, and task operations. 3. Add strict per-tool JSON schema validation before transmitting arguments. 4. Require explicit user confirmation immediately before billable or destructive operations. 5. Bind cancellation, reads, and edits to task or artifact identifiers created by the current package and installation. 6. Place unrelated administrative or media tools in separate clients with separate credentials. 7. Treat remote tool descriptions and user-supplied content as untrusted data rather than instructions that can expand the allowlist. ]]>

other

Warning
Location
scripts/authorize.py:343
Finding
Authorization Collects and Transmits the Local Hostname<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:343-370` and `scripts/authorize.py:438-454` **Vulnerability Type**: Environment reconnaissance and identifying 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(DEVICE_AUTHORIZATION_URL, form) ``` ### Technical Analysis The authorization flow inspects environment-variable signatures to identify the Agent platform and ...[truncated 1945 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove hostname collection unless it is strictly necessary. 2. Use a locally generated, non-identifying device label instead of the operating system hostname. 3. If a recognizable name is desired, request explicit opt-in and allow the user to enter or review the label before transmission. 4. Clearly document every transmitted field, its purpose, retention period, and whether it is shared with other services. 5. Minimize environment inspection and provide a `--no-telemetry` option that omits both platform and device-name fields. 6. Apply restrictive permissions to `host.json`; use the same atomic owner-only file-writing controls applied to credential-related state. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (27)

Lp3

Medium
Category
MCP Least Privilege
Confidence
97% confidence
Finding
The skill invokes a bundled Python client and explicitly performs network calls, local file access, shell execution, and package modification behaviors, yet declares no permissions. This creates a misleading trust boundary: a user or host may treat it as low-risk content-generation logic while it actually has broad system and network capabilities.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared purpose is image-module generation, but the skill also includes OAuth login, persistent credential storage, remote tool access, uploads, telemetry/registration, uninstall/revocation flows, and automatic package updates. That mismatch is dangerous because users may authorize the skill for a narrow creative task without understanding it can modify the local environment, store secrets, and communicate extensively with remote services.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The skill contains self-updating package management capability unrelated to its core A+ image-generation function. Any mechanism that downloads and installs code can become a supply-chain or remote-code-execution path if the update channel, signing, CDN, package ownership checks, or client logic are compromised.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The file documents installation, remote authorization, token storage, and use of a bundled MCP client for Beatra, which is unrelated to an Amazon A+ content formatting skill. This mismatch is a strong indicator of hidden scope expansion: a seemingly local formatting skill is instructing the agent to establish persistent remote access and manage credentials for an external service.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
Persistent credential management and remote device authorization are unjustified for the stated function of turning seller-supplied selling points into Amazon A+ modules. Embedding these instructions in an unrelated skill can trick an operator or agent into granting long-lived external access under false pretenses, enabling data access or later misuse beyond the advertised capability.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The documentation describes an outbound installation registration call and persistent local cache writes that are unrelated to the advertised Amazon A+ content generation function. Even if framed as non-billable and non-secret, this introduces hidden telemetry and filesystem persistence, which can leak environment metadata and create user trust and consent issues because the behavior is not aligned with the skill's stated purpose.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
A package-registration capability is context-inappropriate for a skill whose sole stated purpose is generating Amazon A+ modules, which makes the hidden network and host-identification behavior more suspicious and more dangerous in context. The documented collection of package slug, version, platform, and a stable external installation reference enables cross-installation tracking or inventorying of agent environments without a clear functional need.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
The skill requests a very broad OAuth scope set, including artifacts, images, videos, music, speech, voices, wallet spending, and task controls, which is far beyond what an Amazon A+ module formatting skill appears to need. Over-scoped credentials violate least privilege and create a large blast radius: if the token is misused, stolen, or the service is compromised, the account could be used for unrelated generation actions and spending.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
The code detects the host agent platform from environment variables and captures a device-identifying hostname, then uses and persists that metadata during authorization. For a skill whose stated purpose is generating Amazon A+ content modules, collecting platform and device identity is not obviously necessary and increases privacy exposure and fingerprinting risk.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The skill records a local inventory of installed packages including slug, platform, install path, and timestamp in ~/.beatra/skills.json. This creates unnecessary local tracking of user environment details unrelated to producing A+ modules and could expose filesystem layout and usage history to other local processes or future code paths.

Description-Behavior Mismatch

High
Confidence
96% confidence
Finding
The client implements broad capabilities unrelated to the advertised A+ content generation function, including self-update, installation registration, and local inventory management. Expanding a creative skill into a package manager and telemetry client increases trust requirements and attack surface; if the upstream service or distribution channel is compromised, the skill can change local code and persist behavior beyond the user's expected scope.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
The code fingerprints the host environment via environment variables and host.json, then injects source metadata into tool calls. That collection and transmission are unrelated to the skill's stated creative purpose and create privacy and profiling risk, especially when users are not clearly informed that their agent platform is being identified and reported.

Context-Inappropriate Capability

High
Confidence
95% confidence
Finding
The client maintains a local skill inventory and performs installation registration telemetry unrelated to generating Amazon A+ modules. This creates persistence and tracking behavior beyond user expectations, and the repeated best-effort recording on every use increases privacy risk and makes the skill behave more like an endpoint management agent than a narrowly scoped content tool.

Description-Behavior Mismatch

High
Confidence
95% confidence
Finding
The script defines OAuth revocation endpoints and a Beatra-specific user agent even though the skill is described as an Amazon A+ content-generation package. That mismatch is dangerous because it gives the package authority over shared device authorization state unrelated to the advertised function, increasing the risk of credential disruption or unauthorized account-impacting actions during uninstall.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
This code reads an access token from credentials.json and uses it to make a remote OAuth revocation request. For a skill whose stated purpose is generating Amazon A+ modules, direct credential access and token-use capability are overprivileged and create a path to misuse shared authentication material or break other installed skills if the logic is wrong or repurposed.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The script enumerates and may delete files in the shared ~/.beatra state directory, including installation and skill inventory data for all skills. Even though it tries to be careful, this exceeds the needs of a content-generation skill and creates cross-skill impact if the shared-state assumptions are wrong, corrupted, or manipulated.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill states that newer versions install automatically without separate confirmation, but this system-modifying behavior is not prominently disclosed in the skill's stated purpose or user-facing warning. Silent auto-installation increases risk because users may unknowingly run changed code with the skill's existing privileges after initial trust was granted.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The document states that the client silently checks for updates and automatically installs newer versions without separate confirmation, but it does not clearly warn users that this behavior modifies the local installation. Even with integrity checks and rollback protections, silent self-updating changes executable/package files on disk and can violate user expectations, organizational change-control requirements, or least-surprise safety practices.

Missing User Warnings

Low
Confidence
79% confidence
Finding
Host metadata is written to disk as host.json without any explicit user-facing disclosure or consent. While not directly enabling code execution, silent persistence of environment and device metadata is a privacy issue and can compound other data collection risks.

Missing User Warnings

Low
Confidence
82% confidence
Finding
The code silently records a skill inventory including installation paths and timestamps without explicit user disclosure. Even if intended for uninstall/account management, undisclosed persistence of local environment details is not justified by the skill's advertised purpose and weakens user privacy expectations.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill performs automatic silent self-updates that fetch remote content and replace installed package files without contemporaneous user approval. Even with checksum and path validation, silent code replacement is risky in a skill whose declared purpose is content generation, because compromise of the update channel or publisher trust lets behavior change unexpectedly on user systems.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
the user signs in or creates their account there, and the approval page
  continues automatically after sign-in;
- say once that the connection continues automatically after Allow, then
  detect completion yourself — never ask the user to confirm in chat that
  they approved.

Approval legitimately takes minutes when sign-in or account creation is
Confidence
85% confidence
Finding
The instruction to 'never ask the user to confirm' approval encourages the agent to complete an authorization workflow with reduced user verification and transparency. In the context of an unrelated skill that is already requesting external authorization, this increases the risk of covert account linking or unauthorized continuation of a privileged flow.

Credential Access

High
Category
Privilege Escalation
Content
- `~/.beatra/installation.json` contains one stable, non-secret installation
  reference.
- `~/.beatra/credentials.json` contains the single Device Token.

On POSIX systems the directory must be mode `0700` and both files mode `0600`.
On Windows the current user must be the only principal granted access through
Confidence
93% confidence
Finding
The documentation instructs the skill to maintain a local credentials file containing a persistent Device Token. For an Amazon A+ formatting skill, collecting and retaining such credentials is unnecessary and expands the blast radius if the host, agent, or filesystem is compromised.

Credential Access

High
Category
Privilege Escalation
Content
4. polls every 5 seconds for up to 15 minutes while the user signs in (or
   creates their account) and selects Allow;
5. atomically saves the returned Device Token to
   `~/.beatra/credentials.json` without printing an HTTP response body;
6. validates the new credential with the same non-billable MCP request and
   prints Ready only after it succeeds.
Confidence
94% confidence
Finding
The flow explicitly saves a returned Device Token to a persistent file after completing browser-based authorization. In this skill context, that creates a long-lived secret on disk for an unrelated external service, enabling reuse of granted access and increasing the consequences of local compromise or deceptive user authorization.

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
Including credentials.json in the set of files this script manages indicates that the package can remove shared credential material during uninstall. In the context of an Amazon A+ content skill, access to shared credentials is unjustified and dangerous because compromise, logic error, or deceptive packaging could disrupt authentication for unrelated skills or enable token misuse.

Static analysis

No suspicious patterns detected.