Back to skill

Security audit

My skill

Security checks for vulnerabilities and agentic risk

Overview

This skill matches its self-improvement purpose, but it asks agents to add always-on reminders and write learned rules into future agent instruction files, which needs careful review before installation.

Install only if you want persistent learning logs and future-agent memory changes. Prefer project-local setup, avoid global hooks and empty matchers, review every proposed write to instruction files, keep .learnings out of shared repos unless intentional, and do not forward raw transcripts, command output, or secrets across sessions.

Vulnerability Patterns
  • 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
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (3)

T01 · Skill Instruction Hijacking

Error
Location
hooks/openclaw/handler.js:8
Finding
Agent Bootstrap and Per-Prompt Instruction Injection<![CDATA[ ## Vulnerability Details **File Location**: `hooks/openclaw/handler.js:8-24, 28-51`; `scripts/activator.sh:8-19`; `SKILL.md:489-536` **Vulnerability Type**: T01: Skill Instruction Hijacking **Risk Level**: High ### Vulnerable Code ```javascript const REMINDER_CONTENT = ` ## Self-Improvement Reminder After completing tasks, evaluate if any learnings should be captured: **Log when:** - User corrects you → \`.learnings/LEARNINGS.md\` - Command/operation fails → \`.learnings/ERRORS.md\` - User wants missing capability → \`.learnings/FEATURE_REQUESTS.md\` - You discover your knowledge was wrong → \`.learnings/LEARNINGS.md\` - You find a better approach → \`.learnings/LEARNINGS.md\` **Promote when pattern is proven:** - Behavioral patterns → \`SOUL.md\` - Workflow improvements → \`AGENTS.md\` - Tool gotchas → \`TOOLS.md\` Keep entries simple: date, title, what happened, what to do differently. `.trim(); const handler = async (event) => { // Safety checks for event structure if (!event || typeof event !== 'object') { return; } // Only handle agent:bootstrap events if (event.type !== 'agent' || event.action !== 'bootstrap') { return; } // Safety check for context if (!event.context || typeof event.context !== 'object') { return; } // Inject the reminder as a virtual bootstrap file // Check that bootstrapFiles is an array before pushing if (Array.isArray(event.context.bootstrapFiles)) { event.context.bootstrapFiles.push({ path: 'SELF_IMPROVEMENT_REMINDER.md', content: REMINDER_CONTENT, virtual: true, }); } }; ``` The per-prompt hook also emits instructions explicitly intended to become system context: ```bash # Output reminder as system context cat << 'EOF' <self-improvement-reminder> After completing this task, evaluate if extractable knowledge emerged: - Non-obvious solution discovered through investigation? - Workaround for unexpected behavior? - Project-specific pattern learned? - E ...[truncated 2324 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not insert skill-controlled behavioral instructions into bootstrap or system-equivalent context. 2. Emit a clearly identified, non-authoritative notification that cannot be confused with system instructions. 3. Run learning evaluation only after explicit invocation by the user rather than after every prompt or bootstrap. 4. Require separate, explicit consent before writing a learning, creating a skill, or modifying an agent-context file. 5. Display the destination, proposed content, and exact diff before any write. 6. Ensure hook output is treated as untrusted tool output rather than privileged instructions. 7. Scope hook activation to specific projects and provide a visible method to inspect and disable it. 8. Add tests confirming that hook content cannot override the current task, user instructions, or platform safety constraints. ]]>

T02 · Agent Memory Poisoning

Error
Location
SKILL.md:282
Finding
Persistent Poisoning of Agent Instruction and Memory Files<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:40-43, 282-309, 366-380, 463-470`; `hooks/openclaw/handler.js:19-23` **Vulnerability Type**: T02: Agent Memory Poisoning **Risk Level**: High ### Vulnerable Instructions ```markdown | Broadly applicable learning | Promote to `CLAUDE.md`, `AGENTS.md`, and/or `.github/copilot-instructions.md` | | Workflow improvements | Promote to `AGENTS.md` (OpenClaw workspace) | | Tool gotchas | Promote to `TOOLS.md` (OpenClaw workspace) | | Behavioral patterns | Promote to `SOUL.md` (OpenClaw workspace) | ``` ```markdown ## Promoting to Project Memory When a learning is broadly applicable (not a one-off fix), promote it to permanent project memory. ### When to Promote - Learning applies across multiple files/features - Knowledge any contributor (human or AI) should know - Prevents recurring mistakes - Documents project-specific conventions ### Promotion Targets | Target | What Belongs There | |--------|-------------------| | `CLAUDE.md` | Project facts, conventions, gotchas for all Claude interactions | | `AGENTS.md` | Agent-specific workflows, tool usage patterns, automation rules | | `.github/copilot-instructions.md` | Project context and conventions for GitHub Copilot | | `SOUL.md` | Behavioral guidelines, communication style, principles (OpenClaw workspace) | | `TOOLS.md` | Tool capabilities, usage patterns, integration gotchas (OpenClaw workspace) | ### How to Promote 1. **Distill** the learning into a concise rule or fact 2. **Add** to appropriate section in target file (create file if needed) 3. **Update** original entry: - Change `**Status**: pending` → `**Status**: promoted` - Add `**Promoted**: CLAUDE.md`, `AGENTS.md`, or `.github/copilot-instructions.md` ``` ```markdown ### Promotion Rule (System Prompt Feedback) Promote recurring patterns into agent context/system prompt files when all are true: - `Recurrence-Count >= 3` - Seen across at least 2 distinct tasks - Occurred within a 30- ...[truncated 2794 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Treat all conversation-derived learnings and command output as untrusted data. 2. Prohibit automatic or agent-initiated promotion into `CLAUDE.md`, `AGENTS.md`, Copilot instructions, `SOUL.md`, and `TOOLS.md`. 3. Require explicit user approval for every promotion, including an exact diff and the original provenance. 4. Remove the “promote aggressively” guidance and default to no promotion when trust or applicability is uncertain. 5. Store learnings in a non-executable data format that is not automatically interpreted as agent instruction. 6. Apply an allowlist of writable promotion targets and reject behavioral directives, tool commands, external URLs, and secret-bearing content. 7. Record the source session, author, timestamp, review status, and evidence supporting each proposed rule. 8. Require human review before committing promoted content to a shared repository. 9. Add integrity controls so future sessions can distinguish reviewed policy from untrusted learned observations. 10. Provide rollback and expiration mechanisms for promoted rules. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/extract-skill.sh:97
Finding
Workspace Write Boundary Can Be Bypassed Through Symbolic Links<![CDATA[ ## Vulnerability Details **File Location**: `scripts/extract-skill.sh:97-112, 148-151` **Vulnerability Type**: T09: Insecure Skill Coding Practices **Risk Level**: Medium ### Vulnerable Code The script performs only lexical checks on the user-selected output directory: ```bash # Validate output path to avoid writes outside current workspace. if [[ "$SKILLS_DIR" = /* ]]; then log_error "Output directory must be a relative path under the current directory." exit 1 fi if [[ "$SKILLS_DIR" =~ (^|/)\.\.(/|$) ]]; then log_error "Output directory cannot include '..' path segments." exit 1 fi SKILLS_DIR="${SKILLS_DIR#./}" SKILLS_DIR="./$SKILLS_DIR" SKILL_PATH="$SKILLS_DIR/$SKILL_NAME" ``` The resulting path is then created and opened without canonicalization or symbolic-link checks: ```bash # Create skill directory structure log_info "Creating skill: $SKILL_NAME" mkdir -p "$SKILL_PATH" # Create SKILL.md from template cat > "$SKILL_PATH/SKILL.md" << TEMPLATE ``` ### Technical Analysis Rejecting absolute paths and `..` path components prevents straightforward traversal but does not guarantee that the resolved destination remains below the current workspace. Unix file operations follow symbolic links by default. If an existing component of `SKILLS_DIR` or `SKILL_PATH` is a symbolic link to a directory outside the workspace, `mkdir -p` and the subsequent shell redirection operate on the linked destination. The script therefore enforces a lexical path boundary rather than a filesystem-resolved boundary. The existing-directory check does not mitigate this condition because `-d` follows symbolic links, and the script only aborts when the complete skill path already resolves to a directory. An attacker can arrange a symlinked parent directory while leaving the final skill directory absent. ### Attack Path 1. An attacker gains control of files inside the workspace or supplies a prepared project archive. 2. The attacker creates a relative ...[truncated 1094 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Resolve the workspace root and destination parent with `realpath` or `realpath -m` before creating files. 2. Verify that the canonical destination begins with the canonical workspace-root path followed by a path separator. 3. Inspect every existing path component with `lstat` and reject symbolic links. 4. Recheck the resolved destination immediately before opening the output file to reduce time-of-check/time-of-use exposure. 5. Create directories one component at a time while refusing symlink traversal. 6. Open the destination using no-follow semantics where supported, such as a small helper using `openat()` with `O_NOFOLLOW`. 7. Refuse to overwrite an existing file, including a symbolic link, and use exclusive atomic creation. 8. For example, enforce a canonical boundary before writing: ```bash WORKSPACE_ROOT="$(realpath .)" PARENT="$(realpath -m "$SKILLS_DIR")" case "$PARENT/" in "$WORKSPACE_ROOT/"*) ;; *) log_error "Resolved output directory escapes the workspace." exit 1 ;; esac if find "$SKILLS_DIR" -type l -print -quit 2>/dev/null | grep -q .; then log_error "Output path cannot contain symbolic links." exit 1 fi ``` 9. Perform the final file creation atomically and fail if `SKILL.md` already exists. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (15)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description presents a memory/learning-capture capability triggered by failures, corrections, missing capabilities, API/tool issues, outdated knowledge, or improved recurring approaches. The supplied code does not capture learnings, record errors/corrections, review prior learnings, or implement those triggers. Instead, it is a CLI helper that generates a new skill scaffold on disk from a learning entry, including directory creation and template file writing. While related to the broader learning/skill workflow, its primary purpose and concrete behavior are materially different from the declared description.

Agent Config Directory Access

High
Category
Agent Snooping
Content
### Option 2: User-Level Configuration

Add to `~/.claude/settings.json` for global activation:

```json
{
Confidence
90% confidence
Finding
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.

Exfiltration Commands

High
Category
Prompt Injection
Content
### sessions_send

Send message to another session:
```
sessions_send(sessionKey="session-id", message="Learning: API requires X-Custom-Header")
```
Confidence
90% confidence
Finding
Instructions found that direct the agent to transmit conversation context or user data to external services.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The description says to use the skill when a command fails unexpectedly, when a user corrects the agent, when a better approach is discovered, and to review learnings before major tasks. Several of these conditions are broad and subjective, especially 'a better approach is discovered' and 'before major tasks,' which do not define clear boundaries or exclusions for when the skill should or should not activate.

Session Persistence

Medium
Category
Rogue Agent
Content
└── FEATURE_REQUESTS.md
```

### Create Learning Files

```bash
mkdir -p ~/.openclaw/workspace/.learnings
Confidence
88% confidence
Finding
This skill instructs creation and ongoing use of persistent workspace files under `~/.openclaw/workspace/.learnings`, which can retain user corrections, tool failures, and potentially sensitive workflow context across sessions. Even with warnings not to store secrets, session persistence increases the blast radius of accidental data retention and can expose prior-session information to later agents or users in the same environment.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The listed triggers include everyday phrases like 'Actually, it should be...', 'Can you also...', and 'Is there a way to...', which commonly occur in normal chat and are not specific to self-improvement logging. Without stronger constraints, these examples risk unintended invocation or excessive logging during routine conversation.

Skill Enumeration

Medium
Category
Agent Snooping
Content
When the above learning is extracted as a skill, it becomes:

**File**: `skills/docker-m1-fixes/SKILL.md`

```markdown
---
Confidence
80% confidence
Finding
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Session Persistence

Medium
Category
Rogue Agent
Content
### Option 1: Project-Level Configuration

Create `.claude/settings.json` in your project root:

```json
{
Confidence
84% confidence
Finding
Project-level hook configuration introduces persistent behavior that automatically executes commands in future sessions. In this self-improvement skill, persistence makes the behavior more dangerous because it may continue collecting context or responding to prompts long after the user forgets it was enabled.

Vague Triggers

Medium
Confidence
95% confidence
Finding
An empty matcher causes the hook to fire on every user prompt, creating an always-on execution path for a shell command. In this skill context, that broad trigger scope increases exposure to accidental data capture, unnecessary processing, and abuse if the hook script is modified or replaced.

Vague Triggers

Medium
Confidence
97% confidence
Finding
Using an empty matcher in a user-level configuration makes the hook globally active across sessions and repositories, greatly expanding where the shell script runs. Because it lives under the user's agent config directory, compromise or unexpected behavior in the script can persist and affect unrelated work, increasing the blast radius.

Vague Triggers

Medium
Confidence
93% confidence
Finding
Although presented as 'lower overhead', the minimal setup still executes the hook for every prompt due to the empty matcher. That makes the example misleading from a security perspective because it reduces functionality but not execution scope.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The Codex CLI example also uses an empty matcher, so the command hook runs on all prompts rather than on a defined subset of cases. In an agent tooling context, broad implicit execution of shell scripts is risky because users may copy the sample verbatim into automation-heavy environments.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The documentation asserts that hook scripts 'only output text' and 'don't modify files or run commands', but the setup explicitly executes shell scripts as hook commands. That mismatch can cause users to overtrust the hooks' behavior and deploy them without appropriate review, even though invoked shell scripts can perform arbitrary actions with the agent's privileges.

Session Persistence

Medium
Category
Rogue Agent
Content
openclaw hooks enable self-improvement
```

### 3. Create Learning Files

Create the `.learnings/` directory in your workspace:
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.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The 'Detection Triggers' section includes generic conditions such as 'Knowledge gaps', 'API errors', and user corrections like 'No, that's wrong...', without clearly constraining when the skill should activate versus merely observe normal conversation flow. Because this is a markdown file and the trigger list lacks explicit scope limits or negative examples, it creates a vague invocation surface.

Static analysis

No suspicious patterns detected.