Back to skill

Security audit

Cat Therapy

Security checks for vulnerabilities and agentic risk

Overview

This cat-relaxation skill is not clearly malicious, but it should be reviewed because it ships saved user metadata and has weak controls around automatic triggers and stored uploads.

Review before installing. The skill's cat image fetching is ordinary for its purpose, but the package should remove the included user_cats.json data, narrow or confirm broad auto-response triggers, document exactly what user photos/sounds are stored and for how long, and harden language-file selection to an allowlist such as zh/en.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/cat_therapy.py:70
Finding
Path Traversal in Language File Selection## Vulnerability Details **File Location**: `scripts/cat_therapy.py`, lines 70–77; attacker-controlled input originates at line 106 **Vulnerability Type**: Path traversal and arbitrary local JSON file read **Risk Level**: Medium **Vulnerable Code**: ```python def get_quote(language="zh"): """Get a random healing quote in specified language.""" i18n_dir = os.path.join(os.path.dirname(__file__), "..", "i18n") lang_file = os.path.join(i18n_dir, f"{language}.json") if os.path.exists(lang_file): with open(lang_file, 'r', encoding='utf-8') as f: data = json.load(f) quotes = data.get("quotes", []) ``` The untrusted value is obtained from a command-line argument: ```python language = sys.argv[1] if len(sys.argv) > 1 else "zh" quote = get_quote(language) ``` ### Technical Analysis The `language` value is incorporated into a filesystem path without an allowlist, canonicalization, or containment check. An attacker who can control the command-line argument can supply traversal sequences such as `../../directory/file` or an absolute path. Because `.json` is appended, the target must be a process-readable JSON file whose name ends in `.json`. If the selected file contains a `quotes` array, one of its entries is returned in the program output. If the file is malformed JSON or has an unexpected top-level type, the uncaught parsing or attribute error can terminate the process. ### Attack Path 1. The attacker gains control over the language argument passed to `scripts/cat_therapy.py`. 2. The attacker supplies a value such as `../../target`, causing the constructed path to resolve to `../../target.json` outside the intended `i18n` directory. 3. The script confirms that the path exists and opens it with the privileges of the Skill process. 4. If the file is valid JSON with a `quotes` array, a randomly selected entry is exposed in the generated response. 5. Alternat ...[truncated 577 chars]
Remediation
## Remediation Suggestions - Restrict the language value to an explicit allowlist such as `{"zh", "en"}` before constructing a path. - Reject absolute paths, path separators, traversal components, and unsupported locale identifiers. - Resolve both the intended localization directory and candidate file with `pathlib.Path.resolve()`, then verify that the candidate remains beneath the localization directory. - Avoid using raw command-line input as a filename; map accepted locale identifiers to fixed filenames. - Catch `OSError`, `json.JSONDecodeError`, and schema/type errors and safely fall back to the default localization file. - Validate that parsed content is an object and that `quotes` is a list of strings. Example hardening approach: ```python LANGUAGE_FILES = { "zh": "zh.json", "en": "en.json", } def get_quote(language="zh"): filename = LANGUAGE_FILES.get(language, LANGUAGE_FILES["en"]) lang_file = os.path.join(i18n_dir, filename) ```

T09 · Insecure Skill Coding Practices

Note
Location
user_cats.json:2
Finding
User-Specific Metadata Included in the Distributed Skill Package## Vulnerability Details **File Location**: `user_cats.json`, lines 2–5 **Vulnerability Type**: Sensitive metadata exposure **Risk Level**: Low **Vulnerable Data**: ```json { "user_8E8893DDD10A138203887E503C535A33": { "image": "/root/.openclaw/workspace/user_cat.png", "sound": "/root/.openclaw/qqbot/downloads/91e06003936117aa1f6494afdc79d8f0_1772630322834.wav", "updatedAt": "2026-03-04T21:19:31.666841" } } ``` ### Technical Analysis The project package contains a persistent user identifier, internal absolute filesystem paths, a bot download filename, and a preference update timestamp. This appears to be runtime-generated user data rather than configuration required for distribution. Including this file in the released artifact exposes deployment details and user-associated metadata to anyone who can download or inspect the package. It also conflicts with the documented expectation that custom cat information remains local to the deployment. ### Attack Path 1. An attacker or package recipient obtains the distributed Skill artifact. 2. The recipient opens `user_cats.json`. 3. The recipient recovers the persistent user identifier, update timestamp, internal workspace structure, bot download directory, and media filename. 4. The disclosed details may be correlated with other logs, artifacts, or deployment information available to the recipient. ### Impact Assessment The issue exposes user-associated metadata and internal deployment paths but does not expose the referenced image or audio file contents because those files are not shown as part of the package. No credentials, execution capability, or elevated privileges are obtained directly. The principal impact is privacy loss, deployment fingerprinting, and possible correlation of the identifier or filename with information from other sources.
Remediation
## Remediation Suggestions - Remove all runtime-generated user records from the distributed artifact and repository history. - Ship an empty object or a documented example file containing only synthetic placeholder values. - Add `user_cats.json` and similar runtime state files to version-control and packaging exclusion rules. - Store preferences in a dedicated runtime data directory outside the immutable Skill package. - Apply restrictive filesystem permissions so only the service account can read or modify stored preferences. - Avoid using raw platform identifiers as storage keys; use scoped or pseudonymous identifiers where feasible. - Define retention and deletion procedures for uploaded media references and associated timestamps. - Add an automated release check that rejects artifacts containing absolute home-directory paths, user identifiers, or runtime download filenames.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (22)

