fix: address review findings for escalation race condition, SQL injection, and sc_codes scope

- Race condition: mv escalations.jsonl to a PID-stamped snapshot before
  processing so concurrent dev-poll appends go to a fresh file; rm snapshot
  after loop — no entries are ever silently dropped
- SQL injection: validate ESC_PR_SHA is a 40-char hex string before
  interpolating into the wpdb query
- sc_codes scope: compute per-file from file_errors (already filtered to
  that file) instead of the entire step log; also switch grep to -F so
  dots in filenames are not treated as regex wildcards
- step_pid validation: reject non-integer values from Woodpecker API before
  passing as CLI argument
- Fallback body now distinguishes "CI logs unavailable" from "logs found
  but issue creation API calls failed"
- ESC_GENERIC_FAIL: avoid leading blank line by using conditional separator
  and fix code-block opening newline
- is_escalated(): remove dead esc_file/done_file locals; add Python-level
  int() guard so empty/non-numeric issue or pr values fail cleanly instead
  of producing a syntax error suppressed by 2>/dev/null

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
openhands 2026-03-17 15:11:53 +00:00
parent d9520f48a6
commit 13bc948b1d
2 changed files with 48 additions and 15 deletions

View file

@ -60,10 +60,12 @@ json.dump(d,open(f,'w'))
# Check whether an issue/PR has been escalated to supervisor (unprocessed or processed)
is_escalated() {
local issue="$1" pr="$2"
local esc_file="${FACTORY_ROOT}/supervisor/escalations.jsonl"
local done_file="${FACTORY_ROOT}/supervisor/escalations.done.jsonl"
python3 -c "
import json, sys
try:
issue, pr = int('${issue}'), int('${pr}')
except (ValueError, TypeError):
sys.exit(1)
for path in ['${FACTORY_ROOT}/supervisor/escalations.jsonl',
'${FACTORY_ROOT}/supervisor/escalations.done.jsonl']:
try:
@ -73,7 +75,7 @@ for path in ['${FACTORY_ROOT}/supervisor/escalations.jsonl',
if not line:
continue
d = json.loads(line)
if d.get('issue') == ${issue} and d.get('pr') == ${pr}:
if d.get('issue') == issue and d.get('pr') == pr:
sys.exit(0)
except OSError:
pass