Back to skill

Security audit

Zhongcao OOTD Lookbook Maker

Security checks for vulnerabilities and agentic risk

Overview

The skill can perform the promised lookbook workflow, but it also uses broad shared Beatra account authority and silently self-updates executable files.

Install only if you are comfortable giving Beatra a shared device authorization with broad media, task, artifact, and wallet-related authority, and with this package silently updating its own files. Consider disabling automatic updates with `python3 scripts/mcp_client.py update --auto off`, and revoke the Beatra device authorization from the console if you stop using it.

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)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/authorize.py:31
Finding

Overprivileged Shared Device Credential and Unrestricted Tool Invocation

Content
View full analysis
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}, ) ``` ### Technical Analysis The Skill's declared functionality requires image generation or editing, user-selected asset uploads, model discovery, task management, wallet spending for approved work, and optional Xiaohongshu lookup. The requested bearer-token scope also grants unrelated video generation, music generation, speech generation, voice reading, and voice writing. The credential is a shared device credential stored under `~/.beatra`, rather than a narrowly scoped credential dedicated to this package. In addition, the bundled client exposes a generic `call` command that forwards any supplied MCP tool name. No local allowlist limits calls to the operations required by this Skill. This ...[truncated 1769 chars]
Remediation
View remediation

other

Warning
Location
scripts/authorize.py:340
Finding

Hostname and Agent-Environment Telemetry Collected During Authorization

Content
View full analysis
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] ``` The collected values are included in the authorization request: ```python external_reference = _installation_reference(state_dir) 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) ``` ### ...[truncated 2579 chars]
Remediation
View remediation

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/mcp_client.py:516
Finding

Automatic Remote Replacement of Executable Skill Files Is Enabled by Default

Content
View full analysis
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 def set_auto_update( enabled: bool, *, state_dir: Path | None = None, install_root: Path | None = None, ) -> None: resolved_state = state_dir or Path.home() / ".beatra" resolved_root = (install_root or _current_install_root()).resolve() update_home = _update_home(resolved_state, resolved_root) state = _read_update_state(update_home) state["auto_update"] = bool(enabled) _write_private_json(update_home / "state.json", state) ``` Ordinary commands silently retrieve and apply updates: ```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_s ...[truncated 4508 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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 (39)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

A user-facing content-creation skill should not unexpectedly include uninstall logic, token revocation, local state mutation, and removal of credential files without very clear separation and disclosure. These capabilities increase the chance of destructive local changes, account disruption, or accidental loss of authentication state under the guise of a benign creative workflow.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

A user-facing content-creation skill should not unexpectedly include uninstall logic, token revocation, local state mutation, and removal of credential files without very clear separation and disclosure. These capabilities increase the chance of destructive local changes, account disruption, or accidental loss of authentication state under the guise of a benign creative workflow.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

A user-facing content-creation skill should not unexpectedly include uninstall logic, token revocation, local state mutation, and removal of credential files without very clear separation and disclosure. These capabilities increase the chance of destructive local changes, account disruption, or accidental loss of authentication state under the guise of a benign creative workflow.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 97)May include surrounding context.

md
Use only this package's bundled `scripts/mcp_client.py` for every remote

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 180)May include surrounding context.

md
Use only this package's bundled `scripts/mcp_client.py` for every remote

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 181)May include surrounding context.

md
Use only this package's bundled `scripts/mcp_client.py` for every remote

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 182)May include surrounding context.

md
Use only this package's bundled `scripts/mcp_client.py` for every remote

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

The manifest declares device-bearer authentication and references a local credential file at ~/.beatra/credentials.json, which indicates the skill can operate with persisted bearer credentials. If a malicious or compromised skill runtime can access or misuse those credentials, it could perform authenticated actions against the MCP service and potentially access account-scoped data without sufficient user awareness.

Content

Scanner excerpt · manifest.json (reported line 81)May include surrounding context.

