Back to skill

Security audit

Best Practice Skill Creator

Security checks for vulnerabilities and agentic risk

Overview

The skill has a legitimate media-to-skill purpose, but its default setup exposes a plaintext API key and sends screenshots or video frames to a nonstandard remote endpoint without strong disclosure or review controls.

Review this skill before installing. Do not use the bundled API key, rotate it if it is yours, and replace the default endpoint with a trusted provider. Only process videos or screenshots that are safe to send to that provider, and manually inspect any generated SKILL.md before installing or publishing it.

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

T09 · Insecure Skill Coding Practices

Error
Location
config.yaml:10
Finding
Hard-Coded API Credential and Unrestricted Transmission to a Nonstandard Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `config.yaml:10-13`; related request sink at `src/mllm/openai_provider.py:27-39` **Vulnerability Type**: Hard-coded secret and unsafe external endpoint configuration **Risk Level**: High ### Vulnerable Code ```yaml openai: api_key: "sk-9Ld6xm13fTFHmfQYigDyStTcVrXEjxerlLxizlu6nRs" base_url: "https://api.cloubic.com/v1" model: "gemini-3.1-pro-preview" ``` The configured credential and endpoint are used by the following request code: ```python url = f"{self.base_url.rstrip('/')}/chat/completions" headers = { "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json", } with httpx.Client(timeout=120) as client: resp = client.post(url, json=payload, headers=headers) resp.raise_for_status() data = resp.json() ``` ### Technical Analysis A live-looking API credential is committed in plaintext configuration. Anyone with access to the source package or repository history can retrieve and attempt to use it. The provider named `openai` defaults to `https://api.cloubic.com/v1`, which is not an official OpenAI endpoint, while its configured model is a Gemini model identifier. The application does not enforce a trusted-host allowlist, verify that the endpoint corresponds to the selected provider, or warn before sending the bearer token and media payload to a custom host. Environment-variable support does not mitigate the committed secret because the plaintext value remains the fallback whenever `MLLM_API_KEY` is absent. ### Attack Path 1. An attacker obtains the distributed project files or repository history. 2. The attacker extracts the plaintext API credential from `config.yaml`. 3. The attacker attempts to use the credential against its associated API, potentially consuming quota or incurring charges. 4. Independently, a user runs the documented default configuration without overriding the endpoint. 5. The application sends the configured bearer credential, task de ...[truncated 896 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Revoke and rotate the exposed credential immediately. 2. Remove the credential from the current repository and all reachable repository history. 3. Replace committed secrets with empty placeholders and require `MLLM_API_KEY` through an environment variable or secret manager. 4. Configure official provider endpoints as defaults. 5. Maintain an explicit allowlist of approved schemes and hostnames for each provider. 6. Reject non-HTTPS endpoints and provider/model combinations that do not match expected configurations. 7. Require explicit user confirmation before sending credentials or media to a custom endpoint. 8. Add automated secret scanning to pre-commit hooks and CI. 9. Use credentials with minimum permissions, limited quota, short validity, and service-specific scope. ]]>

T01 · Skill Instruction Hijacking

