T09 · Insecure Skill Coding Practices
- 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: MediumVulnerable 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' <<< '$(head -5 "$FILE")$(tail -5 "$FILE")'" "P16: First/last repetition"Technical Analysis
The
checkfunction 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" fiAlternatively, make
checkaccept 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" fiAdditional hardening should include:
- Quote every parameter expansion unless word splitting is explicitly required.
- Use
--before user-controlled path arguments. - Avoid
echofor arbitrary content; useprintf '%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
shellcheckin continuous integration to detect unquoted expansion and shell-parsing mistakes.
