From 02daa912713cbeda0ab01f7df61408131a9e80d4 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 13 Dec 2025 11:11:35 +0000 Subject: [PATCH] fix(security): use jq for safe JSON output in example hooks Example hook scripts were using shell string concatenation to embed variables in JSON output, which could cause malformed JSON if the variable contained special characters like quotes or backslashes. Changed: - validate-write.sh: Use jq --arg for file_path in error messages - read-settings-hook.sh: Use jq --arg for MAX_SIZE in error message Before: echo '{"systemMessage": "Path: '"$file_path"'"}' >&2 After: jq -n --arg path "$file_path" \ '{"systemMessage": "Path: \($path)"}' >&2 This ensures proper JSON escaping regardless of the variable content. --- .../skills/hook-development/examples/validate-write.sh | 9 ++++++--- .../plugin-settings/examples/read-settings-hook.sh | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/plugins/plugin-dev/skills/hook-development/examples/validate-write.sh b/plugins/plugin-dev/skills/hook-development/examples/validate-write.sh index e665193..c4dde41 100755 --- a/plugins/plugin-dev/skills/hook-development/examples/validate-write.sh +++ b/plugins/plugin-dev/skills/hook-development/examples/validate-write.sh @@ -18,19 +18,22 @@ fi # Check for path traversal if [[ "$file_path" == *".."* ]]; then - echo '{"hookSpecificOutput": {"permissionDecision": "deny"}, "systemMessage": "Path traversal detected in: '"$file_path"'"}' >&2 + jq -n --arg path "$file_path" \ + '{"hookSpecificOutput": {"permissionDecision": "deny"}, "systemMessage": "Path traversal detected in: \($path)"}' >&2 exit 2 fi # Check for system directories if [[ "$file_path" == /etc/* ]] || [[ "$file_path" == /sys/* ]] || [[ "$file_path" == /usr/* ]]; then - echo '{"hookSpecificOutput": {"permissionDecision": "deny"}, "systemMessage": "Cannot write to system directory: '"$file_path"'"}' >&2 + jq -n --arg path "$file_path" \ + '{"hookSpecificOutput": {"permissionDecision": "deny"}, "systemMessage": "Cannot write to system directory: \($path)"}' >&2 exit 2 fi # Check for sensitive files if [[ "$file_path" == *.env ]] || [[ "$file_path" == *secret* ]] || [[ "$file_path" == *credentials* ]]; then - echo '{"hookSpecificOutput": {"permissionDecision": "ask"}, "systemMessage": "Writing to potentially sensitive file: '"$file_path"'"}' >&2 + jq -n --arg path "$file_path" \ + '{"hookSpecificOutput": {"permissionDecision": "ask"}, "systemMessage": "Writing to potentially sensitive file: \($path)"}' >&2 exit 2 fi diff --git a/plugins/plugin-dev/skills/plugin-settings/examples/read-settings-hook.sh b/plugins/plugin-dev/skills/plugin-settings/examples/read-settings-hook.sh index 8f84ed6..e1b8220 100755 --- a/plugins/plugin-dev/skills/plugin-settings/examples/read-settings-hook.sh +++ b/plugins/plugin-dev/skills/plugin-settings/examples/read-settings-hook.sh @@ -56,7 +56,8 @@ if [[ -n "$MAX_SIZE" ]] && [[ "$MAX_SIZE" =~ ^[0-9]+$ ]]; then content_size=${#content} if [[ $content_size -gt $MAX_SIZE ]]; then - echo '{"hookSpecificOutput": {"permissionDecision": "deny"}, "systemMessage": "File exceeds configured max size: '"$MAX_SIZE"' bytes"}' >&2 + jq -n --arg size "$MAX_SIZE" \ + '{"hookSpecificOutput": {"permissionDecision": "deny"}, "systemMessage": "File exceeds configured max size: \($size) bytes"}' >&2 exit 2 fi fi