Back to skill

Security audit

apartment-kitchen-tour

Security checks for vulnerabilities and agentic risk

Overview

This skill does the advertised kitchen-photo video workflow, but it also grants and retains broader Beatra account authority than that narrow task needs.

Install only if you are comfortable granting Beatra a shared local device token with broader account capabilities than this kitchen-video task needs. Consider disabling automatic updates with the provided update command before use, and treat uploaded listing photos and Beatra account credits as sensitive.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
Over-Privileged Shared Bearer Credential and Unrestricted Tool Dispatch<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:34-36`; `scripts/mcp_client.py:1513-1517` **Vulnerability Type**: Excessive OAuth scopes and unrestricted authenticated MCP tool selection **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 command-line dispatcher accepts an arbitrary MCP tool name: ```python call = subparsers.add_parser("call", help="Call one tool with a JSON object on stdin") call.add_argument("tool_name") ``` That tool name is sent directly in an authenticated request: ```python return session.request( 2, "tools/call", {"name": tool_name, "arguments": arguments}, ) ``` ### Technical Analysis The declared purpose of this Skill is to animate a kitchen photograph into a video. Its legitimate requirements include uploading an artifact, discovering compatible video models, generating a video, reading relevant task results, and performing necessary billing operations. The requested credential additionally grants unrelated capabilities, including: - Image generation - Music generation - Speech generation - Voice reading and writing - Broad artifact and task access - Task cancellation The credential is shared across Beatra Skills rather than being isolated to this package. In addition, `mcp_client.py call` performs no local allowlist validation before loading the shared bearer token and submitting a requested tool name. This violates least privilege. Any local process or Agent instruction capable of invoking the bundled client can attempt an unrelated MCP tool call under the broader account authorization. Whether a particular call ultimately succeeds also depends on server-side tool availability and authorization enforcement, but the local client does not constrain calls to the Skill's declared function. ...[truncated 1230 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the shared full-scope token with a package-specific, least-privilege credential. 2. Remove scopes unrelated to this Skill, particularly: - `images:generate` - `music:generate` - `speech:generate` - `voices:read` - `voices:write` 3. Narrow artifact and task permissions to resources created by this package or installation where the service supports resource-scoped authorization. 4. Add a local allowlist of permitted MCP tools, such as the exact model, upload, video, task, wallet, and registration operations required by the documented workflow. 5. Reject unknown tool names before reading the credential or creating an MCP session. 6. Separate read-only wallet and task operations from billable or destructive permissions where supported. 7. Require explicit user confirmation immediately before any billable or destructive operation. 8. Add server-side enforcement binding the credential to the package slug and approved tool set; local validation alone should not be the security boundary. 9. Rotate existing shared credentials after deploying reduced scopes. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/authorize.py:345
Finding
Host and Agent-Environment Metadata Collection Exceeds Minimum Functional Requirements<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:345-370`, `scripts/authorize.py:455-466`; `scripts/mcp_client.py:1213-1221`, `scripts/mcp_client.py:1348-1365` **Vulnerability Type**: Device and execution-environment reconnaissance with remote transmission **Risk Level**: Medium ### Vulnerable Code The authorization helper inspects process-environment signatures: ```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" ``` It also obtains the local hostname: ```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] ``` Both values are incorporated into the remote 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, "package_version": PACKAGE_VERSION, ...[truncated 2644 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not collect or transmit the hostname by default. 2. Make device naming an explicit opt-in option, such as `--device-name`, with a clear disclosure that the value is sent to Beatra. 3. Default platform attribution to a generic value such as `unknown` unless it is essential for compatibility. 4. If platform detection is retained, disclose every collected and transmitted field before authorization. 5. Avoid persisting host metadata unless required; otherwise protect `host.json` with the same atomic-write and permission controls used for other private state. 6. Provide a telemetry-disable option that suppresses: - Hostname collection - Agent-platform detection - Installation registration - Source-platform attribution 7. Minimize server retention and correlation of hostname, platform, and stable installation identifiers. 8. Document the purpose, retention period, and deletion mechanism for the transmitted metadata. ]]>
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 (23)

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill declares no permissions while instructing use of a bundled Python client that performs file access, shell execution, network calls, credential handling, and updates. That mismatch prevents informed consent and hides the true trust boundary of the skill, which is a real security issue even if the capabilities are used for legitimate workflow steps.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The stated purpose is a simple kitchen-photo animation workflow, but the skill also includes authentication, persistent credential storage, generic MCP tool invocation, artifact upload, telemetry/registration, self-update, and uninstall/revocation behaviors. This broad hidden functionality materially expands attack surface and data exposure beyond user expectations, making abuse or accidental overreach much more dangerous.

Description-Behavior Mismatch

High
Confidence
95% confidence
Finding
The documentation directs the skill to use a bundled MCP client connected to a remote Beatra service and states that one approval grants access to image, video, music, speech, upload, model, and task tools. For a skill whose declared purpose is turning one kitchen photo into one short clip, this is overbroad capability and remote access that is not narrowly scoped to the advertised task, creating unnecessary attack surface and opportunity for data exfiltration or unauthorized tool use.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
The skill introduces persistent account authorization and storage of a long-lived Device Token in user files even though the stated use case is a narrow listing-photo animation workflow. This mismatch between advertised function and credentialed remote account access increases trust risk and can enable continued access beyond what a user would reasonably expect from a simple media transformation skill.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The skill requests a very broad OAuth scope set that far exceeds its stated purpose of turning a single kitchen photo into a short animation clip. Excess privileges increase blast radius if the token is abused, enabling access to unrelated generation, artifact, task, and wallet capabilities not needed for this workflow.

