Back to skill

Security audit

skillminer

Security checks for vulnerabilities and agentic risk

Overview

The skill’s core purpose is disclosed, but it reads sensitive local memory and persists derived reviews, logs, and draft skills with weaker protection than its documentation implies.

Review before installing on any shared or privileged machine. Keep FORGE_RUNNER unset unless you accept sending prompt data off-host, avoid running setup.sh with sudo, and treat state/review/log/_pending outputs as potentially containing private memory content until permissions and scrubbing are hardened.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/run-nightly-scan.sh:81
Finding

Memory-derived reviews, logs, and generated skill drafts bypass deterministic secret scrubbing

Content
View full analysis
> "$LOG" 2>&1 EXIT=$? elif [ "$FORGE_RUNNER" = "claude" ]; then # Note: Claude Code blocks file-read permission bypass as root (security policy). # The claude runner requires running as a non-root user. As root, use FORGE_RUNNER=openclaw. if [ "$(id -u)" = "0" ]; then echo "WARNING: claude runner cannot bypass file permissions as root (Claude Code security policy)." >> "$LOG" echo "Use FORGE_RUNNER=openclaw (default) or run as a non-root user for the claude runner." >> "$LOG" rm -f "$PROMPT_FILE" exit 1 fi claude --print \ --model sonnet \ --effort high \ --permission-mode auto \ --max-budget-usd "$MAX_BUDGET_USD" \ < "$PROMPT_FILE" >> "$LOG" 2>&1 EXIT=$? ``` After execution, the review is promoted without scrubbing. Only the JSON state temporary file is passed through `scrub_file_in_place`: ```bash if [ "$EXIT" -eq 0 ]; then if ! atomic_text_write "$REVIEW_DIR/$TODAY.md.tmp" "$REVIEW_DIR/$TODAY.md"; then echo "[skillminer] ERROR: nightly review tmp failed non-empty check, keeping previous state" >> "$LOG" rollback_state_and_review "review tmp failed non-empty check" VALIDATION_EXIT=2 elif ! { [ -f "$STATE_FILE.tmp" ] && scrub_file_in_place "$STATE_FILE.tmp"; true; } || ! atomic_json_write "$STATE_FILE.tmp" "$STATE_FILE" "$BACKUP_FILE"; then echo "[skillminer] ERROR: nightly state tmp failed JSON validation, restored backup" ...[truncated 4952 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
setup.sh:11
Finding

Sensitive state, review, and log files are created without restrictive permissions

Content
View full analysis
"$LOG" ``` The morning wrapper follows the same pattern: ```bash LOG_DIR="$STATE_DIR/logs" mkdir -p "$LOG_DIR" "$WRITE_LOG_DIR" ``` ```bash { echo "=== skillminer morning-write ===" echo "started: $(date -u --iso-8601=seconds)" echo "CLAWD_DIR=$CLAWD_DIR" echo "FORGE_RUNNER=$FORGE_RUNNER" echo "user: $(id -un)" echo "---" } > "$LOG" ``` ### Technical Analysis The project processes local memory files that may contain credentials and private conversations. Despite this sensitivity, no audited entry point establishes `umask 077`, and the relevant creation paths do not call `chmod` or install files with explicit restrictive modes. On systems using a common `umask 022`, newly created directories are typically mode `0755`, while newly created regular files are typically mode ...[truncated 1701 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
setup.sh:32
Finding

Root setup installs a system-wide command symlink to a potentially user-writable working tree

Content
View full analysis
$SKILL_DIR/scripts/skillminer" fi else SYMLINK_NOTE="Not root, skipped /usr/local/bin/skillminer symlink install." fi ``` ### Technical Analysis When setup is run as root, it automatically creates `/usr/local/bin/skillminer`, a system-wide command, as a symbolic link to the current project checkout. The script does not verify: - Ownership of the checkout - Ownership of `scripts/skillminer` - Write permissions on the target or any parent directory - Whether the target is itself a symlink - Whether an unprivileged user can replace or modify the target later A command under `/usr/local/bin` is commonly treated as a trusted administrative executable. Linking it directly to a mutable working tree violates that trust boundary. If the checkout is owned or writable by an unprivileged user, that user can alter the linked script after installation. A later privileged invocation of `skillminer` then executes attacker-controlled shell code as root. The check for an existing destination prevents direct replacement of an existing `/usr/local/bin/skillminer`, but it does not establish the integrity of the newly linked target. ### Attack Path 1. An administrator extracts or clones the project into a directory owned or writable by an unprivileged user. 2. The administrator runs `sudo bash setup.sh`. 3. Setup creates `/usr/local/bin/skillminer` pointing to `/scripts/skillminer`. 4. The u ...[truncated 972 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (30)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · CHANGELOG.md (reported line 45)May include surrounding context.

