Back to skill

Security audit

Self Discipline

Security checks for vulnerabilities and agentic risk

Overview

This skill is coherent and local, but needs Review because it persists agent rules and executable validators while providing broad activation modes and fragile security-validator examples.

Install only if you want a persistent local enforcement system for agent behavior. Choose manual or ask-first setup modes, review every proposed AGENTS.md, HEARTBEAT.md, hook, and validator change before approving it, and harden/test validator scripts instead of relying on the provided examples for security-critical protection.

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

T09 · Insecure Skill Coding Practices

Warning
Location
validators.md:38
Finding
Secret-scanning pre-commit validator can be bypassed with crafted filenames## Vulnerability Details **File Location**: `validators.md`, lines 38-49 **Vulnerability Type**: Incomplete and unsafe shell filename handling **Risk Level**: Medium ### Vulnerable Code ```bash # Check staged files for secrets STAGED=$(git diff --cached --name-only) for file in $STAGED; do if grep -qE '(api_key|password|secret)\s*=' "$file" 2>/dev/null; then echo "❌ BLOCKED: Potential secret in $file" echo "Rule: no-secrets-in-code (INC-002)" exit 1 fi done exit 0 ``` ### Technical Analysis The example processes the newline-delimited output of `git diff --cached --name-only` through unquoted shell word splitting: ```bash for file in $STAGED ``` Git filenames may legally contain spaces, tabs, newlines, wildcard characters, and leading hyphens. Consequently: - A filename containing whitespace is split into multiple nonexistent paths. - A filename containing a newline can alter the apparent list of files. - Shell wildcard characters can undergo pathname expansion. - A leading-hyphen filename may be interpreted by `grep` as an option because no `--` option terminator is used. - Errors are hidden by `2>/dev/null`, and failure to inspect a file does not block the commit. The validator therefore fails open: unreadable or incorrectly parsed staged files are treated as safe. Although presented as an example, the document explicitly directs users to install such validators as Git hooks, making this an insecure implementation pattern rather than merely illustrative pseudocode. ### Attack Path 1. An attacker who can contribute repository content creates a file whose name contains whitespace, a newline, or another shell-sensitive character. 2. The attacker places a value matching the secret pattern in that file, such as `api_key = ...`. 3. The crafted file is staged for commit. 4. `git diff --cached --name-only` returns the filename, but command substitution and `for file in $STAGED ...[truncated 594 chars]
Remediation
## Remediation Suggestions Use Git's NUL-delimited output and consume it without command substitution or word splitting: ```bash while IFS= read -r -d '' file; do if [[ ! -f "$file" ]]; then echo "❌ BLOCKED: Cannot safely inspect staged path: $file" exit 1 fi if grep -qE -- '(api_key|password|secret)[[:space:]]*=' "$file"; then echo "❌ BLOCKED: Potential secret in $file" exit 1 fi done < <(git diff --cached --name-only -z --diff-filter=ACMR) ``` Additional hardening should include: - Scan staged blob contents rather than working-tree files, so the validator checks exactly what will be committed. - Use `--` before all externally derived path arguments. - Treat inspection errors as blocking failures. - Test filenames containing spaces, tabs, newlines, glob characters, Unicode, and leading hyphens. - Supplement pattern matching with a maintained secret-scanning tool where strong assurance is required.

T09 · Insecure Skill Coding Practices