Context-Inappropriate Capability

Critical
Confidence
98% confidence
Finding
The requested scopes include generic MCP tool use, task read/cancel, and broad artifact permissions that exceed a narrowly scoped photo-to-video listing skill. This overbroad access could let the skill interact with unrelated tools or manipulate user tasks and data beyond the expected feature set.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The requested scopes include generic MCP tool use, task read/cancel, and broad artifact permissions that exceed a narrowly scoped photo-to-video listing skill. This overbroad access could let the skill interact with unrelated tools or manipulate user tasks and data beyond the expected feature set.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The requested scopes include generic MCP tool use, task read/cancel, and broad artifact permissions that exceed a narrowly scoped photo-to-video listing skill. This overbroad access could let the skill interact with unrelated tools or manipulate user tasks and data beyond the expected feature set.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
The file exposes a generic network-connected MCP client that can list tools, call arbitrary remote tools from stdin, upload local files, perform telemetry, and invoke package update behavior, which is far broader than the declared one-photo kitchen clip purpose. This mismatch expands the trust boundary substantially and enables the skill to act as a general remote capability conduit rather than a narrowly scoped media transformation tool.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The code fingerprints the host environment via environment variables and host.json, then records local installation inventory and registration telemetry unrelated to the stated creative task. While not immediately destructive, this collects contextual device/agent metadata beyond user expectations for a kitchen photo animation skill and increases privacy and tracking risk.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The skill implements a full self-update system that downloads manifests and archives from the network and rewrites installed package files. Even with integrity checks, this creates a powerful code-replacement channel unrelated to the advertised kitchen clip behavior, increasing supply-chain and persistence risk if the update infrastructure or signing assumptions fail.

Description-Behavior Mismatch

High
Confidence
96% confidence
Finding
The uninstall script handles shared device credentials, cross-skill inventory, and token revocation even though the advertised skill is only for kitchen-photo clip generation. That creates a clear scope mismatch: installing this skill also introduces code that can affect authentication state for other skills on the device, increasing trust and blast-radius beyond what a user would reasonably expect.

Context-Inappropriate Capability

High
Confidence
95% confidence
Finding
This code performs remote OAuth revocation and shared installation-state management, which is unrelated to generating a kitchen animation clip. Even if intended for uninstall hygiene, embedding network-capable auth-management logic inside a content-generation skill creates unnecessary privilege and a hidden control path over shared account state.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The bundled client is allowed to download and replace package-owned files automatically without separate confirmation. Any auto-update mechanism that performs network retrieval and local file replacement increases supply-chain risk; if the update channel, signing, or client is compromised, code can be changed on the host silently.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The document states that the client silently checks for updates and automatically installs newer releases without separate confirmation. Even though the text also describes integrity checks and rollback protections, unattended file replacement changes executable behavior without an upfront interactive warning or opt-in, which creates a meaningful trust and supply-chain risk if the update channel is ever compromised or if users are unaware that ordinary commands can modify their installation.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The documentation describes an automatic installation registration call that sends package and environment metadata and writes a local cache, but it does not clearly disclose this behavior to end users or require consent. Even if the data is described as non-billable and non-secret, silent telemetry can expose usage patterns and host environment details, creating privacy and trust risks.

Missing User Warnings

Medium
Confidence
83% confidence
Finding
The authorization request sends host platform and device name metadata to the remote service, but the user-facing prompts only discuss approval and do not clearly disclose this metadata collection at the moment it occurs. Even if limited, hostname and platform data can identify a user's environment and should be transparently disclosed because this skill's purpose does not obviously require it.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
maybe_auto_update() performs silent best-effort updates during normal execution, allowing installed files to change without user-facing disclosure at the moment the skill runs. That behavior undermines auditability and informed consent, especially for a skill whose declared purpose is simple media generation from a photo.

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
84% confidence
Finding
This documents storage of a Device Token in a persistent local credential file. While secure local storage is common, in this skill context it still represents credential access and retention beyond the minimally expected behavior for a simple kitchen clip tool, so compromise of the local account or skill environment could expose reusable remote-service credentials.

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
82% confidence
Finding
The helper automatically saves the returned Device Token to a persistent credential file after authorization. Even though the text instructs safe handling and avoids printing the token, persisting a reusable bearer token locally creates a credential theft target that is broader than the skill's advertised single-purpose media workflow would suggest.

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
The script explicitly targets credentials.json as part of managed state, showing that this skill package is aware of and authorized to manipulate shared credential material. In the context of a simple media skill, access to shared credentials is over-privileged and dangerous because compromise or misuse could affect all installed skills tied to the same device 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
92% confidence
Finding
The _device_token function reads an access token directly from credentials.json so it can call the remote revocation endpoint. Direct token retrieval by a skill uninstall script is sensitive credential access and is disproportionate to the skill's declared purpose, making it a real privilege-boundary issue even if no exfiltration is present.

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 CLI explicitly exposes self-update behavior for the installed package, and elsewhere in the file that updater can replace package contents on disk. In the context of a narrowly described media skill, self-modification materially increases the risk of post-install capability drift, persistence, and supply-chain compromise.

Static analysis

No suspicious patterns detected.