md
Hotfix release. 4 defects surfaced by external second-opinion review (3 LLMs: claude-code + codex + gemini).

- [CRIT] **setup.sh installs schema-0.4 template** — every fresh install broken on first `manage-ledger` call. Bumped `state-template.json` schema_version to `0.5`.
- [HIGH] **rollback symmetry in run-nightly-scan.sh** — `rm -f review/$TODAY.md` was only in 1 of 5 rollback branches. Factored into `rollback_state_and_review()` called from all rollback sites.
- [HIGH] **`_pending/<slug>/` orphaned on state rollback** — morning-write now stages writes to `_pending/.staging/<slug>-$STAMP/` and only renames to final path after state commits. Rollback cleans staging dirs.
- [HIGH] **migrate-state.sh acquired no skillminer lock** — races with cron-scheduled wrappers possible. Now uses same hash-derived flock lock as manage-ledger.sh, plus stale-tmp cleanup.

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

md
- Rename cron jobs to skillminer-nightly-scan / skillminer-morning-write

## 0.1.6
- Rewrite SKILL.md body — benefit-focused, non-technical, quick start via ClawHub
- Update Quick Start to include both ClawHub and manual git clone install methods

## 0.1.5

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is about mining local memory files to propose reusable skills and managing draft skill suggestions. The actual code instead implements a secret-scrubbing/redaction helper. Its primary purpose, data handling, and operations do not align with the declared behavior. In particular, it performs content redaction and file rewriting, which are undeclared capabilities unrelated to suggesting skills from recurring patterns. This is a clear description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared purpose is about analyzing recurring patterns in memory files to propose reusable skills and manage draft skill suggestions under a human review workflow. The supplied code does not perform any pattern analysis, skill suggestion, draft creation, trigger handling, or optional external fallback. Instead, it is purely a maintenance/migration utility for a local state file, including version checks, locking, backup, JSON transformation, and overwrite of the state file. This is a materially different primary purpose and introduces undeclared file-modification capabilities unrelated to the described behavior.

Content

No source excerpt is available for this finding.

Memory Manipulation

High
Category
Memory Poisoning
Confidence
80% confidence
Finding

Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Content

Scanner excerpt · USER_GUIDE.md (reported line 244)May include surrounding context.

  • Check that you accepted at least one candidate before 10:00
  • Check cat state/state.json | jq '.candidates'

Reset state

bash
cp state-template.json state/state.json

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 · prompts/nightly-scan.md (reported line 191)May include surrounding context.

md
Empty sections are allowed, but all sections must exist.

Display rules:
- Portfolio section must be first section after the title.
- For each pending candidate already in the ledger, compute `pendingSinceDays` from `createdAt` to `TODAY` in whole days.
- Mark a pending candidate as stale when `pendingSinceDays >= 14`.

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · scripts/lib/atomic-write.sh (reported line 59)May include surrounding context.

sh
local state_file="$1"

  ls -t "${state_file}".bak.[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]T[0-9][0-9][0-9][0-9][0-9][0-9]Z 2>/dev/null \
    | tail -n +8 | xargs -r rm -f
}

