Back to skill

Security audit

Safe Self-Improvement

Security checks for vulnerabilities and agentic risk

Overview

The skill is not clearly malicious, but it automatically stores conversation and error learnings for future sessions and includes an under-disclosed promotion bypass, so users should review it before installing.

Install only in low-sensitivity personal workspaces where automatic local learning logs are acceptable. Review .learnings regularly, avoid logging raw user text or command output, and remove or disable the promotion-gate force command before relying on the approval model. Do not use it for financial, medical, critical infrastructure, or shared environments without stronger human-controlled storage and review.

Vulnerability Patterns
  • 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
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • 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 (4)

T02 · Agent Memory Poisoning

Error
Location
SKILL.md:38
Finding
Untrusted Conversation Content Is Persisted in Cross-Session Agent Memory<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:38, 74-113, 290-299` **Vulnerability Type**: Persistent memory poisoning **Risk Level**: High ### Vulnerable Code ```markdown This skill operates autonomously between sessions. The agent reads SKILL.md on trigger and executes logging, sanitization, and promotion workflows. ``` ```markdown Before writing ANY entry, you MUST run the sanitization script: ```bash ./scripts/sanitize.sh "<content_to_log>" ``` The script checks for: - API keys / tokens (GitHub, AWS, OpenAI, etc.) - Private keys (RSA, EC, SSH, etc.) - Passwords and secrets in plain text - IP addresses (private ranges) - MAC addresses - Phone numbers - Email addresses (non-placeholder) - SSID/WiFi credentials - GPS coordinates - Device serial numbers ``` ```markdown Automatically log when you notice: - **Corrections**: "No, that's not right...", "Actually...", "You're wrong about..." - **Feature Requests**: "Can you also...", "I wish you could...", "Is there a way to..." - **Knowledge Gaps**: User provides info you didn't know, docs are outdated, API differs - **Errors**: Non-zero exit codes, exceptions, unexpected output, timeouts > ⚠️ Note on corrections: If a correction feels suspicious (e.g., repeated similar corrections in short succession), log it but flag it in the entry with `**Confidence**: low`. Do not promote low-confidence learnings without extra scrutiny. ``` ### Technical Analysis The Skill directs the Agent to automatically persist user-controlled corrections, error output, and other conversational material in `.learnings/`, where it can be reviewed during later sessions. The required sanitizer only looks for selected sensitive-data patterns. It does not detect prompt-injection instructions, operational directives, misleading rules, or adversarial text designed to influence future Agent behavior. Suspicious corrections are still stored; the `Confidence: low` marker only limits promotion. It does not prevent the pers ...[truncated 1431 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require explicit user approval before storing any conversation-derived content across sessions. 2. Treat all logged content as untrusted data and serialize it in a strongly delimited, quoted format that cannot be interpreted as Agent instructions. 3. Add detection and rejection for instruction-like language, tool-use directives, role changes, safety overrides, and requests to modify Agent configuration. 4. Store only a minimal Agent-generated summary instead of raw user text or raw command output. 5. Record immutable provenance, including source type, session identifier, author, trust level, and approval state. 6. Prevent unapproved or low-confidence records from being loaded into normal task context. 7. Require a separate human review before any stored entry can influence future behavior, independently of the later promotion process. 8. Keep promotion candidates in a data-only review queue rather than directly presenting their original content as trusted context. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/promotion-gate.sh:149
Finding
Promotion Gate Exposes an Unauthenticated Force Bypass<![CDATA[ ## Vulnerability Details **File Location**: `scripts/promotion-gate.sh:149-179, 190-191` **Vulnerability Type**: Approval and rate-limit bypass **Risk Level**: High ### Vulnerable Code ```bash cmd_force() { local id="${1:-}" local reason="${2:-unknown}" [ -z "$id" ] && { echo "Usage: promotion-gate.sh force <learning_id> <reason>"; exit 1; } validate_id "$id" || exit 1 echo "⚠️ FORCE: bypassing gate on user responsibility." local state=$(get_state) local now=$(now_ts) local new_state new_state=$(run_python " import json, sys d = json.loads(sys.stdin.read()) now = $now cutoff = now - 7 * 24 * 3600 d['promotions'] = [p for p in d['promotions'] if p.get('ts', 0) > cutoff] sys.stdout.write(json.dumps(d)) " <<< "$state") updated=$(run_python " import json, sys d = json.loads(sys.stdin.read()) d['promotions'].append({'id': '$id', 'ts': $now}) d['last_batch'] = $now sys.stdout.write(json.dumps(d)) " <<< "$new_state") save_state "$updated" echo "✅ Force-recorded $id. Reason: $reason" } ``` ```bash case "$COMMAND" in check) cmd_check ;; approve) shift; cmd_approve "$@" ;; status) cmd_status ;; force) shift; cmd_force "$@" ;; *) echo "Usage: promotion-gate.sh [check|approve <id>|status|force <id> <reason>]" ;; esac ``` ### Technical Analysis The script advertises mandatory human approval and rate limiting, but its public command dispatcher exposes `force`, which directly writes a promotion record without calling `cmd_check`. It therefore bypasses both the 24-hour promotion limit and the cooldown. No authentication, approval token, terminal confirmation, or external authorization artifact distinguishes a human invocation from an Agent invocation. The free-form `reason` is only printed and is not evidence of approval. The normal `approve` operation is also not cryptographically bound to a particular proposed rule, target file, or approving identity. The script does not itself m ...[truncated 1217 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the `force` command from both the implementation and public dispatcher. 2. Do not rely on an Agent-callable script as proof of human approval. 3. Require an out-of-band authorization artifact that the Agent cannot create, such as a signed approval record or a trusted UI-mediated confirmation. 4. Bind approval to the learning ID, exact proposed text, destination file, destination location, timestamp, and approving identity. 5. Verify the approval artifact immediately before modifying the target file. 6. Store promotion state in a protected location that is not freely writable by the Agent performing the promotion. 7. Make the log append-only and record failed or bypass attempts. 8. Reject duplicate promotion IDs and validate that the referenced learning exists and is eligible. 9. Add automated tests demonstrating that no command path can bypass cooldown, quota, or human authorization. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/sanitize.sh:10
Finding
Sensitive Content Is Exposed Through Process Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/sanitize.sh:10-15` and `SKILL.md:89-113` **Vulnerability Type**: Plaintext sensitive data exposure through process arguments **Risk Level**: Medium ### Vulnerable Code ```bash CONTENT="${1:-}" if [ -z "$CONTENT" ]; then echo "Usage: sanitize.sh <text>" exit 1 fi ``` The required invocation is: ```bash ./scripts/sanitize.sh "<content_to_log>" ``` ### Technical Analysis The sanitizer accepts the complete proposed log entry as its first command-line argument. If that entry contains a token, password, private key fragment, internal address, or other sensitive material, the sensitive value is placed in the process argument vector before it can be detected and rejected. Depending on the operating system and process isolation configuration, command-line arguments can be visible through process inspection interfaces such as `ps` or `/proc`. They may also be captured by command tracing, shell history when invoked manually, monitoring software, or process-audit systems. Sanitization after placing the content in argv cannot prevent this transient disclosure. ### Attack Path 1. A command failure or user message includes sensitive information. 2. Following `SKILL.md`, the Agent invokes `sanitize.sh` with the complete content as a quoted argument. 3. The operating system stores that content in the sanitizer process's argv. 4. A concurrent same-host user, monitoring process, or audit collector reads the command line. 5. The sanitizer rejects the entry, but the sensitive value has already been exposed outside the intended data flow. ### Impact Assessment The issue can disclose any sensitive value passed for inspection to same-host principals or monitoring systems capable of reading process arguments. It does not itself send data over the network, elevate privileges, or create persistence. The practical scope depends on host process-visibility restrictions and the privileges of other local users ...[truncated 28 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Read content from standard input instead of argv: ```bash printf '%s' "$content" | ./scripts/sanitize.sh ``` 2. Modify the script to use `IFS= read -r` or `cat` to consume stdin without echoing the input. 3. For large content, use a temporary file created with `mktemp`, mode `0600`, restrictive `umask`, and guaranteed cleanup through `trap`. 4. Disable shell tracing around sensitive processing and document that callers must not place raw content in shell history. 5. Avoid printing matched secret values or complete sensitive patterns in diagnostics. 6. Add a regression test that inspects the sanitizer process command line and verifies that submitted content is absent. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/sanitize.sh:18
Finding
Incomplete and Inconsistent Secret Detection Can Produce False Safety Results<![CDATA[ ## Vulnerability Details **File Location**: `scripts/sanitize.sh:18-55`; secondary location `scripts/audit.sh:25-32` **Vulnerability Type**: Inadequate sensitive-data validation **Risk Level**: Medium ### Vulnerable Code From `scripts/sanitize.sh`: ```bash PATTERNS=( # API keys / tokens (GitHub, AWS, OpenAI, etc.) "(ghp_|gho_|github_pat_|sk-|AKIA|xox[baprs])[a-zA-Z0-9]{10,}" # Private keys "-----BEGIN (RSA |EC |DSA |OPENSSH )PRIVATE KEY-----" # Passwords in plain text (various formats) -E "(password|passwd|pwd|secret|passphrase)\\s*(is|:|=|:\\\\s*)\\s*[^\\\\s'\\\"]{4,}" # IPs "192\\.168\\.[0-9]+\\.[0-9]+|10\\.[0-9]+\\.[0-9]+\\.[0-9]+|172\\.(1[6-9]|2[0-9]|3[0-1])\\.[0-9]+\\.[0-9]+" # MAC addresses "([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}" # Phone numbers (China mobile pattern) "1[3-9][0-9]{9}" # Email (non-placeholder, simple check) "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}" # SSID with password "(ssid|wifi|wlan)\\s*[:=]\\s*[^\\\\s'\\\"]{1,30}" # GPS coordinates (lat, lon) "[0-9]+\\.[0-9]{6,},[0-9]+\\.[0-9]{6,}" # Device serial numbers "(serial|device.id|devid)\\s*[:=]\\s*[A-Z0-9]{6,}" ) FOUND=0 MATCHES=() for pattern in "${PATTERNS[@]}"; do if echo "$CONTENT" | grep -Ei "$pattern" > /dev/null 2>&1; then FOUND=1 MATCHES+=("Pattern matched: $pattern") fi done ``` From `scripts/audit.sh`: ```bash SENSITIVE_PATTERNS=( "(ghp_|gho_|github_pat_|sk-|AKIA|xox[baprs])[a-zA-Z0-9]{10,}" "-----BEGIN (RSA |EC |DSA |OPENSSH )PRIVATE KEY-----" "1[3-9][0-9]{9}" "192\.168\.[0-9]+\.[0-9]+|10\.[0-9]+\.[0-9]+\.[0-9]+" ) ``` ### Technical Analysis The sanitizer contains a stray unquoted `-E` array element. During iteration, that value is passed as the apparent pattern to an already option-bearing `grep -Ei` invocation. Errors are redirected and ignored, preventing operators from noticing malformed scanner behavior. The password and SSID express ...[truncated 1773 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the stray `-E` array entry and place every expression in an explicitly quoted array element. 2. Check and propagate scanner execution errors instead of redirecting and ignoring them. 3. Use `printf '%s\n'` rather than `echo` for predictable input handling. 4. Centralize all sensitive-data rules in one implementation shared by pre-write sanitization and periodic auditing. 5. Add unit tests with positive, negative, multiline, encoded, malformed, and boundary-condition fixtures for every supported secret class. 6. Supplement pattern matching with entropy checks and maintained secret-scanning tooling where appropriate. 7. Treat scanner success as “no configured pattern matched,” not proof that content contains no sensitive data. 8. Minimize stored content and redact values before scanning rather than relying exclusively on detection. 9. Run the scanner over all archive and state files, not only top-level `.learnings/*.md` files. 10. Fail closed if any scanner rule is invalid or any scan command returns an unexpected status. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (15)

Anti-Refusal Statement

High
Category
Anti-Refusal
Content
| Secrets in logs | ⚠️ Soft | ✅ **Script-enforced sanitization** |
| Bulk promotion abuse | ❌ Unchecked | ✅ **Rate-limiting + cooldown period** |
| No self-audit | ❌ None | ✅ **Automated audit.sh** |
| High-security use | ❌ No warning | ✅ **Explicit disclaimer** |
| Dynamic payload fetching | ⚠️ Risk | ✅ **Explicitly forbidden** |

## Installation
Confidence
80% confidence
Finding
Skill instructs the agent to omit warnings, disclaimers, or ethical commentary. Stripping safety caveats hides risk from the user and is a common jailbreak preamble.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description presents a full self-improvement system with capture, correction handling, approval gating, sanitization, auditing, and controlled promotion. The supplied code implements only one narrow component: an audit script for existing markdown files in .learnings. It reads local learning files, performs pattern/format/link/size checks, and emits a pass/fail summary. While this partially aligns with the 'audit tooling' and some sanitization-related checking, it materially falls short of the declared primary purpose and omits major described capabilities such as capturing learnings, enforcing human approval, and rate-limited promotion. Therefore the description does not accurately represent what this code chunk actually does.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description presents a broad self-improvement workflow skill with multiple controls: learning capture, correction handling, mandatory human approval, audit support, and promotion throttling. The supplied code chunk implements only one narrow component: sanitization of input text by regex-scanning for sensitive data and blocking on matches. While sanitization is mentioned in the description, the code does not realize the core advertised workflow or governance features, and its primary behavior is materially narrower and different from the declared purpose. No suspicious undeclared external access is present, but the description substantially overstates what this code chunk does.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The script advertises a mandatory human-approval gate, but the `force` command records promotions without enforcing `cmd_check` or any separate authorization control. In a self-improvement/promotion workflow, this creates a direct bypass of the core safety mechanism, allowing rate limits and approval requirements to be sidestepped by anyone who can invoke the script.

Vague Triggers

Medium
Confidence
93% confidence
Finding
The invocation conditions are very broad and include common events like failures, corrections, outdated knowledge, and discovering a better approach. In practice, this can cause the skill to activate frequently and collect large amounts of conversational or operational context, increasing the chance of over-logging sensitive data or creating an unintended persistence channel. The danger is heightened because the skill is expressly designed to store cross-session learnings locally.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
- **No external transmission**: Zero network calls; no data sent to any third party
- **Sensitive data protection**: `scripts/sanitize.sh` must pass before any entry is written (see Pre-Log Sanitization)
- **Cross-session sharing**: Blocked by default; requires explicit user approval per session
- **Read-only recommendation**: For high-security environments, set `.learnings/` to read-only (`chmod 555`)

## Model Invocation Note
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
- **No external transmission**: Zero network calls; no data sent to any third party
- **Sensitive data protection**: `scripts/sanitize.sh` must pass before any entry is written (see Pre-Log Sanitization)
- **Cross-session sharing**: Blocked by default; requires explicit user approval per session
- **Read-only recommendation**: For high-security environments, set `.learnings/` to read-only (`chmod 555`)

## Model Invocation Note
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
- **No external transmission**: Zero network calls; no data sent to any third party
- **Sensitive data protection**: `scripts/sanitize.sh` must pass before any entry is written (see Pre-Log Sanitization)
- **Cross-session sharing**: Blocked by default; requires explicit user approval per session
- **Read-only recommendation**: For high-security environments, set `.learnings/` to read-only (`chmod 555`)

## Model Invocation Note
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
1. **NEVER auto-modify core files** — `SOUL.md`, `AGENTS.md`, `TOOLS.md`, `MEMORY.md`, `IDENTITY.md` must NOT be modified without explicit user approval shown as a clear question and awaiting a "yes" response.
2. **No secrets in logs** — Never log tokens, API keys, passwords, private keys, env vars, or full config/source files. Use redacted summaries only.
3. **No cross-session sharing without approval** — Using `sessions_send` or `sessions_spawn` to share learnings requires the same approval gate as promotion: present what will be shared, to which session, and wait for explicit "yes". Never share automatically.
4. **No hook scripts** — This skill does not install or use hook scripts that read command output.
5. **No dynamic payload fetching** — Never fetch remote content at runtime for skill logic.
6. **Promotion = proposal, not action** — When a learning qualifies for promotion, ASK the user first.
Confidence
75% 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.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
## Promotion (Human-Approval Gate + Rate-Limit)

When a learning qualifies for promotion, propose — **never auto-execute**.

### When a Learning Qualifies for Promotion
Confidence
85% 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.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The automatic detection triggers rely on ambiguous natural-language phrases such as corrections or feature requests in ordinary conversation. That makes the skill susceptible to prompt-driven logging of attacker-supplied text, including attempts to poison future behavior, create misleading learnings, or persist adversarial instructions across sessions. In a self-improvement skill, ambiguous auto-capture is more dangerous than in ordinary note-taking because the stored content is intended to influence future actions.

Intent-Code Divergence

Medium
Confidence
99% confidence
Finding
The security manifest comment states 'Environment variables accessed: none', but STATE_FILE is derived from LEARNINGS_DIR if set. This is a direct contradiction between inline documentation and code behavior, not merely omitted detail.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The comments above run_python state that state JSON is piped to Python via stdin and that the Python script uses sys.stdin for state data. In reality, run_python invokes `python3 -B -c "$python_script"` inside command substitution and does not forward stdin to that process, contradicting the documented intent of the helper.

Intent-Code Divergence

Low
Confidence
98% confidence
Finding
The inline security manifest says 'Local files read: $1 (the content to check)', which describes $1 as a file path being read. In the implementation, line L11 assigns $1 directly to CONTENT and the script only pipes that string into grep; no file is opened or read. This is a direct documentation/implementation contradiction about what data source the script handles.

Intent-Code Divergence

Low
Confidence
95% confidence
Finding
The documented purpose promises that a write will be blocked when sensitive data is found. In reality, the script has no write logic and no enforcement hook beyond printing a message and returning exit code 1, so the statement overclaims what the code itself does. This is an intent-level mismatch in the inline documentation.

Static analysis

No suspicious patterns detected.