Back to skill

Security audit

Prompt Hardening

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed prompt-hardening advisory skill with a flawed local audit script, but no evidence of hidden execution, persistence, credential access, exfiltration, or destructive behavior.

Install only if you want a mostly Chinese/bilingual prompt-hardening guide. Treat its recommendations as advisory, apply rewritten prompt changes manually, and avoid running scripts/audit.sh on untrusted prompt files until the shell-check logic is fixed.

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/audit.sh:7
Finding

Unsafe Dynamic Condition Execution Produces Unreliable Results and Argument Injection

Content
View full analysis

Vulnerability Details

File Location: scripts/audit.sh, lines 7-25
Vulnerability Type: Unsafe shell expansion and argument injection
Risk Level: Medium

Vulnerable Code

bash
check() { if $1; then echo "  ✅ $2"; PASS=$((PASS+1)); else echo "  ❌ $2"; fi; }
echo "=== Prompt Hardening Audit: $(basename "$FILE") ==="
check "[[ '$LOWER' == *'must'* || '$LOWER' == *'never'* ]]" "P1: MUST/NEVER keywords"
check "[[ '$LOWER' == *'not '* || '$LOWER' == *'not)'* ]]" "P2: Use X (NOT Y) pattern"
check "[[ '$LOWER' == *'❌'* || '$LOWER' == *'禁止'* ]]" "P3: Exhaustive negative list"
check "[[ '$LOWER' == *'当'* || '$LOWER' == *'when'* ]]" "P4: Conditional triggers"
check "[[ '$LOWER' == *'如果你发现自己'* || '$LOWER' == *'reframing'* ]]" "P5: Anti-reasoning block"
check "[[ '$LOWER' == *'优先级'* || '$LOWER' == *'priority'* ]]" "P6: Priority hierarchy"
check "[[ '$CONTENT' == *'good-example'* || '$CONTENT' == *'<example>'* ]]" "P7: Good/bad examples"
check "[[ '$LOWER' == *'不需要'* || '$LOWER' == *'not your'* ]]" "P8: Scope limits"
check "[[ '$LOWER' == *'reminder'* || '$LOWER' == *'提醒'* ]]" "P9: Drift protection"
check "[[ '$LOWER' == *'信任'* || '$LOWER' == *'trust'* ]]" "P10: Trust boundary"
check "[[ '$LOWER' == *'确认'* || '$LOWER' == *'verify'* || '$LOWER' == *'check'* ]]" "P11: Echo-check"
check "[[ $(echo "$CONTENT" | wc -l) -gt 30 ]]" "P12: Constraint > task ratio"
check "[[ '$LOWER' == *'hook'* || '$LOWER' == *'plugin'* || '$LOWER' == *'guard'* ]]" "P13: Code-level backup"
check "[[ '$LOWER' == *'前置条件'* || '$LOWER' == *'precondition'* || '$LOWER' == *'gate'* ]]" "P14: State machine gate"
check "[[ '$LOWER' == *'我刚才'* || '$LOWER' == *'self-correct'* ]]" "P15: Self-correction template"
check "grep -q 'MUST\|NEVER\|CRITICAL' &lt;&lt;&lt; '$(head -5 "$FILE")$(tail -5 "$FILE")'" "P16: First/last repetition"

Technical Analysis

The check function accepts a shell condition as a string and attempts to execute ...[truncated 2931 chars]

Remediation
View remediation

Remediation Suggestions

Do not pass shell expressions as strings or execute conditions through unquoted parameter expansion. Implement each condition directly in Bash syntax and pass only its evaluated status to a reporting function.

For example:

bash
pass() {
    printf '  ✅ %s\n' "$1"
    PASS=$((PASS + 1))
}

fail() {
    printf '  ❌ %s\n' "$1"
}

if [[ "$LOWER" == *must* || "$LOWER" == *never* ]]; then
    pass "P1: MUST/NEVER keywords"
else
    fail "P1: MUST/NEVER keywords"
fi

Alternatively, make check accept an already evaluated exit status:

bash
check() {
    local status=$1
    local description=$2

    if (( status == 0 )); then
        printf '  ✅ %s\n' "$description"
        PASS=$((PASS + 1))
    else
        printf '  ❌ %s\n' "$description"
    fi
}

[[ "$LOWER" == *must* || "$LOWER" == *never* ]]
check "$?" "P1: MUST/NEVER keywords"

P16 should inspect the file through a pipeline or a temporary variable without embedding its content into a command:

bash
if {
    head -n 5 -- "$FILE"
    tail -n 5 -- "$FILE"
} | grep -qE -- 'MUST|NEVER|CRITICAL'; then
    pass "P16: First/last repetition"
else
    fail "P16: First/last repetition"
fi

Additional hardening should include:

  • Quote every parameter expansion unless word splitting is explicitly required.
  • Use -- before user-controlled path arguments.
  • Avoid echo for arbitrary content; use printf '%s'.
  • Add tests covering spaces, newlines, quotes, glob characters, leading hyphens, shell metacharacters, and path-like tokens in prompt files.
  • Expand the current smoke test so it validates all 16 checks and confirms that crafted prompt content cannot become command arguments.
  • Run shellcheck in continuous integration to detect unquoted expansion and shell-parsing mistakes.
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (8)

Tp2

High
Category
MCP Tool Poisoning
Confidence
85% confidence
Finding

Mixing characters from multiple Unicode scripts in a single identifier is a common technique to create visually ambiguous tool names.

Content

No source excerpt is available for this finding.

Tp2

High
Category
MCP Tool Poisoning
Confidence
85% confidence
Finding

Mixing characters from multiple Unicode scripts in a single identifier is a common technique to create visually ambiguous tool names.

Content

No source excerpt is available for this finding.

Tp2

High
Category
MCP Tool Poisoning
Confidence
85% confidence
Finding

Mixing characters from multiple Unicode scripts in a single identifier is a common technique to create visually ambiguous tool names.

Content

No source excerpt is available for this finding.

Tp2

High
Category
MCP Tool Poisoning
Confidence
85% confidence
Finding

Mixing characters from multiple Unicode scripts in a single identifier is a common technique to create visually ambiguous tool names.

Content

No source excerpt is available for this finding.

Skill Enumeration

Medium
Category
Agent Snooping
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.

Content

Scanner excerpt · README.md (reported line 12)May include surrounding context.

~/.openclaw/skills/prompt-hardening/scripts/audit.sh ~/path/to/SOUL.md

Apply hardening (read SKILL.md for the 16 patterns)

cat ~/.openclaw/skills/prompt-hardening/SKILL.md

text

## When to Use

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trigger list contains broad phrases such as 'prompt 优化', 'instruction following', and 'rule enforcement' that can match ordinary support or writing requests, causing this skill to activate outside its intended scope. In a prompt-hardening skill, accidental invocation is more dangerous because it can steer the agent toward rewriting prompts and strengthening behavioral constraints in contexts where a different, safer, or more task-specific skill should be used.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The document is written entirely in Chinese and presents all operational patterns, examples, and required responses in that language, including prescribed agent replies such as '已通过 dispatch.sh 派发到 nc-review-2251'. There is no indication that language selection is optional or limited to a justified region-specific context, so this creates a natural-language locale policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This code embeds Chinese terms alongside English ones in multiple audit checks, effectively imposing language-specific policy expectations on prompt files. Because the script does not explain that it is intentionally bilingual or limited to a particular locale, it may violate the requirement not to force a specific language or locale without user opt-in.

Content

No source excerpt is available for this finding.