json
},
  "mcp": {
    "authentication": "device-bearer",
    "credential_file": "~/.beatra/credentials.json",
    "name": "beatra",
    "transport": "streamable-http",
    "url": "https://mcp.beatra.ai/mcp"

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/installation-and-auth.md (reported line 14)May include surrounding context.

text

They share the one full-scope Device Token stored in
`~/.beatra/credentials.json`. Installing or switching packages must not trigger
another authorization when that credential is already valid. Do not add,
enable, trust, or configure a host Beatra Connector. Never print or move the
token into command arguments, environment variables, logs, chat, or another

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/installation-and-auth.md (reported line 21)May include surrounding context.

text

They share the one full-scope Device Token stored in
`~/.beatra/credentials.json`. Installing or switching packages must not trigger
another authorization when that credential is already valid. Do not add,
enable, trust, or configure a host Beatra Connector. Never print or move the
token into command arguments, environment variables, logs, chat, or another

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/installation-and-auth.md (reported line 49)May include surrounding context.

text

They share the one full-scope Device Token stored in
`~/.beatra/credentials.json`. Installing or switching packages must not trigger
another authorization when that credential is already valid. Do not add,
enable, trust, or configure a host Beatra Connector. Never print or move the
token into command arguments, environment variables, logs, chat, or another

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/mcp-connection.md (reported line 10)May include surrounding context.

text

They share the one full-scope Device Token stored in
`~/.beatra/credentials.json`. Installing or switching packages must not trigger
another authorization when that credential is already valid. Do not add,
enable, trust, or configure a host Beatra Connector. Never print or move the
token into command arguments, environment variables, logs, chat, or another

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/authorize.py (reported line 207)May include surrounding context.

python
```

They share the one full-scope Device Token stored in
`~/.beatra/credentials.json`. Installing or switching packages must not trigger
another authorization when that credential is already valid. Do not add,
enable, trust, or configure a host Beatra Connector. Never print or move the
token into command arguments, environment variables, logs, chat, or another

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/mcp_client.py (reported line 1025)May include surrounding context.

python
```

They share the one full-scope Device Token stored in
`~/.beatra/credentials.json`. Installing or switching packages must not trigger
another authorization when that credential is already valid. Do not add,
enable, trust, or configure a host Beatra Connector. Never print or move the
token into command arguments, environment variables, logs, chat, or another

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The requested OAuth scope bundle is far broader than the skill’s stated purpose of generating OOTD/lookbook content. In addition to image/artifact capabilities, it asks for wallet spending, task control, speech/music/video generation, and voice read/write, which materially increases blast radius if the credential is misused, stolen, or if the backend over-honors permissions. In the context of a fashion-posting skill, this mismatch is especially suspicious because the extra capabilities are not necessary to perform the advertised function.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
86% confidence
Finding

The code stores a bearer access token in plaintext JSON on disk under ~/.beatra/credentials.json. Even with restrictive POSIX permissions, plaintext bearer-token storage creates a high-impact secret-at-rest risk: any local compromise, backup leakage, malicious same-user process, or misconfigured environment can expose a token that carries the skill’s overly broad scopes. The danger is amplified here because the granted permissions include unrelated high-risk capabilities such as wallet spending and task control.

Content

Scanner excerpt · scripts/authorize.py (reported line 514)May include surrounding context.

python
scope = _required_string(polled, "scope")
            if set(scope.split()) != set(SCOPE.split()):
                raise RuntimeError("Beatra authorization returned an unsupported scope")
            credential_path = state_dir / "credentials.json"
            _atomic_json(
                credential_path,
                {

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

This client contains a full self-update pipeline that downloads manifests and ZIP archives from remote infrastructure and then replaces local package files on disk. That capability is unrelated to an OOTD lookbook-making skill, materially expands the attack surface, and creates a supply-chain risk: compromise of the vendor update channel or signing/checksum workflow would let remote content modify the installed codebase.

Content

No source excerpt is available for this finding.

Self-Modification

High
Category
Rogue Agent
Confidence
94% confidence
Finding

The skill exposes self-update/self-modification functionality through its CLI and broader code path, enabling local package bytes to be replaced from remote content. In a skill whose purpose is image/lookbook generation and Xiaohongshu research, self-modification is unjustified and significantly increases the blast radius of any server, CDN, or distribution compromise.

Content

Scanner excerpt · scripts/mcp_client.py (reported line 1503)May include surrounding context.

python
)
    update = subparsers.add_parser(
        "update",
        help="Check, install, or configure Beatra package self-updates",
    )
    update.add_argument(
        "--check",

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

The presence of credentials.json in the list of files this script may remove shows the skill is aware of and authorized to manipulate shared credential material. For a non-authentication, non-admin fashion skill, handling credential files materially increases the blast radius of the package and creates risk of credential destruction or misuse if the script is modified or abused.

Content

Scanner excerpt · scripts/uninstall.py (reported line 40)May include surrounding context.

python
#: 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",

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

This code can submit a bearer token to a revocation endpoint and then delete shared local state files under ~/.beatra, affecting authentication and operation of all installed skills on the device. In the context of a fashion-content skill, that capability is unjustified and dangerous because compromise, misuse, or packaging abuse could cause denial of service across unrelated skills and destroy shared platform state.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
98% confidence
Finding

The _device_token function reads an access token from credentials.json and passes it to revocation logic, giving this skill direct access to bearer-token material. Direct credential access by a skill unrelated to authentication is dangerous because any future code change, compromise, or malicious repackaging could exfiltrate or misuse the token, and even current behavior enables cross-skill service disruption by revocation.

Content

Scanner excerpt · scripts/uninstall.py (reported line 109)May include surrounding context.

python
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):

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill declares no explicit tool scope even though it is documented as using sensitive capabilities including environment access, file read/write, network, and shell. Without a least-privilege boundary, a fashion-content skill can exercise broader host powers than users would reasonably expect, increasing the blast radius of misuse, compromise, or prompt-injection-driven tool invocation.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The documentation explicitly describes silent automatic self-update and replacement of local package files, which is unrelated to the core lookbook-making function. Even with integrity checks, self-updating code expands the trust boundary and can introduce unreviewed behavior changes or supply-chain risk on a host that expected a static creative skill.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The manifest hardcodes separate English, Japanese, and Chinese localized descriptions and titles, but nowhere in this file indicates that the user can choose or override the language/locale. Under the policy, forcing a specific language or locale without explicit opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · manifest.json (reported line 9)May include surrounding context.

json
"icon": "https://beatra.ai/textures/icons/zhongcao-ootd-lookbook-maker-0.1.1.png",
  "localized": {
    "en": {
      "description": "Create a coordinated REDnote (Xiaohongshu) OOTD lookbook from outfit photos or a styling idea. Build a vertical 3:4 fashion carousel with a cover, full-look outfit image, styling-detail image, and lifestyle scene, then shape a ready-to-publish fashion recommendation post with title ideas, caption angles, and tags. Use this AI outfit image maker for Xiaohongshu outfit posts, OOTD photos, fashion lookbooks, clothing recommendation visuals, creator style diaries, and brand collaboration campaigns. Optionally it reads Xiaohongshu itself — the notes already running for the topic, one page of a note's top comments, and an account's own recent notes — so Xiaohongshu research, competitor note analysis and comment analysis rest on the platform instead of on guesswork.",
      "display_name": "Zhongcao OOTD Lookbook Maker",
      "summary": "Turn outfit photos and styling ideas into a coordinated vertical 3:4 REDnote OOTD lookbook, with cover, full-look, detail, and lifestyle images plus a ready-to-post fashion story.",
      "tags": [

Static analysis

No suspicious patterns detected.