fix: emit hook JSON with printf so a POSIX-mode shell cannot mangle it
Seven shell hooks build their JSON by interpolating a python json.dumps result and emitting it with echo. bash's echo leaves the escapes alone, so the hooks are correct when run through their own #!/bin/bash shebang. Run them with sh on macOS, where /bin/sh is bash in POSIX mode with xpg_echo set, and echo turns the escaped \n inside the string back into a real newline, producing JSON with a raw control character that every parser rejects. printf '%s\n' never interprets backslashes in its argument, so the emitted bytes are the same under every shell. Reported by @dylanpulver while rebasing #226: the macOS failure of test_copilot_shell_hooks_skip_context_when_disabled is this, not his change. Diagnosis and the one-line repro were his.
This commit is contained in:
@@ -19,7 +19,7 @@ CURRENT_PHASE=$(grep -m1 "^## Current Phase" "$PLAN_FILE" 2>/dev/null || grep -m
|
||||
if [ -n "$CURRENT_PHASE" ]; then
|
||||
PYTHON=$(command -v python3 || command -v python)
|
||||
ESCAPED=$($PYTHON -c "import sys,json; print(json.dumps(sys.stdin.read(), ensure_ascii=False))" <<< "[planning-with-files] Current: $CURRENT_PHASE" 2>/dev/null || echo "\"\"")
|
||||
echo "{\"additionalContext\":$ESCAPED}"
|
||||
printf '%s\n' "{\"additionalContext\":$ESCAPED}"
|
||||
else
|
||||
echo '{}'
|
||||
fi
|
||||
|
||||
@@ -23,7 +23,7 @@ PYTHON=$(command -v python3 || command -v python)
|
||||
if [ -n "$PYTHON" ]; then
|
||||
ESCAPED=$($PYTHON -c "import sys,json; print(json.dumps(sys.stdin.read(), ensure_ascii=False))" <<< "$CONTEXT" 2>/dev/null)
|
||||
if [ -n "$ESCAPED" ] && [ "$ESCAPED" != "\"\"" ]; then
|
||||
echo "{\"systemMessage\":$ESCAPED}"
|
||||
printf '%s\n' "{\"systemMessage\":$ESCAPED}"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -19,7 +19,7 @@ if [ -f "$SCRIPT_DIR/check-complete.sh" ]; then
|
||||
if [ -n "$RESULT" ]; then
|
||||
PYTHON=$(command -v python3 || command -v python)
|
||||
ESCAPED=$($PYTHON -c "import sys,json; print(json.dumps(sys.stdin.read(), ensure_ascii=False))" <<< "$RESULT" 2>/dev/null || echo "\"\"")
|
||||
echo "{\"systemMessage\":$ESCAPED}"
|
||||
printf '%s\n' "{\"systemMessage\":$ESCAPED}"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -24,7 +24,7 @@ fi
|
||||
|
||||
if [ -n "$CATCHUP" ]; then
|
||||
ESCAPED=$($PYTHON -c "import sys,json; print(json.dumps(sys.stdin.read(), ensure_ascii=False))" <<< "$CATCHUP" 2>/dev/null || echo "\"[planning-with-files] Session recovery data available. Read task_plan.md, progress.md, and findings.md.\"")
|
||||
echo "{\"hookSpecificOutput\":{\"additionalContext\":$ESCAPED}}"
|
||||
printf '%s\n' "{\"hookSpecificOutput\":{\"additionalContext\":$ESCAPED}}"
|
||||
else
|
||||
echo '{"hookSpecificOutput":{"additionalContext":"[planning-with-files] Active plan detected. Read task_plan.md, progress.md, and findings.md before proceeding."}}'
|
||||
fi
|
||||
|
||||
@@ -34,7 +34,7 @@ except:
|
||||
if [ -n "$ERROR_MSG" ]; then
|
||||
CONTEXT="[planning-with-files] Error detected: ${ERROR_MSG}. Log this error in task_plan.md under Errors Encountered with the attempt number and resolution."
|
||||
ESCAPED=$($PYTHON -c "import sys,json; print(json.dumps(sys.stdin.read(), ensure_ascii=False))" <<< "$CONTEXT" 2>/dev/null || echo "\"\"")
|
||||
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"ErrorOccurred\",\"additionalContext\":$ESCAPED}}"
|
||||
printf '%s\n' "{\"hookSpecificOutput\":{\"hookEventName\":\"ErrorOccurred\",\"additionalContext\":$ESCAPED}}"
|
||||
else
|
||||
echo '{}'
|
||||
fi
|
||||
|
||||
@@ -33,5 +33,5 @@ done
|
||||
[ -z "$PYTHON" ] && PYTHON=$(command -v python3 2>/dev/null || command -v python 2>/dev/null)
|
||||
ESCAPED=$(echo "$CONTEXT" | $PYTHON -c "import sys,json; print(json.dumps(sys.stdin.read(), ensure_ascii=False))" 2>/dev/null || echo "\"\"")
|
||||
|
||||
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"allow\",\"additionalContext\":$ESCAPED}}"
|
||||
printf '%s\n' "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"allow\",\"additionalContext\":$ESCAPED}}"
|
||||
exit 0
|
||||
|
||||
@@ -45,5 +45,5 @@ fi
|
||||
# Escape context for JSON
|
||||
ESCAPED=$(echo "$CONTEXT" | $PYTHON -c "import sys,json; print(json.dumps(sys.stdin.read(), ensure_ascii=False))" 2>/dev/null || echo "\"\"")
|
||||
|
||||
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"SessionStart\",\"additionalContext\":$ESCAPED}}"
|
||||
printf '%s\n' "{\"hookSpecificOutput\":{\"hookEventName\":\"SessionStart\",\"additionalContext\":$ESCAPED}}"
|
||||
exit 0
|
||||
|
||||
Reference in New Issue
Block a user