Back to skill

Security audit

Porting OpenClaw Skills Across Platforms

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a legitimate skill-porting helper, but its converter can copy files outside the selected skill folder through symlinks, so it needs review before use.

Install only if you are comfortable reviewing the converter before use. Run it only on trusted skill directories, inspect sources for symlinks first, use a scratch output folder, and do not publish or share generated ports until checking that no unintended local files were copied.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/port_skill.py:332
Finding

Source Symlink Allows Files Outside the Skill Directory to Be Copied

Content
View full analysis

Vulnerability Details

File Location: scripts/port_skill.py, lines 332–378
Vulnerability Type: Source-directory boundary bypass through symbolic links
Risk Level: Medium

Vulnerable Code

python
for p in sorted(src.rglob("*")):
    if p.is_dir():
        continue
    rel = p.relative_to(src)
    is_text = p.suffix.lower() in TEXT_EXTS
    if is_text:
        orig = p.read_text(encoding="utf-8", errors="replace")
        if _is_tool_catalog(str(rel), orig):
            warnings.append(f"Tool mapping document: {rel} skipped auto-replacement; must be fully rewritten as the target platform's tool table.")
            files_copied += 1
            if not dry_run:
                dst = dst_root / rel
                dst.parent.mkdir(parents=True, exist_ok=True)
                dst.write_text(orig, encoding="utf-8")
            continue
        text = orig
        if rel.name == "SKILL.md":
            if fix_name and name_mismatch:
                text = _fix_name(text, skill_name)
            text = normalize_frontmatter(text, target)
        file_flags = []
        text, n = transform_text(text, target, file_flags, str(rel))
        files_copied += 1
        if n:
            files_changed += 1
            total_changes += n
        if strip_output_directives:
            text_after_strip, n_strip = _strip_output_directives(text)
            if n_strip:
                file_flags = [f for f in file_flags if not _is_output_directive_flag(f)]
                file_flags.append(f"{rel}: (auto-removed {n_strip} output directive(s))")
            directives_removed += n_strip
            text = text_after_strip
        flags.extend(file_flags)
        if text != orig:
            diffs.append((str(rel), orig, text))
        if not dry_run:
            dst = dst_root / rel
            dst.parent.mkdir(parents=True, exist_ok=True)
            dst.write_text(text, encoding="utf-8")
    else:
        files_copied += 1
        if not dry_run:
          
...[truncated 2472 chars]
Remediation
View remediation

Remediation Suggestions

  • Reject symbolic links before processing:
python
if p.is_symlink():
    raise ValueError(f"symbolic links are not allowed in source skills: {p}")
  • Resolve every candidate and enforce containment beneath the canonical source directory before reading or copying:
python
src_root = src.resolve()

for p in sorted(src.rglob("*")):
    if p.is_symlink():
        raise ValueError(f"symbolic links are not allowed: {p}")

    resolved = p.resolve(strict=True)
    if resolved != src_root and src_root not in resolved.parents:
        raise ValueError(f"source entry escapes source directory: {p}")

    if resolved.is_dir():
        continue
  • Prefer file-opening mechanisms with no-follow semantics, where supported, to reduce time-of-check/time-of-use symlink races.
  • Apply the same containment policy to every source entry regardless of whether it is treated as text or copied as binary data.
  • Fail closed when encountering broken links, special files, sockets, FIFOs, or device nodes; accept only regular files and directories.
  • Add regression tests covering text and binary symlinks to external files, nested symlinks, broken symlinks, and links changed during processing.
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (14)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
aw skill's **structure is already compatible with the Agent Skills standard** (`SKILL.md` + frontmatter + `references/`/`scripts/`/`assets/`), and every platfor

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
aw skill's **structure is already compatible with the Agent Skills standard** (`SKILL.md` + frontmatter + `references/`/`scripts/`/`assets/`), and every platfor

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · references/openclaw-specifics.md (reported line 5)May include surrounding context.

md
Inventory the platform coupling points that may appear in OpenClaw skill content, organized into three categories: auto-replaceable / needs manual rewrite / not portable.

## A. Output Directives (delete or rewrite)

OpenClaw's assistant output directives are not recognized by other platforms and should be **deleted** (or rewritten to the target platform's equivalent mechanism):

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

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

md
## A. Output Directives (delete or rewrite)