acquire_skillminer_lock() {

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · scripts/migrate-state.sh (reported line 64)May include surrounding context.

sh
' "$STATE" > "$TMP"

# Validate
jq -e . "$TMP" >/dev/null || { echo "error: migration produced invalid JSON" >&2; rm -f "$TMP"; exit 1; }
mv "$TMP" "$STATE"

echo "migration complete: $STATE is now schema_version 0.5"

Chaining Abuse

High
Category
Tool Misuse
Confidence
89% confidence
Finding

The pipeline find ... | xargs rm -rf performs recursive deletion over directories discovered in the filesystem, and pathname handling is not null-delimited. If an attacker can create crafted directory names inside the staging tree, whitespace/newline or dash-prefixed names can cause unintended deletions or option confusion, which is especially dangerous because rm -rf is used.

Content

Scanner excerpt · scripts/run-morning-write.sh (reported line 37)May include surrounding context.

sh
# Remove any staging dir not scoped to this run's STAMP — mtime-based cleanup
# leaks crash dirs from within the last hour, which could shadow the new run.
if [[ -d "$CLAWD_DIR/skills/_pending/.staging" ]]; then
  find "$CLAWD_DIR/skills/_pending/.staging" -maxdepth 1 -mindepth 1 -type d ! -name "*-${STAMP}" 2>/dev/null | xargs -r rm -rf
fi

BACKUP_FILE="$(create_state_backup "$STATE_FILE" "$STAMP")"

External Model or Provider Selection

High
Category
Excessive Agency
Confidence
92% confidence
Finding

The script can route the full prompt to an external Claude provider when FORGE_RUNNER=claude, and that prompt contains local filesystem paths plus the complete writer instructions. In a skill that mines local memory and drafts new skills, this increases the risk of sensitive local context or metadata being transmitted off-host without a strong consent gate in this wrapper.

Content

Scanner excerpt · scripts/run-morning-write.sh (reported line 97)May include surrounding context.

sh
rm -f "$PROMPT_FILE"
    exit 1
  fi
  claude --print \
    --model sonnet \
    --effort high \
    --permission-mode auto \

Chaining Abuse

High
Category
Tool Misuse
Confidence
89% confidence
Finding

This rollback cleanup repeats the same unsafe pattern of piping filesystem results into xargs rm -rf without null delimiting or an explicit option terminator. In a shared or attacker-influenced workspace, crafted staging directory names could turn rollback into deletion of unintended paths.

Content

Scanner excerpt · scripts/run-morning-write.sh (reported line 117)May include surrounding context.

sh
rollback_pending_staging() {
  # Remove any staging dirs left by this run
  find "$STAGING_BASE" -maxdepth 1 -type d -name "*-${STAMP}" 2>/dev/null | xargs -r rm -rf
}

rollback_state_and_write_log() {

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/run-morning-write.sh (reported line 125)May include surrounding context.

sh
if [[ -f "$BACKUP_FILE" ]]; then
    cp -f "$BACKUP_FILE" "$STATE_FILE"
  fi
  rm -f "$WRITE_LOG_DIR/$TODAY.md" "$STATE_FILE.tmp"
  rollback_pending_staging
  echo "[skillminer] ROLLBACK: $reason" >> "$LOG"
}

Chaining Abuse

High
Category
Tool Misuse
Confidence
81% confidence
Finding

The log-rotation pipeline parses filenames through text processing and then passes them to xargs rm -f, which is fragile for filenames containing spaces, newlines, or leading dashes. While the log directory is more likely to be controlled by the script itself, the pattern is still unsafe and could delete the wrong files if hostile filenames are introduced.

Content

Scanner excerpt · scripts/run-morning-write.sh (reported line 189)May include surrounding context.

sh
# rotate logs — keep last 30
find "$LOG_DIR" -name 'write-*.log' -type f -printf '%T@ %p\n' | \
  sort -n | head -n -30 | cut -d' ' -f2- | xargs -r rm -f

exit "$FINAL_EXIT"

External Model or Provider Selection

High
Category
Excessive Agency
Confidence
90% confidence
Finding

Skill selects an external model or provider that may use a different account or billing plan than the operator expects. Undisclosed model switches can cause unexpected cost or quota consumption.

Content

Scanner excerpt · scripts/run-nightly-scan.sh (reported line 98)May include surrounding context.

sh
rm -f "$PROMPT_FILE"
    exit 1
  fi
  claude --print \
    --model sonnet \
    --effort high \
    --permission-mode auto \

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/run-nightly-scan.sh (reported line 118)May include surrounding context.

sh
if [[ -f "$BACKUP_FILE" ]]; then
    cp -f "$BACKUP_FILE" "$STATE_FILE"
  fi
  rm -f "$REVIEW_DIR/$TODAY.md"
  rm -f "$STATE_FILE.tmp"
  echo "[skillminer] ROLLBACK: $reason" >> "$LOG"
}