Error
Location
src/skill_generator.py:36
Finding
Untrusted Multimodal Model Output Is Written Directly into Installable Agent Instructions<![CDATA[ ## Vulnerability Details **File Location**: `src/analyzer.py:5-54, 73-74`; `src/skill_generator.py:36-88` **Vulnerability Type**: Indirect prompt injection and unsafe generation of Agent instructions **Risk Level**: High ### Vulnerable Code The analyzer embeds the user-controlled description directly in the model prompt and asks the model to create executable-style Agent instructions: ```python ANALYSIS_PROMPT = """\ You are an expert at analyzing task demonstrations and extracting structured best practices. You are given: 1. A sequence of images (frames from a video or screenshots) showing someone performing a task. 2. A text description of what the task accomplishes. ## Task Description {description} ## Your Job Analyze the images in order and produce a structured best practice document with the following sections: ### 1. TASK_NAME A short, kebab-case identifier for this task (e.g., "setup-ci-cd-pipeline"). ### 2. TASK_TITLE A human-readable title (e.g., "Set Up CI/CD Pipeline with GitHub Actions"). ### 3. TASK_DESCRIPTION A one-sentence description suitable for an AI agent's skill description field. Include trigger phrases starting with "Use when..." followed by 3-5 specific scenarios. Aim for 20-40 words total. ### 4. TASK_EMOJI A single emoji that represents this task. ### 5. REQUIRED_TOOLS A JSON list of CLI tools/binaries required (e.g., ["git", "docker", "kubectl"]). ### 6. REQUIRED_ENV A JSON list of environment variables needed (e.g., ["GITHUB_TOKEN"]). ### 7. STEPS A detailed, numbered list of steps. For each step: - Step number and title - What to do (imperative instructions) - Any commands to run (in code blocks) - Expected outcome - Common pitfalls to avoid ### 8. BEST_PRACTICES A bullet list of key best practices, tips, and warnings observed from the demonstration. ### 9. SKILL_INSTRUCTIONS Write the full body of an agent skill instruction document. This should be written as if you are instructing an AI agent on how to pe ...[truncated 4092 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Explicitly state in the analysis prompt that text and commands found in descriptions, screenshots, and videos are untrusted content to be analyzed, not instructions to follow. 2. Separate source data from control instructions using structured message boundaries and provider-supported system instructions. 3. Validate every generated field against a strict schema: - Require a valid kebab-case Skill name. - Restrict emoji and operating-system metadata. - Allowlist required binaries and environment-variable names where practical. - Reject malformed or unexpected sections. 4. Scan generated instructions for high-risk behaviors, including secret access, credential transmission, remote script execution, persistence, destructive commands, privilege escalation, and instructions to override safety constraints. 5. Require a mandatory human review step before installation or publication. 6. Present a security-focused diff showing commands, URLs, required tools, required environment variables, and sensitive-resource references. 7. Mark generated output as untrusted until it passes validation; do not describe it as fully compliant merely because it has valid frontmatter. 8. Consider generating a constrained intermediate representation and rendering approved instructions from that representation rather than accepting free-form model output. 9. Add adversarial tests using prompt injections embedded in descriptions, screenshots, and video frames. ]]>

other

Warning
Location
src/mllm/openai_provider.py:12
Finding
Sensitive Screenshots and Video Frames Are Uploaded Without a Prominent Destination-Specific Privacy Warning<![CDATA[ ## Vulnerability Details **File Location**: `src/mllm/openai_provider.py:12-39`; equivalent behavior at `src/mllm/gemini_provider.py:12-40`; documentation at `SKILL.md:14-23, 48-56` **Vulnerability Type**: Undisclosed external transmission of potentially sensitive media **Risk Level**: Medium ### Vulnerable Code The OpenAI-compatible provider embeds every processed image in the external request: ```python def analyze_images( self, images_base64: list[str], prompt: str ) -> MLLMResponse: content = [{"type": "text", "text": prompt}] for img_b64 in images_base64: content.append( { "type": "image_url", "image_url": { "url": f"data:image/jpeg;base64,{img_b64}", "detail": "high", }, } ) payload = { "model": self.model, "messages": [{"role": "user", "content": content}], "max_tokens": 4096, } url = f"{self.base_url.rstrip('/')}/chat/completions" headers = { "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json", } with httpx.Client(timeout=120) as client: resp = client.post(url, json=payload, headers=headers) ``` The Gemini provider performs the same transmission using inline data: ```python parts = [{"text": prompt}] for img_b64 in images_base64: parts.append( { "inline_data": { "mime_type": "image/jpeg", "data": img_b64, } } ) payload = { "contents": [{"parts": parts}], "generationConfig": { "maxOutputTokens": 4096, "temperature": 0.2, }, } url = ( f"{self.base_url.rstrip('/')}/models/{self.model}:generateContent" f"?key={self.api_key}" ) headers = {"Content-Type": "application/json"} with httpx.Client(timeout=120) as client: resp = client.post(url, json=payload, headers=headers) ``` ### Technical ...[truncated 1814 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Display a preflight disclosure before every upload, identifying: - The destination hostname. - The provider and model. - The categories of data being transmitted. - The number of images or frames being uploaded. 2. Require explicit user consent, especially for custom or nonstandard endpoints. 3. Add an optional local-only processing mode. 4. Provide automated redaction for likely credentials, tokens, email addresses, and other sensitive screen regions. 5. Show frame previews and allow users to remove individual frames before transmission. 6. Minimize transmitted data by sampling only necessary frames and reducing resolution where possible. 7. Document provider retention and privacy implications. 8. Prevent silent endpoint changes and clearly distinguish official endpoints from OpenAI-compatible third-party services. 9. Warn users not to process recordings containing secrets or regulated data unless the selected provider is approved for that data. ]]>

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding
Unpinned Runtime Dependencies Permit Unreviewed Future Releases<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt:1-4` **Vulnerability Type**: Non-reproducible dependency resolution and supply-chain exposure **Risk Level**: Medium ### Vulnerable Code ```text httpx>=0.27.0 Pillow>=10.0.0 opencv-python>=4.8.0 PyYAML>=6.0 ``` ### Technical Analysis All runtime dependencies use open-ended minimum-version constraints. A future installation can therefore resolve package versions that did not exist when the Skill was reviewed. No lock file or package hashes are present in the audited project structure. This does not prove that any currently named dependency is malicious. However, it prevents reproducible builds and allows newly released, compromised, or behaviorally incompatible versions to enter the environment without a source change or security review. These packages process network traffic, YAML configuration, images, and video data, so vulnerabilities or malicious changes in resolved versions would execute within the privileges of the user running the application. ### Attack Path 1. A user installs the project at a later date with `pip install -r requirements.txt`. 2. The package resolver selects the newest versions satisfying the lower bounds. 3. A selected release contains a newly introduced vulnerability or has been compromised upstream. 4. The package is installed and imported by the application. 5. Malicious package code or an exploitable parser defect runs in the context of the invoking user. ### Impact Assessment A compromised dependency can execute Python code with the same operating-system privileges as the application. That may provide access to the user's files, environment variables, API credentials, network connectivity, and generated output directories. The exact impact depends on the compromised package and the invoking account. No evidence was found that the currently specified package names are typosquatted or intentionally malicious. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin every direct dependency to an explicitly reviewed version. 2. Generate and commit a lock file containing resolved transitive dependencies. 3. Require cryptographic hashes during installation, for example through a hash-locked requirements file. 4. Build dependencies from a trusted package index and disable unintended extra indexes. 5. Run automated dependency vulnerability and provenance scanning in CI. 6. Review updates through controlled pull requests rather than resolving arbitrary future versions at deployment time. 7. Regularly rebuild the lock file so security updates are adopted deliberately rather than remaining permanently frozen. 8. Consider separating heavy media-processing dependencies into a constrained execution environment because they parse attacker-controlled binary formats. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (24)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
Calling an external OpenAI-compatible API for generic multimodal analysis is a significant behavior that should be explicitly declared, especially when users may supply screenshots or videos containing secrets, proprietary workflows, or internal system details. When that networked behavior is not accurately reflected in the skill's declared purpose and permissions, it creates a meaningful risk of silent data exfiltration to third-party services.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
Calling an external OpenAI-compatible API for generic multimodal analysis is a significant behavior that should be explicitly declared, especially when users may supply screenshots or videos containing secrets, proprietary workflows, or internal system details. When that networked behavior is not accurately reflected in the skill's declared purpose and permissions, it creates a meaningful risk of silent data exfiltration to third-party services.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Calling an external OpenAI-compatible API for generic multimodal analysis is a significant behavior that should be explicitly declared, especially when users may supply screenshots or videos containing secrets, proprietary workflows, or internal system details. When that networked behavior is not accurately reflected in the skill's declared purpose and permissions, it creates a meaningful risk of silent data exfiltration to third-party services.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
Calling an external OpenAI-compatible API for generic multimodal analysis is a significant behavior that should be explicitly declared, especially when users may supply screenshots or videos containing secrets, proprietary workflows, or internal system details. When that networked behavior is not accurately reflected in the skill's declared purpose and permissions, it creates a meaningful risk of silent data exfiltration to third-party services.

Ae1

High
Category
analysis-evasion
Content
- `SKILL.md` — A fully compliant OpenClaw skill with proper frontmatter
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill advertises use of environment variables, file output, and external MLLM providers, but does not declare an explicit tool scope such as permissions or allowed-tools. That creates an under-specified trust boundary: users and orchestrators cannot easily tell that the skill may write files and make authenticated network calls, which increases the risk of unintended data exposure or overbroad execution.

Session Persistence

Medium
Category
Rogue Agent
Content
---
name: best-practice-skill-creator
description: Create OpenClaw skills from best practice videos or image sequences. Use when creating skill from video, generating skill from screenshots, converting tutorial to skill, building best practice automation.
user-invocable: true
metadata: {"openclaw":{"emoji":"🎓","requires":{"anyBins":["python3","python"]},"os":["darwin","linux","win32"],"primaryEnv":"MLLM_API_KEY"}}
---
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.

Vague Triggers

Medium
Confidence
90% confidence
Finding
The invocation description is broad enough that the skill may be selected for common 'create a skill' requests beyond the intended video/screenshot workflow. Over-broad routing is dangerous because it can trigger unnecessary file generation, external API usage, or handling of sensitive inputs in situations where a narrower or safer skill should have been chosen.

External Transmission

Medium
Category
Data Exfiltration
Content
providers:
  openai:
    api_key: "sk-9Ld6xm13fTFHmfQYigDyStTcVrXEjxerlLxizlu6nRs"
    base_url: "https://api.cloubic.com/v1"
    model: "gemini-3.1-pro-preview"

  gemini:
Confidence
99% confidence
Finding
This configuration hard-codes what appears to be a live API key alongside an external base URL, creating immediate credential exposure and enabling unauthorized use of the remote service. Because this skill processes videos and images for skill generation, it may transmit potentially sensitive user content to a third-party endpoint, and the unusual mismatch of an 'openai' provider using a nonstandard cloubic URL with a Gemini model increases suspicion of unsafe or deceptive routing.

Session Persistence

Medium
Category
Rogue Agent
Content
def main():
    parser = argparse.ArgumentParser(
        description="Create OpenClaw skills from best practice videos or image sequences.",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""\
Examples:
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.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The tool sends extracted frames or images to an external MLLM provider for analysis, but the CLI does not give an explicit warning or require acknowledgment that user media will leave the local system. This is dangerous because screenshots and videos may contain secrets, personal data, or proprietary information that users may not realize are being transmitted to a third party.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
This code sends the user-provided prompt and base64-encoded image contents to an external Gemini API via HTTP, but there is no confirmation prompt, logging, comment, or docstring warning that user data is transmitted off-system. For a code file, outbound transmission of potentially sensitive user or system data should have some visible disclosure unless clearly documented elsewhere.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The method posts user-supplied prompt text and base64-encoded images to a remote OpenAI-compatible endpoint via `client.post`, which is a privacy-relevant network transmission. In this file there is no confirmation prompt, logging/print statement, or comment/docstring warning that user content will be sent externally.

Vague Triggers

Low
Confidence
77% confidence
Finding
This manifest file says environment variables override file values, but it does not specify when operators should rely on one mechanism versus the other or provide exclusion guidance. In manifest-style skill configuration, that lack of specificity can lead to unintended behavior because multiple configuration sources may appear valid at the same time.

Natural-Language Policy Violations

Low
Confidence
62% confidence
Finding
The file sets a fixed active provider by default and does not present any user-selectable language or locale behavior. While not a strong violation, this is the only natural-language policy-adjacent issue visible in the file and could be improved by documenting user choice where provider behavior may imply language/locale defaults.

Context-Inappropriate Capability

Low
Confidence
77% confidence
Finding
The manifest describes a tool for creating OpenClaw skills from videos or image sequences. In addition to media processing and skill generation, the code loads provider configuration and reads API key/base URL/model values from configuration files and environment variables, which is a separate credential-handling capability not stated in the manifest.

Unpinned Dependencies

Low
Category
Supply Chain
Content
httpx>=0.27.0
Pillow>=10.0.0
opencv-python>=4.8.0
PyYAML>=6.0
Confidence
96% confidence
Finding
The dependency is specified with a lower bound only, which allows any newer release to be installed. This weakens build reproducibility and can unintentionally pull in a vulnerable or breaking version through future installs, making supply-chain risk harder to assess and control.

Unverifiable Dependency: httpx has 2 known advisory(ies) (CVE-2021-41945 (Improper Input Validation in httpx); CVE-2021-41945 (Encode OSS httpx <=1.0.0.beta0 is affected by improper input validation in `http)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
88% confidence
Finding
Because httpx is not pinned, it is impossible to verify from this manifest whether deployment will use a version affected by known advisories. This creates a real supply-chain exposure: a vulnerable release could be selected now or later depending on resolver behavior and environment state.

Unpinned Dependencies

Low
Category
Supply Chain
Content
httpx>=0.27.0
Pillow>=10.0.0
opencv-python>=4.8.0
PyYAML>=6.0
Confidence
97% confidence
Finding
Pillow is not pinned to an exact version, so installations may resolve to different releases over time. Because Pillow has had multiple historical security issues in image parsing, leaving it unpinned increases uncertainty and supply-chain exposure for a skill that likely processes untrusted images or screenshots.

Unverifiable Dependency: Pillow has 16 known advisory(ies) (CVE-2016-2533 (Pillow buffer overflow in ImagingPcdDecode); CVE-2023-50447 (Arbitrary Code Execution in Pillow); CVE-2021-27922 (Pillow Uncontrolled Resource Consumption) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
95% confidence
Finding
Pillow has numerous known advisories, and the unpinned requirement prevents verification that only a safe version will be installed. Given this skill's likely handling of screenshots or image sequences, image-decoding vulnerabilities are more relevant and increase the practical risk.

Unpinned Dependencies

Low
Category
Supply Chain
Content
httpx>=0.27.0
Pillow>=10.0.0
opencv-python>=4.8.0
PyYAML>=6.0
Confidence
97% confidence
Finding
opencv-python is declared with only a minimum version, so future installations can silently consume newer releases without review. In software that processes video or image data, this can increase risk because parser-related flaws in media libraries may be introduced or remain unverifiable.

Unverifiable Dependency: opencv-python has 16 known advisory(ies) (CVE-2017-12864 (Integer Overflow or Wraparound in OpenCV); CVE-2017-12598 (Out-of-bounds Read in OpenCV ); CVE-2019-14493 (NULL Pointer Dereference in OpenCV.) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
94% confidence
Finding
opencv-python has known historical vulnerabilities, and the manifest does not constrain the installed release precisely enough to determine safety. Since the skill context involves video or image sequence processing, any flaw in media parsing libraries is more operationally significant than in a non-media workflow.

Unpinned Dependencies

Low
Category
Supply Chain
Content
httpx>=0.27.0
Pillow>=10.0.0
opencv-python>=4.8.0
PyYAML>=6.0
Confidence
98% confidence
Finding
PyYAML is unpinned, allowing uncontrolled version selection at install time. This is more concerning than a typical library because YAML parsers have a history of unsafe deserialization issues, so lack of pinning makes it harder to guarantee that only a fixed, safe release is used.

Unverifiable Dependency: PyYAML has 8 known advisory(ies) (CVE-2019-20477 (Deserialization of Untrusted Data in PyYAML); CVE-2020-1747 (Improper Input Validation in PyYAML); CVE-2020-14343 (Improper Input Validation in PyYAML) +5 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
96% confidence
Finding
PyYAML has a history of deserialization and input-handling issues, and the manifest does not pin a version, so the actual installed release cannot be verified as safe. If this skill reads YAML-based configuration or generated artifacts, a vulnerable parser version could materially increase attack surface.

Static analysis

No suspicious patterns detected.