Warning
Location
validators.md:91
Finding
Protected-path deletion validator is bypassable through unnormalized paths and ineffective tilde entries## Vulnerability Details **File Location**: `validators.md`, lines 91-111 **Vulnerability Type**: Path-validation bypass **Risk Level**: Medium ### Vulnerable Code ```bash ACTION="$1" TARGET="$2" if [[ "$ACTION" == "delete" ]]; then # Check if target is in protected paths PROTECTED_PATHS=( "/opt/docker" "/etc" "~/.ssh" "~/clawd" ) for path in "${PROTECTED_PATHS[@]}"; do if [[ "$TARGET" == "$path"* ]]; then echo "⚠️ CONFIRMATION REQUIRED" echo "Attempting to delete in protected path: $TARGET" echo "Rule: confirm-delete (INC-003)" echo "" echo "Please confirm with user before proceeding." exit 1 fi done fi exit 0 ``` ### Technical Analysis The validator compares raw strings rather than canonical filesystem paths. It does not resolve: - Relative paths - `.` and `..` components - Symbolic links - Alternative references to the same directory - User-home expansion The entries `"~/.ssh"` and `"~/clawd"` are quoted strings stored in an array. Bash does not perform tilde expansion in this context, so an actual target such as `/home/alice/.ssh` does not match `"~/.ssh"*`. Protected absolute paths can also be expressed in bypassing forms such as `/tmp/../etc`, or reached through a symbolic link outside the protected prefix. The validator then exits successfully even though the eventual deletion resolves into a protected location. ### Attack Path 1. A deletion target is supplied using a noncanonical representation, such as `/tmp/../etc`, `$HOME/.ssh`, or a symbolic link pointing into `/etc`. 2. The validator compares the raw target string against its literal prefix list. 3. None of the string prefixes match. 4. The validator returns exit status zero. 5. A caller that trusts this result proceeds with the destructive operation without requesting the intended confirmation. 6. Files inside a protected directory ...[truncated 447 chars]
Remediation
## Remediation Suggestions - Expand home-directory paths explicitly with `$HOME`, not quoted literal tildes. - Require absolute targets and canonicalize them before comparison. - Resolve existing targets with `realpath` or an equivalent platform-specific API. - For targets that may not yet exist, canonicalize the nearest existing parent and validate the final component separately. - Account for symbolic links and reject a target when canonicalization fails. - Compare path boundaries rather than unrestricted string prefixes. - Pass the canonical, validated path to the destructive operation so validation and use cannot refer to different paths. - Revalidate immediately before deletion to reduce time-of-check/time-of-use races. A hardened comparison should resemble: ```bash protected_paths=( "/opt/docker" "/etc" "$HOME/.ssh" "$HOME/clawd" ) canonical_target=$(realpath -- "$TARGET") || { echo "❌ BLOCKED: Unable to canonicalize target" exit 1 } for protected in "${protected_paths[@]}"; do canonical_protected=$(realpath -- "$protected") || continue if [[ "$canonical_target" == "$canonical_protected" || "$canonical_target" == "$canonical_protected/"* ]]; then echo "⚠️ CONFIRMATION REQUIRED" exit 1 fi done ```

T09 · Insecure Skill Coding Practices

Warning
Location
validators.md:58
Finding
Pre-send validator testing uses a different input channel from the validator implementation## Vulnerability Details **File Location**: `validators.md`, lines 58-76 **Vulnerability Type**: Fail-open validator input-contract mismatch **Risk Level**: Medium ### Vulnerable Code ```bash # SECURITY MANIFEST: # Environment variables accessed: none # External endpoints called: none # Local files read: message content (argument $1) # Local files written: none # Validator: no-urls-with-secrets # Incident: INC-001 # Severity: CRITICAL MESSAGE="$1" # Check for URLs with auth parameters if echo "$MESSAGE" | grep -qE 'https?://[^\s]*[?&](pass|password|token|key|secret|auth)='; then echo "❌ BLOCKED: URL contains embedded credentials" echo "Rule: no-urls-with-secrets (INC-001)" echo "" echo "The URL contains a query parameter that looks like a secret." echo "Do not send URLs with ?pass=, ?token=, ?key=, etc." exit 1 fi exit 0 ``` The corresponding prescribed test at `validators.md`, lines 263-268, is: ```bash # Test a validator echo "test message" | ~/self-discipline/validators/pre-send/no-secrets.sh - # Or for validators that take arguments ~/self-discipline/validators/pre-action/confirm-delete.sh delete /opt/docker ``` A similar mismatch appears in `SKILL.md`, lines 180-196, where the security manifest says the message is read from standard input but the script evaluates `$1`. ### Technical Analysis The pre-send implementation reads the message from positional argument `$1`. The documented test instead pipes the message to standard input and passes the literal string `-` as `$1`. The script therefore scans `-`, not the piped content. This test will report success regardless of secrets in standard input, producing false assurance that the validator works. If an agent runtime also follows the pipeline convention, every message passes because the actual message is never inspected. The script additionally assumes `$1` is present while using `set -u`; invocation witho ...[truncated 997 chars]
Remediation
## Remediation Suggestions Define one unambiguous message-input contract and use it consistently. Prefer standard input for potentially large or sensitive messages: ```bash #!/usr/bin/env bash set -euo pipefail MESSAGE=$(cat) if printf '%s' "$MESSAGE" | grep -qE -- 'https?://[^[:space:]]*[?&](pass|password|token|key|secret|auth)='; then echo "❌ BLOCKED: URL contains embedded credentials" exit 1 fi exit 0 ``` Then test it using actual positive and negative cases: ```bash printf '%s' 'ordinary message' | validator.sh ! printf '%s' 'https://example.test/?token=secret' | validator.sh ``` Alternatively, if positional arguments are required, update every example and runtime integration to pass the complete message as a quoted argument. Add automated tests that verify known secret-bearing input is blocked and confirm that the tested input is the same data channel used in production.
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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (9)

