T09 · Insecure Skill Coding Practices
- Location
scripts/opsec-scan.sh:34- Finding
External OPSEC Scanner Failures Are Incorrectly Treated as Clean Results
- Content
View full analysis
Vulnerability Details
File Location:
scripts/opsec-scan.sh:34-49
Vulnerability Type: Fail-open security validation caused by incorrect exit-status handling
Risk Level: HighVulnerable Code
bash SCANNER_OUTPUT=$(python3 "$PYTHON_SCANNER" "$SKILL_DIR" 2>&1 || true) SCANNER_EXIT=$? # Fall back if the scanner doesn't recognize the directory type if echo "$SCANNER_OUTPUT" | grep -q "Unknown job type\|Valid types:"; then echo " (refactory scanner does not support raw skill dirs — using fallback)" echo "" elif [[ "$SCANNER_EXIT" -eq 0 ]]; then echo "$SCANNER_OUTPUT" echo "" echo "✅ CLEAN — refactory scanner found no violations" exit 0 else echo "$SCANNER_OUTPUT" echo "" echo "❌ BLOCKED — refactory scanner found violations (see above)" exit 1 fiTechnical Analysis
The command substitution appends
|| trueto the Python scanner invocation. Therefore, the compound command's exit status is always zero, regardless of whether the scanner:- Detects a security violation and exits nonzero.
- Crashes because of malformed input.
- Encounters a runtime or dependency error.
- Cannot read one or more files.
- Terminates unexpectedly for any other reason.
SCANNER_EXIT=$?consequently records the status oftrue, not the original Python process. Unless the scanner's text output contains one of the two recognized unsupported-type strings, the subsequentSCANNER_EXIT == 0branch declares the directory clean and exits successfully.This is a fail-open defect in a mandatory pre-publication security control.
Attack Path
- An attacker or accidental release process places sensitive content in a skill release directory.
- The configured external Python scanner detects that content and exits with a nonzero status, or it fails while processing crafted input.
- The
|| trueexpression suppresses that nonzero status. SCANNER_EXITis assigned0.- The script prints
CLEANand exits with status zero. - The rele ...[truncated 781 chars]
- Remediation
View remediation
Remediation Suggestions
Capture the scanner's real exit status without allowing
set -eto terminate the wrapper:bash set +e SCANNER_OUTPUT=$(python3 "$PYTHON_SCANNER" "$SKILL_DIR" 2>&1) SCANNER_EXIT=$? set -eThen use explicit, fail-closed handling:
bash if echo "$SCANNER_OUTPUT" | grep -qE 'Unknown job type|Valid types:'; then echo "Scanner does not support raw skill directories; using fallback." elif [[ "$SCANNER_EXIT" -eq 0 ]]; then echo "$SCANNER_OUTPUT" echo "CLEAN" exit 0 else echo "$SCANNER_OUTPUT" >&2 echo "BLOCKED — scanner reported violations or failed." >&2 exit 1 fiAdditional hardening should include:
- Distinguish a documented “unsupported input” exit code from detected violations and internal scanner errors rather than relying only on output text.
- Treat unknown exit codes, empty output, timeouts, and unreadable files as blocking failures.
- Run the fallback scanner only when the primary scanner explicitly reports unsupported input—not after arbitrary failures.
- Add automated tests for:
- Exit status zero with clean output.
- Nonzero status for detected violations.
- Nonzero status caused by runtime failure.
- Unsupported-directory behavior.
- Malformed or adversarial scanner output.
- Verify that the wrapper's final exit status is nonzero for every failure case.
