Skip to content

fix: Windows/Git Bash compatibility (jq 1.7+ and CRLF)#3

Open
elquer wants to merge 1 commit intooryband:masterfrom
elquer:fix/windows-jq-shfmt-compat
Open

fix: Windows/Git Bash compatibility (jq 1.7+ and CRLF)#3
elquer wants to merge 1 commit intooryband:masterfrom
elquer:fix/windows-jq-shfmt-compat

Conversation

@elquer
Copy link
Copy Markdown

@elquer elquer commented Mar 28, 2026

Summary

Two fixes for running on Windows with Git Bash:

1. jq 1.7+ string interpolation conflict

jq >= 1.7 treats \( inside strings as string interpolation, which breaks the regex patterns in sub() calls used to extract permission prefixes.

Before: sub("^Bash\("; "") → jq 1.7+ sees \( as interpolation start → syntax error
After: sub("^Bash[(]"; "") → character class [(] is compatible with all jq versions

2. CRLF line endings from Windows tools

shfmt and jq on Windows output \r\n (CRLF) line endings. The trailing \r gets appended to extracted command strings and prefixes, causing prefix matching to silently fail (e.g., "find\r" never matches "find").

Fix: Added tr -d '\r' to strip carriage returns from jq/shfmt output pipelines.

Test plan

  • Tested on Windows 11 with Git Bash, jq 1.8.1, shfmt 3.13.0
  • Simple commands: php -l file.php → approved
  • Compound commands: find /path | head -20 → approved
  • Chained commands: cd /path && grep pattern | wc -l → approved
  • Unknown commands: rm -rf / → falls through to prompt
  • Verify no regression on macOS/Linux (the [(] syntax and tr -d '\r' are no-ops on systems without \r)

Two issues when running on Windows with Git Bash:

1. jq 1.7+ treats \( inside strings as string interpolation,
   breaking the regex in sub() calls. Replaced \( with [(]
   character class syntax which is compatible with all jq versions.

2. shfmt and jq on Windows output CRLF line endings, causing
   \r to be appended to extracted command strings and prefixes,
   which breaks prefix matching. Added tr -d '\r' to strip
   carriage returns from jq/shfmt output.

Tested on Windows 11 with Git Bash, jq 1.8.1, shfmt 3.13.0.
Copilot AI review requested due to automatic review settings March 28, 2026 02:55
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Improves approve-compound-bash.sh compatibility when running on Windows via Git Bash by avoiding jq 1.7+ string interpolation parsing issues in regex patterns and by stripping CRLF carriage returns that can break prefix matching.

Changes:

  • Update jq sub() regexes to avoid jq 1.7+ \( string interpolation conflicts.
  • Strip \r from jq/shfmt output in key pipelines to prevent CRLF-related matching failures.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread approve-compound-bash.sh
Comment on lines 353 to +355
while IFS= read -r line; do
[[ -n "$line" ]] && allowed_prefixes+=("$line")
done < <(jq -r '.[] | sub("^Bash\\("; "") | sub("( \\*|\\*|:\\*)\\)$"; "") | sub("\\)$"; "")' <<< "$permissions_json" 2>/dev/null)
done < <(jq -r '.[] | sub("^Bash[(]"; "") | sub("( [*]|[*]|:[*])[)]$"; "") | sub("[)]$"; "")' <<< "$permissions_json" 2>/dev/null)
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The --permissions parsing path still reads raw jq -r output directly into allowed_prefixes without stripping \r. On Windows jq may emit CRLF, leaving a trailing carriage return in each prefix (e.g., "ls\r") and causing prefix matching to fail. Pipe this process substitution through tr -d '\r' (or strip \r from line before appending).

Copilot uses AI. Check for mistakes.
Comment thread approve-compound-bash.sh
while IFS= read -r line; do
[[ -n "$line" ]] && denied_prefixes+=("$line")
done < <(jq -r '.[] | sub("^Bash\\("; "") | sub("( \\*|\\*|:\\*)\\)$"; "") | sub("\\)$"; "")' <<< "$deny_json" 2>/dev/null)
done < <(jq -r '.[] | sub("^Bash[(]"; "") | sub("( [*]|[*]|:[*])[)]$"; "") | sub("[)]$"; "")' <<< "$deny_json" 2>/dev/null)
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same CRLF issue as the allow list: the --deny parsing path appends jq -r output directly into denied_prefixes without removing \r, which can break deny matching on Windows Git Bash. Consider adding | tr -d '\r' to this process substitution as well.

Suggested change
done < <(jq -r '.[] | sub("^Bash[(]"; "") | sub("( [*]|[*]|:[*])[)]$"; "") | sub("[)]$"; "")' <<< "$deny_json" 2>/dev/null)
done < <(jq -r '.[] | sub("^Bash[(]"; "") | sub("( [*]|[*]|:[*])[)]$"; "") | sub("[)]$"; "")' <<< "$deny_json" 2>/dev/null | tr -d '\r')

Copilot uses AI. Check for mistakes.
Comment thread approve-compound-bash.sh
Comment on lines 200 to 202
local raw_commands
raw_commands=$(jq -r "$SHFMT_AST_FILTER" <<< "$ast" 2>/dev/null) || return 1
raw_commands=$(jq -r "$SHFMT_AST_FILTER" <<< "$ast" 2>/dev/null | tr -d '\r') || return 1

Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new CRLF-stripping behavior (tr -d '\r') is not covered by tests. Since this repo uses BATS tests for permissions/parsing, consider adding a test that feeds permissions containing an embedded carriage return (e.g., a JSON string with \r) and asserts it still matches, to prevent regressions in Windows/Git Bash environments.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants