Back to skill

Security audit

Kokonna Frame

Security checks for vulnerabilities and agentic risk

Overview

The skill largely matches its stated frame-control purpose, but it can send API keys and uploaded images to any configured API host without validation.

Install only if you trust the KoKonna service and keep api_base_url set to the official HTTPS endpoint. Avoid uploading sensitive images, protect the config file because it contains device API keys, and be careful with the all-devices option because it can update every configured frame.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
kokonna.py:45
Finding

Unrestricted API endpoint can disclose bearer credentials and uploaded images

Content
View full analysis
str: """获取 API Base URL""" config = load_config() return config.get("api_base_url", DEFAULT_API_BASE_URL) ``` The configured value is subsequently used in authenticated requests: ```python def get_device_info(self) -> Optional[Dict]: """获取设备信息""" url = f"{self.api_base_url}/device" headers = { "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json", } try: response = requests.post(url, headers=headers, json={}, timeout=10) response.raise_for_status() return response.json() ``` Image uploads transmit both the credential and selected image: ```python image_data = self._resize_image(image_source) base64_data = base64.b64encode(image_data).decode('utf-8') url = f"{self.api_base_url}/upload" headers = { "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json", } payload = { "base64": base64_data, "name": filename, } response = requests.post(url, headers=headers, json=payload, timeout=30) response.raise_for_status() ``` ### Technical Analysis The `api_base_url` configuration value is accepted without validating its scheme or destination hostname. The Skill then attaches the configured device API key as a bearer token to requests sent to that endpoint. A malicious or mistakenly configured URL can therefore direct authenticated requests to an arbitrary server. If an `http://` endpoint is used, credentials, device operations, filenames, and image contents can also be intercepted or modified in transit. The Base64 operation itself is not covert exfiltration: it serializes the user-selected image for the documented JSON up ...[truncated 1639 chars]
Remediation
View remediation
str: parsed = urlparse(value) if parsed.scheme != "https": raise ValueError("The API endpoint must use HTTPS") if parsed.hostname not in ALLOWED_API_HOSTS: raise ValueError("The API endpoint hostname is not trusted") if parsed.username or parsed.password or parsed.fragment: raise ValueError("Invalid API endpoint") return value.rstrip("/") ``` ]]>

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Dependencies are not reproducibly pinned and the required YAML package is undeclared

Content
View full analysis
=2.31.0 Pillow>=10.0.0 ``` The implementation also imports a dependency that is absent from `requirements.txt`: ```python def load_config() -> Dict[str, Any]: """从配置文件加载配置""" import yaml for config_path in CONFIG_PATHS: if config_path.exists(): with open(config_path, 'r', encoding='utf-8') as f: return yaml.safe_load(f) or {} ``` The documentation similarly recommends unpinned installation: ```bash pip install requests Pillow ``` ### Technical Analysis Lower-bound-only constraints allow future versions of `requests` and `Pillow` to be selected without review. Consequently, two installations performed at different times can execute different dependency code. No lock file or package hashes are supplied to establish a reviewed, reproducible dependency set. The implementation imports `yaml`, which is conventionally supplied by the `PyYAML` distribution, but that distribution is not declared. A user encountering the resulting import failure may attempt to install a package based only on the import name or untrusted instructions, increasing dependency-confusion and supply-chain exposure. No evidence was found that either declared package is currently malicious. This finding concerns unsafe and incomplete dependency management rather than a confirmed malicious dependency. ### Attack Path 1. A user installs dependencies using the provided requirements or documentation. 2. The package installer resolves whatever compatible releases are available at that time. 3. A compromised, malicious, or unexpectedly incompatible future release may be selected because no reviewed upper version, exact version, lock fil ...[truncated 902 chars]
Remediation
View remediation
Pillow== PyYAML== ``` Exact values should be selected through compatibility and security testing, with transitive versions and hashes captured in a generated lock file. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (20)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description covers both image upload/display and device info/management. However, this specific code chunk only implements device enumeration and device info retrieval through a CLI interface. It parses arguments like --device, --list-devices, and --json, loads configured devices, and prints status fields such as online state, battery, firmware, nickname, timezone, and screen dimensions. There is no logic for uploading images, pushing content to a frame, or changing what is displayed. Because the declared triggers are centered on sending/displaying images to frames, while the actual code only queries information, the description does not accurately represent this code chunk's actual behavior.

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: kokonna-frame
description: Control KoKonna AI e-ink art frames. Upload images, query device info, and manage multiple frames. Use when user asks to "push to frame", "send to frame", "display on frame", or "upload image to frame".
version: 1.2.0
author: KoKonna
tags:
  - smart-home
  - e-ink
  - art-frame
  - image-upload
triggers:
  - "push to frame"
  - "send to frame"
  - "display on frame"
  - "upload to frame"
  - "show on KoKonna"
---

# KoKonna Frame Control

Control KoKonna AI e-ink art frames. Upload images, query device status, and manage multiple frames.

---

## Configuration

Before using this s

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 · README.md (reported line 20)May include surrounding context.

Configuration

  1. Create config file:
bash
mkdir -p ~/.openclaw/skills/kokonna-frame
cp config.yaml.example ~/.openclaw/skills/kokonna-frame/config.yaml

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The example phrase "Show this on KoKonna" is generic and lacks clear scope constraints, making it more likely to overlap with everyday user requests compared with the more specific frame-control examples nearby. The README also does not provide exclusion conditions or a bounded trigger list to clarify when this skill should or should not activate.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill documents file access and outbound network behavior but does not declare any tool scope or permissions boundaries. In an agent environment, missing explicit capability declarations weakens review and containment, making it easier for the skill to access local files and transmit data without clear user or platform visibility.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill instructs users to upload images and supports pushing content to one or all frames, but it does not clearly warn that images and device-related data are transmitted to a remote service or that --device all can affect multiple devices at once. This can lead to unintentional disclosure of sensitive images or unintended actions across multiple household devices.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · README.md (reported line 28)May include surrounding context.

md
from PIL import Image

# 默认 API 地址
DEFAULT_API_BASE_URL = "https://api.galaxyguide.cn/openapi"

# 配置文件路径
CONFIG_PATHS = [

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

md
from PIL import Image

# 默认 API 地址
DEFAULT_API_BASE_URL = "https://api.galaxyguide.cn/openapi"

# 配置文件路径
CONFIG_PATHS = [

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · kokonna.py (reported line 22)May include surrounding context.

python
from PIL import Image

# 默认 API 地址
DEFAULT_API_BASE_URL = "https://api.galaxyguide.cn/openapi"

# 配置文件路径
CONFIG_PATHS = [

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · manifest.yaml (reported line 17)May include surrounding context.

yaml
from PIL import Image

# 默认 API 地址
DEFAULT_API_BASE_URL = "https://api.galaxyguide.cn/openapi"

# 配置文件路径
CONFIG_PATHS = [

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

This requests.post call sends authenticated device queries to an external service. In a skill ecosystem, any undisclosed external transmission is security-relevant because it can leak usage patterns, device metadata, and credentials to a remote endpoint.

Content

Scanner excerpt · kokonna.py (reported line 192)May include surrounding context.

python
}
        
        try:
            response = requests.post(url, headers=headers, json={}, timeout=10)
            response.raise_for_status()
            return response.json()
        except Exception as e:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The upload_image function base64-encodes the provided image and sends it, along with an authorization token, to a remote Internet API. In the context of an agent skill, this is a real privacy/security issue because user-supplied local files are exfiltrated off-host without any explicit consent, warning, or allowlist enforcement at the call site.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

This requests.post call transmits the full processed image plus authorization credentials to a remote API. Because the skill can read arbitrary local image paths and upload their contents, the external transmission is a genuine data-exfiltration risk if invoked on sensitive files or used without informed consent.

Content

Scanner excerpt · kokonna.py (reported line 228)May include surrounding context.

python
"name": filename,
        }
        
        response = requests.post(url, headers=headers, json=payload, timeout=30)
        response.raise_for_status()
        return response.json()

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The get_device_info method performs a network request to a third-party API using the configured bearer token, but the method interface does not make the external transmission obvious to the caller. While expected for device control, it still exposes credentials and metadata to the remote service and may surprise users in an agent context.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency specification for requests is unpinned, allowing builds to resolve to different versions over time. This creates supply-chain and reproducibility risk because a newly released buggy or compromised version could be installed without review, and it also makes it impossible to determine whether known vulnerabilities are present in deployed environments.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
requests>=2.31.0
Pillow>=10.0.0

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +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
87% confidence
Finding

Requests has multiple historical advisories, but because the manifest only sets a minimum version, there is no reliable way to verify at analysis time whether a safe release will actually be installed. In a skill that uploads images and likely communicates with remote frame endpoints, an affected requests version could expose credentials or weaken transport/authentication protections depending on runtime resolution.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency specification for Pillow is unpinned, so installations may pull different versions depending on when and where the skill is installed. That weakens build integrity and makes the package susceptible to accidental adoption of vulnerable or malicious upstream releases, especially relevant here because Pillow processes image data for an art-frame skill.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
requests>=2.31.0
Pillow>=10.0.0

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
91% confidence
Finding

Pillow has a history of vulnerabilities including denial-of-service and, in some versions, code-execution issues in image parsing paths. Because this skill's purpose is to upload and handle images for e-ink frames, leaving Pillow unpinned increases the chance that a vulnerable image-processing build is installed, making the context more dangerous than in a package that never parses user-controlled images.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code file contains natural-language usage documentation and CLI/help text that assumes Chinese as the only language. Under the language/locale policy, forcing a specific language without offering user choice can be a policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The script prints device listings, errors, and argparse help in Chinese only, which imposes a language choice on users. There is no indication that the tool is region-specific or that users can select their preferred language.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.