skill-checker 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,19 +14,33 @@
14
14
  # }
15
15
  # }
16
16
 
17
- set -euo pipefail
17
+ # Fail-closed helper: any unexpected error path outputs ask + exit 0
18
+ fail_closed() {
19
+ echo "{\"permissionDecision\": \"ask\", \"additionalContext\": \"[skill-gate] $1\"}"
20
+ exit 0
21
+ }
22
+
23
+ # Trap any unexpected error to ensure we never exit without JSON output
24
+ trap 'fail_closed "Unexpected error occurred. Manual review recommended."' ERR
25
+
26
+ set -uo pipefail
27
+ # NOTE: -e is intentionally omitted; we handle errors explicitly via || fail_closed
18
28
 
19
29
  # Check jq availability - required for parsing hook JSON
20
30
  if ! command -v jq &>/dev/null; then
21
- echo '{"permissionDecision": "ask", "additionalContext": "[skill-gate] jq is required but not found. Install with: brew install jq (macOS) or apt install jq (Linux)"}'
22
- exit 0
31
+ fail_closed "jq is required but not found. Install with: brew install jq (macOS) or apt install jq (Linux)"
23
32
  fi
24
33
 
25
34
  # Read hook input from stdin
26
35
  INPUT=$(cat)
27
36
 
28
- # Extract the file path from the hook input
29
- FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // empty')
37
+ # Validate input is non-empty
38
+ if [[ -z "$INPUT" ]]; then
39
+ fail_closed "Empty input received. Manual review recommended."
40
+ fi
41
+
42
+ # Extract the file path from the hook input (fail-closed on jq parse error)
43
+ FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // empty' 2>/dev/null) || fail_closed "Failed to parse hook input JSON. Manual review recommended."
30
44
 
31
45
  # Only process SKILL.md files in skills directories
32
46
  if [[ -z "$FILE_PATH" ]] || [[ ! "$FILE_PATH" =~ SKILL\.md$ ]]; then
@@ -49,9 +63,8 @@ elif command -v npx &>/dev/null; then
49
63
  fi
50
64
 
51
65
  if [[ -z "$CHECKER" ]]; then
52
- # skill-checker not found - warn but allow
53
- echo '{"permissionDecision": "allow", "additionalContext": "[skill-gate] skill-checker not found. Install with: npm install -g skill-checker"}'
54
- exit 0
66
+ # skill-checker not found - fail-closed: ask user to review manually
67
+ fail_closed "skill-checker not found. Install with: npm install -g skill-checker. Manual review recommended."
55
68
  fi
56
69
 
57
70
  # For new file writes, we need to create a temp dir with the content
@@ -59,8 +72,8 @@ fi
59
72
  TEMP_DIR=$(mktemp -d)
60
73
  trap 'rm -rf "$TEMP_DIR"' EXIT
61
74
 
62
- # Extract file content from hook input and write to temp
63
- CONTENT=$(echo "$INPUT" | jq -r '.tool_input.content // empty')
75
+ # Extract file content from hook input and write to temp (fail-closed on jq error)
76
+ CONTENT=$(echo "$INPUT" | jq -r '.tool_input.content // empty' 2>/dev/null) || fail_closed "Failed to extract content from hook input. Manual review recommended."
64
77
  if [[ -n "$CONTENT" ]]; then
65
78
  echo "$CONTENT" > "$TEMP_DIR/SKILL.md"
66
79
  SCAN_DIR="$TEMP_DIR"
@@ -73,8 +86,7 @@ fi
73
86
  RESULT=$($CHECKER scan "$SCAN_DIR" --format hook 2>/dev/null) || RESULT=""
74
87
 
75
88
  if [[ -z "$RESULT" ]]; then
76
- echo '{"permissionDecision": "ask", "additionalContext": "[skill-gate] Scan failed or produced no results. Manual review recommended."}'
77
- exit 0
89
+ fail_closed "Scan failed or produced no results. Manual review recommended."
78
90
  fi
79
91
 
80
92
  # Output the hook response
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skill-checker",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Security checker for Claude Code skills - detect injection, malicious code, and supply chain risks before installation",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -29,7 +29,13 @@
29
29
  "lint": "tsc --noEmit",
30
30
  "prepublishOnly": "npm run lint && npm test && npm run build"
31
31
  },
32
- "keywords": ["claude-code", "skill", "security", "checker", "agent"],
32
+ "keywords": [
33
+ "claude-code",
34
+ "skill",
35
+ "security",
36
+ "checker",
37
+ "agent"
38
+ ],
33
39
  "license": "AGPL-3.0-only",
34
40
  "author": "Alexander Jin",
35
41
  "repository": {