OpenClaw's assistant output directives are not recognized by other platforms and should be **deleted** (or rewritten to the target platform's equivalent mechanism):

| Directive | Meaning | Handling |
|---|---|---|

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · references/example.md (reported line 99)May include surrounding context.

md
## A. Output Directives (delete or rewrite)

OpenClaw's assistant output directives are not recognized by other platforms and should be **deleted** (or rewritten to the target platform's equivalent mechanism):

| Directive | Meaning | Handling |
|---|---|---|

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · references/openclaw-specifics.md (reported line 7)May include surrounding context.

md
## A. Output Directives (delete or rewrite)

OpenClaw's assistant output directives are not recognized by other platforms and should be **deleted** (or rewritten to the target platform's equivalent mechanism):

| Directive | Meaning | Handling |
|---|---|---|

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/port_skill.py (reported line 83)May include surrounding context.

python
## A. Output Directives (delete or rewrite)

OpenClaw's assistant output directives are not recognized by other platforms and should be **deleted** (or rewritten to the target platform's equivalent mechanism):

| Directive | Meaning | Handling |
|---|---|---|

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/port_skill.py (reported line 506)May include surrounding context.

python
## A. Output Directives (delete or rewrite)

OpenClaw's assistant output directives are not recognized by other platforms and should be **deleted** (or rewritten to the target platform's equivalent mechanism):

| Directive | Meaning | Handling |
|---|---|---|

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/port_skill.py (reported line 410)May include surrounding context.

python
if strip_output_directives:
                text_after_strip, n_strip = _strip_output_directives(text)
                if n_strip:
                    # Output directives already auto-removed are no longer flagged as "needs manual handling"
                    file_flags = [f for f in file_flags if not _is_output_directive_flag(f)]
                    file_flags.append(f"{rel}: (auto-removed {n_strip} output directive(s))")
                directives_removed += n_strip

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/port_skill.py (reported line 412)May include surrounding context.

python
if n_strip:
                    # Output directives already auto-removed are no longer flagged as "needs manual handling"
                    file_flags = [f for f in file_flags if not _is_output_directive_flag(f)]
                    file_flags.append(f"{rel}: (auto-removed {n_strip} output directive(s))")
                directives_removed += n_strip
                text = text_after_strip
            flags.extend(file_flags)

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/port_skill.py (reported line 472)May include surrounding context.

python
if n_strip:
                    # Output directives already auto-removed are no longer flagged as "needs manual handling"
                    file_flags = [f for f in file_flags if not _is_output_directive_flag(f)]
                    file_flags.append(f"{rel}: (auto-removed {n_strip} output directive(s))")
                directives_removed += n_strip
                text = text_after_strip
            flags.extend(file_flags)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill instructs use of file-reading and file-writing behavior through scripts/port_skill.py and placement of converted files, but the skill frontmatter does not declare any tool scope such as permissions or allowed-tools. This creates an authorization ambiguity where an agent may perform filesystem actions without an explicit least-privilege declaration, increasing the chance of overbroad file access during porting.

Content

No source excerpt is available for this finding.

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

md
- **Pure knowledge/content** (no tool references, no `MEDIA:`/`cron`/`sessions_*`) → copy directly + normalize frontmatter.
- **References tools/platform-specific features** → run `port_skill.py` for mechanical replacement, then handle remaining items manually per the report.
- Run `--dry-run` first to preview, confirm, then actually write files.

## Workflow

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
`scripts/port_skill.py` performs deterministic conversion: tool names → system files/paths → frontmatter normalization → outputs a "needs manual handling" report.

Arguments: `--target claude-code|codex|cursor|hermes|opencode|generic|all`, `--dry-run` (preview), `--strip-output-directives` (automatically remove `MEDIA:`/`[embed`/`[[reply_*]]`/`[[audio_as_voice]]`), `--fix-name` (fix a name that doesn't match the directory name), `--validate`, `--json`.

Replacement precision: short English words (`read`/`write`/`exec`/`image`…) are replaced only inside backticks; non-English words (`sessions_*`/`memory_*`/`web_fetch`…) are replaced as bare words; `AGENTS.md` is rewritten to `CLAUDE.md` only for Claude Code. See [tool-mappings.md](references/tool-mappings.md) for the full mapping.