Vague Triggers

High
Confidence
97% confidence
Finding
The trigger list includes very common conversational phrases such as '累了', 'tired', 'stress', and 'relax', which are likely to appear in ordinary chats unrelated to invoking this skill. In a multi-platform auto-response skill, this can cause unintended activation, unsolicited media delivery, and noisy cross-channel behavior that may surprise users or leak context into the wrong conversation.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding
The supplied code is a narrow helper for cat sound retrieval, not the full cross-platform therapeutic cat skill described. It does align with one small part of the description—providing cat sounds with local-file or TTS fallback—but it lacks the major declared behaviors: phrase triggers, image delivery, quotes, platform integrations, multilingual handling, and custom upload support. This is a material description-versus-behavior mismatch because the actual code's primary behavior is much more limited than the declared purpose.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The code generally matches part of the declared theme: it prepares cat image data, a cat-sound text string, and a healing quote with basic multilingual quote lookup and simple fallback behavior for image/quote retrieval. However, several major declared capabilities are absent from the supplied code. There is no trigger detection for break-related phrases, no integration with any chat platform, no actual TTS or audio generation, and no upload-processing logic for user-provided media beyond local JSON preferences. The primary purpose is narrower than described: it assembles response payload data rather than acting as a cross-platform auto-sending skill. Therefore the description materially overstates the implemented behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The declared description presents a full end-user skill that sends cat therapy content across multiple platforms, supports uploads, multilingual behavior, and fallback delivery. The supplied code is only an intent classifier: it matches trigger phrases in Chinese/English and returns action labels such as 'therapy', 'save_cat', 'save_sound', 'reset', or 'none'. This is only a supporting component of the described skill, not the described functionality itself. Additionally, it includes a reset capability not mentioned in the description. Therefore the description materially overstates what this code chunk actually does, and there is a description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description presents a full end-user, cross-platform relaxation skill with trigger handling, content delivery, customization, multilingual support, and reliability features. The supplied code chunk only generates local audio asset files (meow.wav and purr.wav) and saves them to disk. While generating cat sounds is loosely related to one small aspect of the description, the actual behavior is only an asset-generation utility and not the described interactive, multi-platform skill. This is a material description-behavior mismatch due to the missing primary capabilities and differing overall purpose.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description presents a full cross-platform relaxation skill with trigger detection, multimodal response delivery, custom uploads, multilingual support, and platform integrations. The supplied code chunk is much narrower: it only retrieves a cat image URL from remote services with fallback sources. While this image-fetching behavior is related to one small part of the declared feature set, it does not implement most of the described capabilities. There is no evidence of undeclared harmful behavior; the mismatch is that the implementation is substantially less capable and different in scope than the description suggests.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The code only implements storage management for user-specific cat preferences in a local JSON file via CLI commands: save, load, delete, and list. While this partially aligns with the narrow claim that users can customize cat images/sounds, it does not implement the skill's stated primary purpose: automatically responding to trigger phrases with healing cat content across multiple platforms. There is no messaging integration, no trigger detection, no TTS/audio generation, no comforting quote output, and no multilingual or fallback delivery logic. Therefore the description materially overstates and misrepresents the actual behavior of this code chunk.

Vague Triggers

