Back to skill

Security audit

BeautyPlus portrait beauty, outfit change, photo restoration

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a real BeautyPlus image-editing integration, but it needs review because it can fetch arbitrary URLs, upload media to cloud storage, and relay server-provided billing links.

Install only in an isolated environment with restricted network access. Prefer local image files or trusted public HTTPS URLs, protect BP and IM credentials, pin dependencies before production use, and do not trust billing links unless they are verified BeautyPlus domains.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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
Findings (5)

T01 · Skill Instruction Hijacking

Error
Location
scripts/beautyplus_ai.py:121
Finding

Untrusted Server Responses Can Inject Links into Mandatory Agent Replies

Content
View full analysis
dict: """Structured stdout for POST /skill/consume.json failures (see docs/errors-and-polling.md).""" api_code = e.code detail = e.msg if api_code == 60001: err = "membership_required" agent_instruction = ( "MANDATORY (user-visible): Quota consume failed — membership or eligible subscription " "is required (api_code 60001). You must tell the user clearly, following the server " "**detail** (API msg). If this JSON has **pricing_url**, include that link in your reply; " "if not, quote or paste the full **detail** so any links in the server message reach the user. " "Do not retry run-task expecting success by only changing --task or --params." ) elif api_code == 60002: err = "credit_required" agent_instruction = ( "MANDATORY (user-visible): Quota consume failed — insufficient credits (api_code 60002). " "You must tell the user they need more credits or a subscription before this API can run, " "using the server **detail** (API msg) as the source of truth. If this JSON has **pricing_url**, " "include that link; if not, quote or paste the full **detail** so links from the API are visible. " "Do not retry run-task or only tweak --task/--params expecting this to clear; do not treat as success." ) ``` The URL extraction and selection logic is: ```python def _https_urls_from_text(text: str) -> list[str]: """Extract https URLs from API msg / detail (e.g. consume.json meta.msg).""" if not isinstance(text, str) or not text.strip(): return [] out: list[ ...[truncated 2358 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
sdk/core/client.py:262
Finding

Arbitrary URL Fetching Enables SSRF and Subsequent Exfiltration Through OSS Upload

Content
View full analysis
Tuple[str, int]: """Stream-download URL to a temp file (bounded size). Caller must unlink path.""" preview = api.safe_url_preview(url) conn_t = url_download_connect_timeout() read_t = url_download_read_timeout() max_b = url_download_max_bytes() headers = {"User-Agent": USER_AGENT} try: with requests.get( url, stream=True, timeout=(conn_t, read_t), headers=headers, ) as resp: try: resp.raise_for_status() except requests.HTTPError as e: code = getattr(resp, "status_code", "?") raise RuntimeError( f"Input URL HTTP {code} (url={preview}). " "Signed URLs may be expired; shell may have broken the URL at '&' without quotes." ) from e fd, path = tempfile.mkstemp(prefix="openclaw_in_", suffix=".bin") total = 0 try: with os.fdopen(fd, "wb") as out: for chunk in resp.iter_content(chunk_size=65536): if not chunk: continue total += len(chunk) if total > max_b: raise RuntimeError( f"Input URL download exceeds max bytes ({max_b}); url={preview}. " "Set MT_AI_URL_MAX_BYTES to raise the cap or use a smaller file." ) out.write(chunk) ``` The response is ...[truncated 3643 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/requirements.txt:1
Finding

Runtime Installation Uses Floating Dependency Versions Without Integrity Verification

Content
View full analysis
=1.2.0 pytest>=7.2.1 requests>=2.28.2 ``` The Skill invokes pip at runtime: ```python r = subprocess.run( [sys.executable, "-m", "pip", "install", "-q", "-r", str(req)], ) ``` The Skill instructions make this an expected setup step: ```bash python3 {baseDir}/scripts/beautyplus_ai.py install-deps ``` ### Technical Analysis All dependencies use lower-bound constraints. No exact versions, lock file, artifact hashes, or restricted package index are provided. A future release satisfying the lower bound can therefore be selected without any project review. Python package installation and subsequent imports can execute package-controlled code. If an upstream account, release process, package index, or dependency is compromised, invoking the documented `install-deps` flow may install and execute malicious code with the same privileges as the agent. `pytest` is also included in runtime requirements even though it is a development and testing tool. This unnecessarily expands the dependency graph and supply-chain attack surface. No direct evidence shows that the currently named packages are malicious. The issue is the uncontrolled installation policy. ### Attack Path 1. The agent follows the mandatory dependency installation step. 2. Pip queries its configured package index. 3. It selects any current or future package version satisfying each `>=` constraint. 4. A compromised or malicious upstream version is downloaded without hash verification. 5. Package installation or later import executes attacker-controlled Python code. 6. That code inherits the process user's filesystem, environment, credential, and network access. ### Impact Assessment A compromised de ...[truncated 319 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
sdk/cli.py:125
Finding

Secret Key Can Be Supplied Through a Process-Visible Command-Line Argument

Content
View full analysis
/cmdline` on supported systems. - Shell history. - Job schedulers and orchestration metadata. - Audit logs, terminal recording, and command telemetry. - Diagnostic output collected by host platforms. The project documentation correctly advises that bot tokens should not be supplied as CLI arguments, but the same protection is not applied to `BP_SK`. ### Attack Path 1. A user or automation invokes `sdk/cli.py --sk ...`. 2. The complete argument vector remains visible while the process is running and may be retained after execution. 3. Another local user, monitoring agent, support bundle, shell-history reader, or log collector obtains the command line. 4. The exposed `BP_SK` is reused to authenticate signed BeautyPlus API requests. ### Impact Assessment Exposure compromises the BeautyPlus secret key associated with the configured tenant. An attacker may be able to make signed API requests, consume paid quota, access tenant-authorized operations, or impersonate the legitima ...[truncated 115 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/beautyplus_ai.py:257
Finding

Task Inputs and Result URLs Are Persisted Without Enforced Restrictive Permissions

Content
View full analysis
None: _ensure_state_dir() with open(LAST_TASK_FILE, "w", encoding="utf-8") as f: json.dump(record, f, indent=2, ensure_ascii=False) HISTORY_DIR.mkdir(parents=True, exist_ok=True) ts = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S") hist_path = HISTORY_DIR / f"task_{ts}.json" with open(hist_path, "w", encoding="utf-8") as f: json.dump(record, f, indent=2, ensure_ascii=False) history_files = sorted(HISTORY_DIR.glob("task_*.json")) if len(history_files) > 50: for old in history_files[:-50]: old.unlink(missing_ok=True) ``` Directory creation also does not specify a restrictive mode: ```python def _ensure ...[truncated 1579 chars]
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (102)

Tainted flow: 'token' from os.environ.get (line 750, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/beautyplus_ai.py (reported line 759)May include surrounding context.

python
}
            )
            return 1
        r = requests.get(
            f"https://api.telegram.org/bot{token}/getFile",
            params={"file_id": args.telegram_file_id},
            timeout=(CONNECT_TIMEOUT, READ_TIMEOUT),

Tainted flow: 'dl_url' from os.environ.get (line 780, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/beautyplus_ai.py (reported line 781)May include surrounding context.

python
)
        filename = f"tg_{uuid.uuid4().hex[:8]}.{extension}"
        dl_url = f"https://api.telegram.org/file/bot{token}/{file_path}"
        r2 = requests.get(
            dl_url,
            timeout=skill_config.url_download_timeout_tuple(),
            headers={

Tainted flow: 'feishu_token' from os.environ.get (line 805, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/beautyplus_ai.py (reported line 813)May include surrounding context.

python
{"error": "FEISHU_APP_TOKEN or --feishu-app-token required"}
            )
            return 1
        r = requests.get(
            f"https://open.feishu.cn/open-apis/im/v1/messages/"
            f"{args.feishu_message_id}/resources/{args.feishu_image_key}",
            params={"type": "image"},

Tainted flow: 'token' from os.environ.get (line 45, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/telegram_send_image.py (reported line 82)May include surrounding context.

python
img_bytes = r.content
        filename = image_source.split("?")[0].split("/")[-1] or "image.jpg"
        files = {"photo": (filename, img_bytes, "image/jpeg")}
        resp = requests.post(
            f"{TELEGRAM_API_BASE}/bot{token}/sendPhoto",
            data=data,
            files=files,

Tainted flow: 'token' from os.environ.get (line 45, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/telegram_send_image.py (reported line 94)May include surrounding context.

python
sys.exit(1)
        with open(image_source, "rb") as f:
            files = {"photo": (os.path.basename(image_source), f, "image/jpeg")}
            resp = requests.post(
                f"{TELEGRAM_API_BASE}/bot{token}/sendPhoto",
                data=data,
                files=files,

Tainted flow: 'token' from os.environ.get (line 35, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/telegram_send_video.py (reported line 87)May include surrounding context.

python
except Exception as exc:
                print(f"[telegram] Thumbnail download error: {exc}, skipping", file=sys.stderr)

        resp = requests.post(
            f"{TELEGRAM_API_BASE}/bot{token}/sendVideo",
            data=data,
            files=files,

Tainted flow: 'token' from os.environ.get (line 35, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/telegram_send_video.py (reported line 137)May include surrounding context.

python
def send_text_message(token: str, chat_id: str, text: str) -> tuple[dict | None, str | None]:
    """Send plain text (URLs are linkified by clients)."""
    print("[telegram] Sending download link text", file=sys.stderr)
    resp = requests.post(
        f"{TELEGRAM_API_BASE}/bot{token}/sendMessage",
        json={"chat_id": chat_id, "text": text},
        timeout=(CONNECT_TIMEOUT, 30),

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

Cloud object storage upload capabilities add another outbound data sink for user media and potentially credentials, which is security-relevant in an agent skill handling arbitrary inputs. If this behavior is not clearly disclosed and tightly scoped, users may not realize their files can be transferred to third-party storage services.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Cloud object storage upload capabilities add another outbound data sink for user media and potentially credentials, which is security-relevant in an agent skill handling arbitrary inputs. If this behavior is not clearly disclosed and tightly scoped, users may not realize their files can be transferred to third-party storage services.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Cloud object storage upload capabilities add another outbound data sink for user media and potentially credentials, which is security-relevant in an agent skill handling arbitrary inputs. If this behavior is not clearly disclosed and tightly scoped, users may not realize their files can be transferred to third-party storage services.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Cloud object storage upload capabilities add another outbound data sink for user media and potentially credentials, which is security-relevant in an agent skill handling arbitrary inputs. If this behavior is not clearly disclosed and tightly scoped, users may not realize their files can be transferred to third-party storage services.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Cloud object storage upload capabilities add another outbound data sink for user media and potentially credentials, which is security-relevant in an agent skill handling arbitrary inputs. If this behavior is not clearly disclosed and tightly scoped, users may not realize their files can be transferred to third-party storage services.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Cloud object storage upload capabilities add another outbound data sink for user media and potentially credentials, which is security-relevant in an agent skill handling arbitrary inputs. If this behavior is not clearly disclosed and tightly scoped, users may not realize their files can be transferred to third-party storage services.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Cloud object storage upload capabilities add another outbound data sink for user media and potentially credentials, which is security-relevant in an agent skill handling arbitrary inputs. If this behavior is not clearly disclosed and tightly scoped, users may not realize their files can be transferred to third-party storage services.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Cloud object storage upload capabilities add another outbound data sink for user media and potentially credentials, which is security-relevant in an agent skill handling arbitrary inputs. If this behavior is not clearly disclosed and tightly scoped, users may not realize their files can be transferred to third-party storage services.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Cloud object storage upload capabilities add another outbound data sink for user media and potentially credentials, which is security-relevant in an agent skill handling arbitrary inputs. If this behavior is not clearly disclosed and tightly scoped, users may not realize their files can be transferred to third-party storage services.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Cloud object storage upload capabilities add another outbound data sink for user media and potentially credentials, which is security-relevant in an agent skill handling arbitrary inputs. If this behavior is not clearly disclosed and tightly scoped, users may not realize their files can be transferred to third-party storage services.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Cloud object storage upload capabilities add another outbound data sink for user media and potentially credentials, which is security-relevant in an agent skill handling arbitrary inputs. If this behavior is not clearly disclosed and tightly scoped, users may not realize their files can be transferred to third-party storage services.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Cloud object storage upload capabilities add another outbound data sink for user media and potentially credentials, which is security-relevant in an agent skill handling arbitrary inputs. If this behavior is not clearly disclosed and tightly scoped, users may not realize their files can be transferred to third-party storage services.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Cloud object storage upload capabilities add another outbound data sink for user media and potentially credentials, which is security-relevant in an agent skill handling arbitrary inputs. If this behavior is not clearly disclosed and tightly scoped, users may not realize their files can be transferred to third-party storage services.

Content

No source excerpt is available for this finding.

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

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

md
---
name: beautyplus-ai
description: "AI image editing and beautification suite for portrait retouching, body reshaping (breast/butt), AI hair styling, AI clothes / cosplay change, expression edits, photo restoration & upscaling, and artistic filters."
version: 1.1.0
author: BeautyPlus
metadata: {"openclaw":{"emoji":"🖼️","requires":{"bins":["python3"],"env":{"BP_AK":{"required":true},"BP_SK":{"required":true}}},"tags":["image-processing","portrait-retouching","body-reshape","virtual-try-on","ai-cosplay","photo-restoration","image-upscaling","makeover"]}}
---

# BeautyPlus Skills & API

> **`{baseDir}` placeholde

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
through `beautyplus_ai.py`; agents do not need to open `client.py` or

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · scripts/batch_effects_audit.py (reported line 89)May include surrounding context.

python
def _read_ak_sk_from_env_file() -> tuple[str, str]:
    ak = os.environ.get("BP_AK", "").strip()
    sk = os.environ.get("BP_SK", "").strip()
    env_path = SCRIPTS_DIR / ".env"
    if not env_path.exists():
        return ak, sk
    try:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · scripts/batch_effects_audit.py (reported line 229)May include surrounding context.

python
def _read_ak_sk_from_env_file() -> tuple[str, str]:
    ak = os.environ.get("BP_AK", "").strip()
    sk = os.environ.get("BP_SK", "").strip()
    env_path = SCRIPTS_DIR / ".env"
    if not env_path.exists():
        return ak, sk
    try:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · scripts/beautyplus_ai.py (reported line 70)May include surrounding context.

python
def _read_ak_sk_from_env_file() -> tuple[str, str]:
    ak = os.environ.get("BP_AK", "").strip()
    sk = os.environ.get("BP_SK", "").strip()
    env_path = SCRIPTS_DIR / ".env"
    if not env_path.exists():
        return ak, sk
    try:

Static analysis

No suspicious patterns detected.