Skip to content

Commit 3c475db

Browse files
GHGuideclaude
andcommitted
fix: recognize a safe file read whose path the CLI wrapped across lines
Claude Code hard-wraps a long path inside its permission dialog, so the line-based Read(...) match missed it entirely and the dialog fell through to the whole-screen critical scan — parking a lane over its own runner-armed kit again (live c44, 2026-08-19, three lanes). approval_is_safe_read now flattens the capture before matching and un-wraps the injected spaces; a wrapped secret path (…/.ssh/id_r sa) is still refused after un-wrapping. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent c989d7c commit 3c475db

2 files changed

Lines changed: 27 additions & 2 deletions

File tree

bin/polylane-run.sh

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3208,10 +3208,17 @@ startup_check() {
32083208
# and parked for an hour (live 2026-08-18). Secrets are judged on the Read(...)
32093209
# target line only — surrounding prompt text must not decide.
32103210
approval_is_safe_read() {
3211-
local txt="$1" target
3211+
local txt="$1" target flat
32123212
printf '%s' "$txt" | grep -qE 'Read file|Read\(' || return 1
3213-
target=$(printf '%s' "$txt" | grep -oE 'Read\([^)]*\)' | tail -1)
3213+
# The CLI hard-wraps a long path across pane lines, so a line-based match
3214+
# misses `Read(` … `)` entirely and the dialog falls through to the
3215+
# whole-screen critical scan (live 2026-08-19: a lane's own kit path wrapped
3216+
# and the lane parked). Flatten first, then match.
3217+
flat=$(printf '%s' "$txt" | tr '\n' ' ' | tr -s ' ')
3218+
target=$(printf '%s' "$flat" | grep -oE 'Read\([^)]*\)' | tail -1)
32143219
[ -n "$target" ] || return 1
3220+
# Un-wrap: the CLI breaks a path anywhere, so remove the spaces it injected.
3221+
target=$(printf '%s' "$target" | tr -d ' ')
32153222
printf '%s' "$target" | grep -qiE '\.ssh|\.env|\.aws|credential|keychain|secret|password|api[_-]?key|token|\.pem|id_rsa' && return 1
32163223
return 0
32173224
}

tests/test-auth-park.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,24 @@ NOISE_TXT=' … prompt tail mentions api_key and token handling …
118118
❯ 1. Yes'
119119
assert_ok "screen-noise-does-not-block-read" approval_is_safe_read "$NOISE_TXT"
120120

121+
# a wrapped path (the CLI breaks long paths across pane lines) is still a read
122+
WRAP_TXT=' Read file
123+
Read(/Users/x/.codex/plugins/cache/claude-plugins-official/superpowers/6.3.0/skills/test-driven-development/SKILL
124+
.md)
125+
Do you want to proceed?
126+
❯ 1. Yes
127+
2. Yes, allow reading from test-driven-development/ during this session
128+
3. No'
129+
assert_ok "wrapped-kit-read-is-safe" approval_is_safe_read "$WRAP_TXT"
130+
131+
# …and a wrapped SECRET path must still be refused after un-wrapping
132+
WRAP_SECRET=' Read file
133+
Read(/Users/x/.ssh/id_r
134+
sa)
135+
Do you want to proceed?
136+
❯ 1. Yes'
137+
assert_fail "wrapped-secret-read-not-safe" approval_is_safe_read "$WRAP_SECRET"
138+
121139
# --- an answered dialog unparks the lane in health_check -----------------------
122140
NEEDS_DECISION_LANES="a"
123141
pane_awaiting_approval() { return 1; } # dialog gone

0 commit comments

Comments
 (0)