Back to skill

Security audit

Skill Creator

Security checks for vulnerabilities and agentic risk

Overview

This skill helps create and package OpenClaw skills, and its file-writing behavior is disclosed and user-directed, with only minor hygiene issues.

Install this only when you want an agent to create or modify OpenClaw skills. Review generated skill files before publishing, keep publishing actions user-approved, and pin any third-party dependencies if you adapt the generated examples.

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

T08 · Insecure Dependencies

Warning
Location
scripts/init_skill.py:63
Finding

Generated Example Recommends an Unpinned Third-Party Dependency

Content
View full analysis

Vulnerability Details

File Location: scripts/init_skill.py, lines 63-70
Vulnerability Type: Unpinned third-party dependency installation
Risk Level: Medium

Vulnerable Code

python
EXAMPLE_SCRIPT = '''#!/usr/bin/env python3
"""
{skill_name} - Helper script

Description: What this script does.
Usage: python3 scripts/example.py [args]

Dependencies:
  - Python 3.8+
  - requests (pip install requests)

Technical Analysis

When a user invokes the initializer with --resources scripts --examples, this template is written into the generated scripts/example.py file. The dependency instructions recommend installing requests without a pinned version, package hash, lockfile, isolated environment, or explicitly trusted package index.

Although requests is a legitimate package, the generated installation instruction relies on mutable package-index resolution. The installed artifact can vary according to the configured index, dependency resolver, release availability, or a compromised package-distribution environment.

Attack Path

  1. A user creates a Skill with example resources enabled.
  2. The initializer writes the dependency instruction into scripts/example.py.
  3. The user follows the generated pip install requests instruction.
  4. Pip resolves the package and transitive dependencies from the user's configured index without version or hash verification.
  5. If the package source, selected release, transitive dependency, or configured index is compromised, attacker-controlled code can execute during installation or subsequent import.

Impact Assessment

Malicious dependency code would execute with the privileges of the user or automation account running pip or the generated script. Depending on those privileges, the code could access project files, user-readable credentials, environment variables, or other resources available to that account. The issue does not independently ...[truncated 94 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove requests from the generic example because the sample script does not use it.
  • If a third-party dependency is necessary, place it in a version-controlled requirements file with an exact reviewed version and cryptographic hashes.
  • Use a command such as pip install --require-hashes -r requirements.txt.
  • Document the expected trusted package index and avoid silently inheriting untrusted index configuration.
  • Recommend installation in a dedicated virtual environment with minimal filesystem and credential access.
  • Periodically review and update pinned dependencies through a controlled dependency-management process.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/quick_validate.py:97
Finding

Malformed YAML Types Can Crash Skill Validation and Packaging

Content
View full analysis

Vulnerability Details

File Location: scripts/quick_validate.py, lines 97-99 and 119-121
Vulnerability Type: Unhandled type confusion in frontmatter validation
Risk Level: Low

Vulnerable Code

python
name = frontmatter.get("name", "").strip()
if not isinstance(name, str):
    return False, f"name must be string, got {type(name).__name__}"
python
desc = frontmatter.get("description", "").strip()
if not isinstance(desc, str):
    return False, f"description must be string"

Technical Analysis

The validator calls .strip() before checking whether the YAML value is a string. YAML permits values such as integers, lists, mappings, booleans, and null. When PyYAML parses one of those values, calling .strip() raises an AttributeError before the intended validation error can be returned.

The exception is not handled inside validate_skill(). Because package_skill.py calls this function before packaging, the same malformed frontmatter can terminate both direct validation and packaging workflows unexpectedly.

Attack Path

  1. An attacker or untrusted contributor supplies a Skill containing non-string frontmatter, such as:

    yaml
    ---
    name: 123
    description: []
    ---
    
  2. PyYAML converts name to an integer or description to a list.

  3. The validator invokes .strip() on the non-string value.

  4. Python raises an unhandled AttributeError.

  5. Validation or packaging terminates rather than returning a controlled invalid-Skill result.

Impact Assessment

Exploitation causes a local denial of service against the affected validation or packaging operation. In automated review, CI, or publishing workflows, a crafted Skill can interrupt the job and prevent other processing in the same pipeline. The flaw does not provide code execution, data access, or privilege escalation.

Remediation
View remediation

Remediation Suggestions

Retrieve and validate the raw value before applying string methods:

python
raw_name = frontmatter.get("name", "")
if not isinstance(raw_name, str):
    return False, f"name must be string, got {type(raw_name).__name__}"
name = raw_name.strip()

raw_desc = frontmatter.get("description", "")
if not isinstance(raw_desc, str):
    return False, f"description must be string, got {type(raw_desc).__name__}"
desc = raw_desc.strip()

Also:

  • Add regression tests for null, numeric, boolean, list, and mapping values.
  • Catch anticipated parser and validation exceptions at the command-line boundary and return a controlled exit code.
  • Ensure package_skill.py treats every validation failure as a normal rejection rather than allowing an uncaught exception to terminate the process.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/quick_validate.py:103
Finding

Unvalidated Slug Allows Malformed Skill Identifiers to Pass Validation

Content
View full analysis

Vulnerability Details

File Location: scripts/quick_validate.py, lines 103-112
Vulnerability Type: Incomplete metadata validation
Risk Level: Low

Vulnerable Code

python
# If name contains spaces or special chars, slug must be present (hyphen-case requirement)
has_special = not re.match(r"^[a-z0-9][a-z0-9-]*$", name)
if has_special and "slug" not in frontmatter:
    return False, f"name '{name}' contains special characters, but no 'slug' field found"
if has_special and "slug" in frontmatter:
    pass  # display name OK with slug present
else:
    if len(name) > MAX_SKILL_NAME_LENGTH:
        return False, f"name too long ({len(name)} chars), max {MAX_SKILL_NAME_LENGTH}"

Technical Analysis

An invalid display name is accepted whenever the slug key exists, but the validator does not inspect the slug's value. It does not verify that the slug is a string, is non-empty, follows lowercase hyphen-case syntax, or stays within the maximum identifier length.

The branch also bypasses the name-length check when an invalid name and a slug field are both present. Consequently, metadata that does not satisfy the validator's stated identifier requirements can receive a successful validation result and be packaged as a validated Skill.

Attack Path

  1. A crafted SKILL.md uses an invalid or oversized display name.

  2. The attacker adds a malformed slug, for example:

    yaml
    ---
    name: "Invalid Display Name With Special Characters!"
    slug: []
    description: Example description
    ---
    
  3. has_special evaluates to true.

  4. Because the slug key exists, execution enters the unconditional pass branch.

  5. No type, syntax, emptiness, or length validation is performed on the slug.

  6. The Skill passes validation and can be packaged for downstream consumption.

Impact Assessment

This weakness can distribute malformed metadata under the appearance of su ...[truncated 373 chars]

Remediation
View remediation

Remediation Suggestions

  • Validate the raw slug type before applying string operations.
  • Require a non-empty slug matching the intended identifier grammar.
  • Enforce the same 64-character maximum used for canonical names.
  • Apply length constraints independently so that adding a slug cannot bypass limits on other fields.
  • Add test cases for empty, null, numeric, list, mapping, uppercase, oversized, leading-hyphen, and trailing-hyphen slug values.

Example hardening:

python
slug = frontmatter.get("slug")
if has_special:
    if not isinstance(slug, str) or not slug.strip():
        return False, "A non-empty string slug is required for display names"
    slug = slug.strip()
    if len(slug) > MAX_SKILL_NAME_LENGTH:
        return False, f"slug too long ({len(slug)} chars)"
    if not re.fullmatch(r"[a-z0-9]+(?:-[a-z0-9]+)*", slug):
        return False, "slug must use lowercase letters, digits, and single hyphens"
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (6)

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

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

touch skills//SKILL.md

text

### Step 4: Write SKILL.md

**Frontmatter rules (two hard rules):**
1. `name`: lowercase + hyphens, ≤64 chars

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · scripts/init_skill.py (reported line 190)May include surrounding context.

python
(skill_dir / "SKILL.md").write_text(content, encoding="utf-8")
        print("[OK] Created SKILL.md")
    except Exception as e:
        print(f"[ERROR] Failed to write SKILL.md: {e}")
        return None

    # Resource directories

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · scripts/init_skill.py (reported line 223)May include surrounding context.

python
print(f"\\n[OK] Skill '{skill_name}' initialized at: {skill_dir}")
    print("\\nNext steps:")
    print("1. Edit SKILL.md, fill in TODO items")
    print("2. Validate: python3 quick_validate.py <skill-path>")
    return skill_dir

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger description is very broad, including phrases like 'improve this skill', 'review the skill', 'tidy up the skill', and 'audit the skill', which can overlap with generic editing or review requests. This can cause the skill to activate in unintended contexts, increasing the chance that a powerful skill-creation workflow is applied when not appropriate and leading to mis-scoped file modifications or unsafe operational guidance.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest description on L4 is entirely in Chinese and does not indicate that other language options are available. Under the policy for natural-language violations, forcing a specific language without opt-in can exclude users and should be documented or made configurable.

Content

No source excerpt is available for this finding.

Scope Creep

Low
Category
Excessive Agency
Confidence
70% confidence
Finding

Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Content

Scanner excerpt · license.txt (reported line 16)May include surrounding context.

text
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.

Static analysis

No suspicious patterns detected.