Credential Access

High
Category
Privilege Escalation
Content
**This skill does NOT:**
- Make network requests
- Access credentials or secrets
- Modify files without explicit user permission
- Run validators without user approval
- Access files outside `~/self-discipline/` without asking
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Hidden Instructions

High
Category
Prompt Injection
Content
**This file is ALWAYS loaded. Rules here are enforced every session.**

<!-- Format for each rule -->
<!--
## [Rule ID] — [Short Name]
severity: critical | medium | low
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
# Incident Log

<!-- Format for each incident -->
<!--
## INC-XXX | YYYY-MM-DD | [severity]

**What happened:** [Brief description]
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
echo "test message" | ~/self-discipline/validators/pre-send/no-secrets.sh -

# Or for validators that take arguments
~/self-discipline/validators/pre-action/confirm-delete.sh delete /opt/docker
```

### 5. Version Control Validators
Confidence
80% 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).

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
- Why? → File not in session's read path
   - Why? → No reference in AGENTS.md / system prompt
   - Why? → Setup assumed it would be read
   - Why? → No verification mechanism

### 3. Verify Flow Reachability (CRITICAL)
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
| Trap | Consequence | Solution |
|------|-------------|----------|
| Writing rule in memory.md only | Future agent won't see it | Add to rules.md (always loaded) |
| "I'll remember" without verification | Same mistake in 3 sessions | Always verify flow reachability |
| Validator that modifies data | Unexpected side effects | Validators ONLY check, never modify |
| Not backing up before edits | Can't recover if wrong | ALWAYS backup before modifying |
| Skipping severity assessment | Under-responding to critical issues | Assess severity FIRST, always |
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
- Access credentials or secrets
- Modify files without explicit user permission
- Run validators without user approval
- Access files outside `~/self-discipline/` without asking

**File modifications outside ~/self-discipline/:**
- Only suggested when needed for rule visibility (e.g., AGENTS.md reference)
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.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The `auto` integration mode activates on any detected mistake, which is an overly broad trigger that can cause the discipline system to engage without clear user consent or objective boundaries. In a skill designed to enforce compliance and create validators, this can lead to excessive intervention, unintended workflow changes, and expansion of persistent rules based on minor or misclassified events.

Vague Triggers

Medium
Confidence
96% confidence
Finding
The `on-trigger` mode relies on whether the user 'seems frustrated,' which is subjective and difficult to evaluate consistently. Ambiguous behavioral triggers can be manipulated or misdetected, causing the skill to activate unexpectedly and potentially alter memory, rules, or validator behavior without a reliable signal.

Static analysis

No suspicious patterns detected.