fix(ci): shell-portability-lint's sed -Ei / --in-place tokens miss operator-terminated forms - #1548
Conversation
…erator-terminated forms Closes #1545 The two GNU-only sed tokens added by #1513/#1534 (-Ei combined-cluster and --in-place long-form) only accepted a trailing whitespace-or-end-of-line boundary, so an operator-terminated form with no separating whitespace (x=$(sed -Ei), sed -Ei|cat, sed --in-place|cat, x=$(sed --in-place)) evaded detection entirely -- the same class of false negative #1537 named for sort -V / grep -P / echo -e. Widens both tokens' trailing boundary to a control operator, redirection, or subshell close ([[:space:]|&;()<>]), NOT a quote or backtick like the sibling tokens #1537/#1546 widen to: a quote immediately following -Ei with no separating whitespace is exactly the attached-EMPTY-suffix shape (-Ei'') #1513/#1534 deliberately deferred as ambiguous sed-dialect territory, so including quotes in the boundary would have silently un-deferred it. Confirmed via the isolated-token regression suite: the full sibling boundary (quotes included) breaks the existing "must not flag -Ei''" test. Verified before landing: check-shell-portability.sh --all hit sets are byte-for-byte identical before and after (75 pre-existing findings, none sed-related), so the widened boundary surfaces no new corpus violations. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Claude finished @kyle-sexton's task in 2m 57s —— View job PR Review — fix(ci): sed -Ei / --in-place operator-terminated boundary
SummaryThe fix is correct and well-reasoned. Two minor issues found; one very minor nit on a test comment. Regex analysisBoth new boundary expressions use
This is the right set. Quotes and backtick are correctly absent, preserving the Findings1. Misleading comment in test file — "or quote must still be detected"
# --- operator-terminated forms: no trailing whitespace before a control
# operator, redirection, subshell close or quote must still be detectedThe phrase "or quote must still be detected" implies quote-terminated forms are included in the detection, but the whole point of this PR's narrower boundary is that they are not — Suggested rewrite: # --- operator-terminated forms: no trailing whitespace before a control
# operator, redirection, or subshell close must still be detected2. Shipped-list test omits
f="$(tmpsh "$(printf '%s\n' \
'x=$(sed -Ei)' \
'sed -Ei|cat' \
'x=$(sed --in-place)' \
'sed --in-place|cat')")"The PR description names four forms as the bug's concrete scope, and the shipped-list check proves those four against the real token file. However, Not blocking — the isolated-token path already covers What's correct
Findings: 1 comment accuracy issue (non-blocking), 1 minor coverage gap in the shipped-list test. Core fix is sound — approve when the comment wording is addressed or acknowledged. |
|
Claude finished @kyle-sexton's task in 2m 1s —— View job Security Review — PR #1548
No security issues found. This PR makes two narrow regex-widening changes to a developer linting tool ( Pattern consumption path — The ERE patterns in ReDoS — The Bracket-expression correctness — Test script injection — The new No workflow files modified — No No secrets, credentials, or supply-chain changes — None present. |
…ed-list coverage (#1549) *This was generated by AI during work-loop execution.* No linked issue ## Summary - #1548 (`sed -Ei` / `--in-place` operator-terminated boundary fix, closing #1545) picked up two non-blocking findings from its automated post-green review before it was merged out from under this follow-up by a concurrent auto-merge (worker-tier `babysit-prs`, gate-proven `c2-mechanical`) — the fix commit landed but a second, already-written commit addressing the review findings never made it in. This PR carries that second commit forward against current `main`. - **Comment accuracy.** The operator-terminated regression-case comment said "...or quote must still be detected", which is backwards for this specific token pair: quotes are deliberately *excluded* from the `sed -Ei`/`--in-place` boundary (unlike the sibling `sort -V`/`grep -P`/ `echo -e` tokens) — that exclusion is the entire point of #1548's narrower boundary, preserving the `sed -Ei''` attached-empty-suffix deferral from #1513/#1534. Reworded and pointed at the `"sed -Ei'' must not be flagged"` test that explains why. Also corrected a stale claim in the shipped-list assertion's own comment, which likewise implied these two tokens share the sibling tokens' (quote-inclusive) boundary. - **Shipped-list test completeness.** The shipped-list assertion proved 4 of the 6 operator-terminated forms the isolated-token loops cover (missing the `;`-terminated pair for both tokens). Not a correctness gap — the isolated-token path already exercises `;` — but the shipped-list check is meant to be the exhaustive real-token-file proof, so added the two missing cases. ## Test plan - [x] `bash scripts/check-shell-portability.test.sh` — 75/75 passing (unchanged pass count; this PR only edits comments and extends one assertion's input set from 4 to 6 lines). - [x] `scripts/check-shell-portability.sh origin/main` run directly against this branch's own diff — clean (no unexcused GNU-only constructs in the 1 changed file). - [x] `shellcheck --rcfile=.shellcheckrc scripts/check-shell-portability.test.sh` — clean. - [x] `typos --config _typos.toml scripts/check-shell-portability.test.sh` — clean. ## Related - #1548 (the PR these findings were raised against, and whose second commit this one carries forward) — review comment: #1548 (comment) - #1545 (the issue #1548 closed) Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This was generated by AI during work-loop execution.
Closes #1545
Summary
sed -Ei(combined extended-regex + in-place short-flag cluster) andsed --in-place(long-form) tokens toscripts/shell-portability-tokens.txt, but both onlyaccepted a trailing whitespace-or-end-of-line boundary — the same shape fix(ci): detect sort's --version-sort / --sort=version long forms #1530's original
sort -Vshort-flag token had, and the same false negative fix(ci): shell-portability-lint's sort -V token misses operator-terminated forms #1537/fix(ci): shell-portability-lint's sort -V token misses operator-terminated forms #1546 fixed forsort -V/grep -P/echo -e: an operator-terminated form with no separating whitespace(
x=$(sed -Ei),sed -Ei|cat,sed --in-place|cat,x=$(sed --in-place)) evaded detectionentirely. Verified via repro before any fix: all four forms passed the gate clean on
main.([[:space:]|&;()<>]|$)(plus the pre-existing=alternative for--in-place=SUFFIX).sort -V/grep -P/echo -eboundary (which alsoincludes quote/backtick chars): a quote immediately following
-Eiwith no separatingwhitespace is exactly the attached-EMPTY-suffix shape (
sed -Ei'') ci: harden shell-portability-lint detection precision (sed -i spellings, portability-scope precision, awk operand edge case) #1513/fix(ci): harden shell-portability-lint detection precision #1534 explicitlydeferred as ambiguous sed-dialect territory (same as the
-i''case). Confirmed empirically —copying the sibling tokens' full quote-inclusive boundary verbatim broke the existing
"sed -Ei'' must not be flagged"regression test, since a bare quote character then satisfiedthe widened boundary at the
i+'junction. Excluding quotes/backtick from this pair'sboundary keeps that deferred case correctly unflagged while still catching every
operator-terminated form the issue named (none of which need a quote as the terminator).
check-shell-portability.sh --allagainst the corpus before and after the token edit: the hit sets are byte-for-byte identical
(75 pre-existing findings, none
sed-related), so the widened boundary surfaces no new corpusviolations and needs no
portability-ok:annotations.Test plan
bash scripts/check-shell-portability.test.sh— 75/75 passing (6 new regression cases: 3operator-terminated forms each for
sed -Eiandsed --in-placeat the isolated-tokenlevel, plus one shipped-list assertion proving all 4 forms are detected under the real
shell-portability-tokens.txt).bash scripts/check-shell-portability.sh --paths t.shagainst a file containing the fouroperator-terminated forms passed clean on
main's shipped list); after the fix, all fourare flagged.
tried first and demonstrably broke the pre-existing
sed -Ei''deferred-ambiguous-suffixtest (
PASS=74 FAIL=1); narrowed to exclude quotes/backtick, re-ran —PASS=75 FAIL=0.scripts/check-shell-portability.sh --all— before/after hit sets identical (75 findings,unrelated to these tokens); see summary above.
scripts/check-shell-portability.sh origin/mainrun directly against this branch's owndiff — clean (no unexcused GNU-only constructs in the 2 changed files).
shellcheck --rcfile=.shellcheckrc scripts/check-shell-portability.test.sh— clean.typos --config _typos.tomlon both changed files — clean.Related
sed -Ei/sed --in-placeas the deferred-out sibling defect this PR fixes)deferral this PR's narrower boundary deliberately preserves)