High
Confidence
97% confidence
Finding
The trigger model is overly broad for an automatically acting skill, using common conversational phrases like '累了', 'stress', and especially short forms like '喵' or 'relax'. This can cause unintended activation in normal conversation, resulting in unsolicited outbound requests, media generation, or storage of user data in contexts where the user did not intend to invoke the skill.

Vague Triggers

High
Confidence
98% confidence
Finding
Single-word and emotional-state triggers create a high chance of accidental invocation because they overlap heavily with ordinary user speech. In a multi-platform, auto-delivery skill, accidental triggers can lead to unnecessary external calls, noisy message delivery, and unintended handling of uploaded content or preferences.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill explicitly invites users to upload cat photos and voice-like content and says those will be saved for later use, but it provides no notice about storage location, retention period, access controls, deletion behavior, or consent implications. Because images and audio can contain personal or biometric information, the absence of privacy and handling safeguards creates a real data-protection risk, especially across multiple supported messaging platforms.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill describes capabilities that imply local file read/write and outbound network access, but it declares no explicit tool scope or permissions boundary. In agent environments, missing least-privilege declarations increases the chance the runtime grants broader access than necessary, making accidental data exposure or unsafe file modification more likely.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill stores user media references, user identifiers, language, and timestamps locally, but the user-facing description does not provide a clear consent notice, retention policy, or disclosure of what is stored. This creates privacy risk because users may unknowingly provide personal data, especially pet photos and persistent identifiers, that remain on disk and may be accessible to others on the host.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The configuration sets "defaultLanguage" to "zh" while also listing English as supported, but there is no indication that users are asked to choose or opt in to Chinese as the default. This creates a natural-language policy concern because the skill appears to impose a specific language preference by default rather than offering a neutral or user-selected locale.

External Transmission

Medium
Category
Data Exfiltration
Content
# Priority 2: Random from API
    try:
        req = urllib.request.Request(
            "https://api.thecatapi.com/v1/images/search",
            headers={"Accept": "application/json", "User-Agent": "CatTherapy/1.0"}
        )
        with urllib.request.urlopen(req, timeout=5, context=ssl_context) as response:
Confidence
90% confidence
Finding
The skill makes an outbound request to a third-party service to fetch content, creating an external data transmission and supply-chain trust dependency. Even though TLS verification is enabled and no obvious user secrets are sent in this request, the remote service learns the host IP/user agent and can return untrusted content that downstream platforms may fetch or render.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The function signature sets the default language to "zh", which forces a specific locale unless the caller explicitly overrides it. This is reinforced by the main entrypoint also defaulting to Chinese when no argument is provided, indicating a language policy choice without opt-in.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
When the script is run without arguments, it assigns "zh" as the language automatically. This creates a natural-language policy issue because the user is not offered a language choice or explicit opt-in before receiving Chinese-language content.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The intent detector sets `lang` to `"en"` only if an English trigger phrase is present; otherwise it defaults to `"zh"`. This imposes a language choice on users based on heuristic matching rather than an explicit preference or opt-in, which can violate language/locale policy expectations.

External Transmission

Medium
Category
Data Exfiltration
Content
# Source 2: TheCatAPI
    try:
        req = urllib.request.Request(
            "https://api.thecatapi.com/v1/images/search",
            headers={"Accept": "application/json", "User-Agent": "CatTherapy/1.0"}
        )
        with urllib.request.urlopen(req, timeout=5, context=ssl_context) as response:
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
# Source 2: TheCatAPI
    try:
        req = urllib.request.Request(
            "https://api.thecatapi.com/v1/images/search",
            headers={"Accept": "application/json", "User-Agent": "CatTherapy/1.0"}
        )
        with urllib.request.urlopen(req, timeout=5, context=ssl_context) as response:
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
# Source 2: TheCatAPI
    try:
        req = urllib.request.Request(
            "https://api.thecatapi.com/v1/images/search",
            headers={"Accept": "application/json", "User-Agent": "CatTherapy/1.0"}
        )
        with urllib.request.urlopen(req, timeout=5, context=ssl_context) as response:
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
This plain-text skill file consists entirely of Chinese-language user-facing content and provides no indication that language selection is optional or limited to a justified locale-specific use case. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation.

Natural-Language Policy Violations

Low
Confidence
92% confidence
Finding
The fallback TTS output is fixed to Chinese phrases ("喵~" and "咕噜咕噜~") with no user opt-in or locale selection. This is a natural-language policy concern because the skill forces a specific language choice rather than offering a configurable or neutral option.

Static analysis

No suspicious patterns detected.