Back to skill

Security audit

小龙虾

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent coding assistant, but it sends and stores full conversation content and has unsafe file-save behavior that can overwrite user-writable files.

Review this before installing. Use a disposable or tightly scoped API key, do not paste secrets or proprietary code unless you are comfortable sending it to the configured Volcengine endpoint, clear history when needed, and avoid using --save with arbitrary paths until path validation and overwrite protection are fixed.

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

Error
Location
xiaolongxia.py:232
Finding

Arbitrary File Overwrite Through Unvalidated Save Path

Content
View full analysis

Vulnerability Details

File Location: xiaolongxia.py, lines 232–238 and 315–321
Vulnerability Type: Path traversal and arbitrary file overwrite
Risk Level: High

Vulnerable Code

python
def save_code_to_file(code, filename=None):
    code_blocks = extract_code_blocks(code)
    if not code_blocks:
        return "未找到可保存的代码"
    ensure_dir()
    saved_files = []
    for i, (lang, content) in enumerate(code_blocks):
        if not filename:
            ext_map = {
                'python': 'py', 'js': 'js', 'typescript': 'ts', 'java': 'java',
                'go': 'go', 'rust': 'rs', 'cpp': 'cpp', 'c': 'c', 'csharp': 'cs',
                'sql': 'sql', 'bash': 'sh', 'shell': 'sh', 'html': 'html',
                'css': 'css', 'json': 'json', 'yaml': 'yaml', 'yml': 'yml',
            }
            ext = ext_map.get(lang.lower(), 'txt')
            filename = f"code_{datetime.now().strftime('%H%M%S')}_{i+1}.{ext}"
        filepath = SKILL_DIR / filename
        with open(filepath, 'w', encoding='utf-8') as f:
            f.write(content.strip())
        saved_files.append(str(filepath))
python
elif cmd == "--save":
    filename = sys.argv[2] if len(sys.argv) >= 3 else None
    history = load_history()
    if history["messages"] and len(history["messages"]) > 1:
        last_response = history["messages"][-1]["content"]
        result = save_code_to_file(last_response, filename)
        print(result)
    else:
        print("没有可保存的代码")
    return

Technical Analysis

The --save argument is passed directly to save_code_to_file() and joined with SKILL_DIR without validation or canonical containment checks.

A value containing parent-directory components, such as ../../target, can escape the intended skill directory. In addition, Python's pathlib behavior means an absolute filename replaces the preceding SKILL_DIR component entirely. The ...[truncated 2090 chars]

Remediation
View remediation

Remediation Suggestions

  1. Reject absolute filenames and any path containing parent-directory traversal:

    python
    def safe_destination(filename: str) -> Path:
        candidate = Path(filename)
        if candidate.is_absolute() or ".." in candidate.parts:
            raise ValueError("Absolute paths and parent traversal are not allowed")
    
        root = SKILL_DIR.resolve()
        destination = (root / candidate).resolve()
    
        if destination.parent != root:
            raise ValueError("Destination must be directly inside the skill directory")
    
        return destination
    
  2. If subdirectories are intentionally supported, use a robust containment test:

    python
    destination.relative_to(root)
    

    Handle ValueError as an attempted directory escape.

  3. Disallow or safely handle symbolic links. Before writing, verify that the destination and relevant parent components are not symbolic links. Where supported, use operating-system flags that prevent following symlinks.

  4. Avoid silently truncating existing files. Use exclusive creation mode ('x') by default and require explicit user confirmation before an overwrite.

  5. Generate server-side filenames instead of accepting arbitrary paths when a caller only needs to select a display name.

  6. Add tests covering absolute paths, ../ traversal, nested traversal, symbolic links, existing-file overwrite, and platform-specific path forms.

T09 · Insecure Skill Coding Practices

Warning
Location
xiaolongxia.py:127
Finding

Plaintext Storage of API Credentials and Sensitive Conversation History

Content
View full analysis

Vulnerability Details

File Location: xiaolongxia.py, lines 20–27, 127–141, 170–177, and 384–386
Vulnerability Type: Insecure secret management and plaintext sensitive-data storage
Risk Level: Medium

Vulnerable Code

python
# ============ 配置 ============
# 请替换为你自己的火山引擎 API Key
API_KEY = "YOUR_API_KEY_HERE"
ENDPOINT = "https://ark.cn-beijing.volces.com/api/coding/v3"
MODEL = "deepseek-v4-pro"

SKILL_DIR = Path.home() / ".openclaw" / "skills" / "xiaolongxia"
HISTORY_FILE = SKILL_DIR / "history.json"
SESSION_FILE = SKILL_DIR / "session.json"
python
def load_history():
    ensure_dir()
    if HISTORY_FILE.exists():
        try:
            with open(HISTORY_FILE, 'r', encoding='utf-8') as f:
                return json.load(f)
        except:
            return {"messages": []}
    return {"messages": []}

