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

Content
View full analysis

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
View 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

Content
View full analysis

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
View 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
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
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.

Content

Scanner excerpt · scripts/cat_therapy.py (reported line 42)May include surrounding context.

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

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

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

md
# 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:

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 · config.json (reported line 6)May include surrounding context.

json
# 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:

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 · scripts/get_cat_image.py (reported line 38)May include surrounding context.

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

Natural-Language Policy Violations

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.