Chaining Abuse

High
Category
Tool Misuse
Confidence
84% confidence
Finding

The log rotation pipeline passes file names from find through text processing into xargs rm, which is unsafe for unusual path names containing newlines or other delimiter-confusing characters. If an attacker can create crafted log filenames in LOG_DIR, the cleanup step could delete unintended files or fail unpredictably; because this script may run from cron and potentially with elevated privileges, the impact is amplified.

Content

Scanner excerpt · scripts/run-nightly-scan.sh (reported line 160)May include surrounding context.

sh
# rotate logs — keep last 30
find "$LOG_DIR" -name 'scan-*.log' -type f -printf '%T@ %p\n' | \
  sort -n | head -n -30 | cut -d' ' -f2- | xargs -r rm -f

exit "$FINAL_EXIT"

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/skillminer (reported line 21)May include surrounding context.

text
Usage:
  skillminer scan     Run the nightly scan wrapper
  skillminer write    Run the morning write wrapper
  skillminer full     Run scan, then write
  skillminer status   Show last scan/write timestamps and pending count
  skillminer help     Show this help
EOF

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 43)May include surrounding context.

↓ YOU DECIDE forge accept / reject / defer / silence ↓ morning write drafts a SKILL.md into skills/_pending// you review it, promote it, ship it

text

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The prompt directs automatic execution of a host shell script on a cron trigger with no user-facing confirmation or safety warning. Even if the script path is intended to be local and controlled, this creates a code-execution surface where a modified skill directory, compromised wrapper script, or unsafe environment variable context could cause unintended privileged actions on the host.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The prompt instructs the agent to tail the latest scan log and report the error verbatim, which can disclose sensitive operational details such as filesystem paths, environment-derived values, internal errors, or contents emitted by nested tools. Because the final text is an announcement payload, this increases the chance that sensitive debugging data is propagated to external messaging channels or broader audiences.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The examples require candidate aging text using German phrases like "Tage" and "pending seit", which imposes a specific language/locale in the generated review output. The file does not offer a user language choice or justify the locale restriction as region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The template requires an "imperative English sentence" in the description and a "One-line English purpose statement," which imposes a specific language on generated skill content. This is a natural-language locale policy issue because the file does not offer any user choice or explain a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The function scrub_file_in_place rewrites the supplied file by creating a temporary file and moving it over the original. Although comments describe the behavior, there is no user-facing prompt, log, or visible disclosure in the code when this destructive file modification occurs.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The inline comment says the script accepts schema versions 0.2, 0.3, and 0.4, but the case statement immediately below actually accepts only 0.5 and rejects 0.2/0.3/0.4 as legacy. This is an active contradiction in operator-facing documentation about what state files the script will process.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The comment and error message say promote requires schema 0.3 or 0.4, and the condition also mentions 0.3/0.4/0.5, but the top-level guard earlier already rejects 0.3 and 0.4 outright. In practice, only 0.5 can reach this branch, so the documentation and messaging here contradict actual executable behavior.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.