def save_history(history):
    ensure_dir()
    history["updated_at"] = datetime.now().isoformat()
    with open(HISTORY_FILE, 'w', encoding='utf-8') as f:
        json.dump(history, f, ensure_ascii=False, indent=2)
python
def call_deepseek(messages):
    url = f"{ENDPOINT}/chat/completions"
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {API_KEY}"
    }
    data = {
        "model": MODEL,
        "messages": messages,
        "temperature": 0.7,
        "max_tokens": 4096
    }
python
response = call_deepseek(messages)
messages.append({"role": "assistant", "content": response})
save_history({"messages": messages})

Technical Analysis

The source code instructs users to replace a placeholder with a real API key. Doing so places a reusable bearer credential directly in the Python source file, where it can be exposed through source-control commits, archives, backups, package distribution, diagnostic collection, or access by another local process.

The applicatio ...[truncated 2554 chars]

Remediation
View remediation

Remediation Suggestions

  1. Do not place API keys in source code. Load the credential from a protected environment variable or operating-system secret store:

    python
    API_KEY = os.environ.get("VOLCENGINE_API_KEY")
    if not API_KEY:
        raise RuntimeError("VOLCENGINE_API_KEY is not configured")
    
  2. Add the relevant local configuration and history files to version-control ignore rules. Provide only a placeholder configuration template.

  3. Enforce owner-only permissions:

    • Create SKILL_DIR with mode 0700.
    • Create history and session files with mode 0600.
    • Verify and correct permissions on existing files before reading sensitive content.
  4. Write sensitive files atomically through a securely created temporary file, apply restrictive permissions, and then replace the destination.

  5. Make conversation retention opt-in or provide a no-history mode. Minimize retained data, limit retention duration, and allow users to delete individual conversations.

  6. Warn users not to submit credentials or other secrets. Consider detecting and redacting common credential formats before persistence.

  7. Clearly disclose that the complete message history is sent to the configured external API. Send only the context required for the current request where practical.

  8. If confidentiality against local file access is required, encrypt history using a key stored in an operating-system credential manager rather than alongside the encrypted data.

  9. Rotate any real API key that has previously been embedded in source code or committed to a repository; removing it from the latest revision alone is insufficient.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • 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
Findings (11)

Vague Triggers

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrases are extremely broad and match ordinary programming requests, so this skill could activate in many unrelated conversations. Overbroad activation is dangerous because it can unexpectedly steer the agent into higher-risk coding, file, or network workflows without the user intentionally selecting this skill.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill advertises capabilities that imply file read/write and network use, but it does not declare any explicit tool scope or permissions boundaries. In a coding assistant context, this increases the risk of unintended privileged actions, because behavior like saving files or calling external APIs may occur without clear user-visible authorization constraints.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

The skill name, description, and operational text present the assistant as a Chinese-language experience, but there is no indication that users may choose another language or locale. This can violate language-choice policy when a skill implicitly forces a specific language without opt-in.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The automatic mode-recognition rules switch behavior based on ambiguous cues like any code block, error description, or the word '继续', without validating user intent or scope. In a coding assistant with write/export features, this can cause unintended transitions into review, debugging, or file-action flows that the user did not clearly authorize.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill includes commands to save generated code to files and export all generated code, but it does not warn the user about modifying local data, overwriting files, or packaging potentially sensitive content. This is risky because users may unintentionally persist or bundle proprietary, credential-bearing, or otherwise sensitive code artifacts.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest advertises very broad trigger phrases such as '编程', '写代码', 'debug', and '代码助手', which overlap heavily with common user requests and can cause the skill to activate in many unrelated coding contexts. Overbroad activation increases the chance of unintentional routing, prompt interference, or the skill superseding safer/default behaviors, especially because this is a general-purpose coding assistant rather than a narrowly scoped tool.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The natural-language system prompt defines the assistant persona entirely in Chinese and presents the tool as a Chinese-language assistant by default. There is no visible option in the prompt or CLI flow offering language choice or obtaining user opt-in for this locale preference.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill persistently saves history.json and session.json under the user's home directory without a clear warning, consent flow, or retention policy. Stored prompts and generated code may include tokens, credentials, client data, or proprietary material that could later be exposed to other local users, backups, or malware.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill sends user prompts and accumulated conversation history to a third-party API endpoint, but the manifest description does not disclose this external transmission. In a coding assistant context, users may paste credentials, source code, or internal architecture details, making undisclosed off-device transfer a meaningful confidentiality issue.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The request body includes the full messages array, which can contain prior user prompts and assistant responses, and transmits it over the network without any user-facing warning. This is dangerous because a user may reasonably expect a local coding helper, while sensitive code or secrets are actually forwarded to an external service.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The skill stores conversation history and session metadata on disk and also provides save/export features, which expands its data-handling scope beyond a simple transient coding assistant. This is not inherently malicious, but it creates privacy and confidentiality risk because prompts, code, secrets, or proprietary snippets may be retained locally without clear disclosure or retention controls.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.