Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .github/scripts/autofix-push-and-report.sh
Original file line number Diff line number Diff line change
Expand Up @@ -324,8 +324,9 @@ run_deferred_upsert() {
if [[ "${UPSERT_OUT}" != *'__upsert_child_live__'* ]]; then
echo "::warning::deferred-findings upsert child never started (loader trace mode or exec failure); NOT persisted this round"
fi
# The child's output is agent-reachable content, so a line-start
# `::` is neutralized before it reaches this step's stdout.
# The child's output is agent-reachable content, so both workflow-command
# syntaxes are neutralized before it reaches this step's stdout (`##[`
# parses mid-line too — #9761).
while IFS= read -r _upsert_line; do
# Wrapper-authored lines carry a marker and are emitted
# VERBATIM so they still render as GitHub annotations; the
Expand All @@ -335,7 +336,7 @@ run_deferred_upsert() {
elif [[ "${_upsert_line}" == __upsert_trusted__* ]]; then
printf '%s\n' "${_upsert_line#__upsert_trusted__}"
else
printf '%s\n' "${_upsert_line//::/;;}"
printf '%s\n' "${_upsert_line//::/;;}" | sed 's/##\[/##[/g'
Comment thread
wenshao marked this conversation as resolved.
Outdated
fi
done <<< "${UPSERT_OUT}"
}
Expand Down
24 changes: 15 additions & 9 deletions .github/scripts/run-autofix-review-verification.sh
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,10 @@ fi
if [[ -f "${WORKDIR}/failure.md" && -n "$(git status --porcelain)" ]]; then
echo "❌ Agent wrote failure.md after leaving a dirty workspace:"
git status --short
cat "${WORKDIR}/failure.md"
# Agent-written content on step stdout: both workflow-command syntaxes
# parse here (`##[` mid-line too — measured on #9761). Same reason
# 'Show run artifacts' neutralizes these files.
sed -e 's/::/;;/g' -e 's/##\[/##[/g' "${WORKDIR}/failure.md"
Comment thread
wenshao marked this conversation as resolved.
echo "outcome=failed" >> "${GITHUB_OUTPUT}"
echo "kiss_audit=${KISS_AUDIT:-false}" >> "${GITHUB_OUTPUT}"
if [[ "${AUDIT_VERDICT_RECORDED:-false}" == 'true' ]]; then
Expand All @@ -247,7 +250,7 @@ fi

if [[ -f "${WORKDIR}/failure.md" ]]; then
echo "🛑 Agent aborted intentionally:"
cat "${WORKDIR}/failure.md"
sed -e 's/::/;;/g' -e 's/##\[/##[/g' "${WORKDIR}/failure.md"
echo "outcome=failed" >> "${GITHUB_OUTPUT}"
echo "kiss_audit=${KISS_AUDIT:-false}" >> "${GITHUB_OUTPUT}"
if [[ "${AUDIT_VERDICT_RECORDED:-false}" == 'true' ]]; then
Expand Down Expand Up @@ -277,7 +280,7 @@ if [[ -s "${WORKDIR}/handoff.md" && -n "$(git status --porcelain)" \
&& "${AUDIT_VERDICT:-}" != 'conflict' ]]; then
echo "❌ Agent wrote handoff.md after leaving a dirty workspace:"
git status --short
sed 's/::/;;/g' "${WORKDIR}/handoff.md"
sed -e 's/::/;;/g' -e 's/##\[/##[/g' "${WORKDIR}/handoff.md"
echo "outcome=dirty_handoff" >> "${GITHUB_OUTPUT}"
echo "kiss_audit=${KISS_AUDIT:-false}" >> "${GITHUB_OUTPUT}"
if [[ "${AUDIT_VERDICT_RECORDED:-false}" == 'true' ]]; then
Expand All @@ -299,7 +302,7 @@ if [[ -s "${WORKDIR}/handoff.md" && "${committed_rc:-0}" -eq 1 \
&& "${AUDIT_VERDICT:-}" != 'conflict' ]]; then
echo "❌ Agent wrote handoff.md but the round HAS a commit — a brake violation:"
git log --oneline "origin/${BRANCH}..${BRANCH}"
sed 's/::/;;/g' "${WORKDIR}/handoff.md"
sed -e 's/::/;;/g' -e 's/##\[/##[/g' "${WORKDIR}/handoff.md"
echo "outcome=committed_handoff" >> "${GITHUB_OUTPUT}"
echo "kiss_audit=${KISS_AUDIT:-false}" >> "${GITHUB_OUTPUT}"
if [[ "${AUDIT_VERDICT_RECORDED:-false}" == 'true' ]]; then
Expand All @@ -321,10 +324,11 @@ if git diff --quiet "origin/${BRANCH}...${BRANCH}" \
&& [[ -s "${WORKDIR}/handoff.md" ]] \
&& [[ "${AUDIT_VERDICT:-}" != 'conflict' ]]; then
echo "🤝 Branch unchanged with a handoff — the agent stopped under instruction and deferred this item to a human:"
# Agent-written content: a line-start `::` would be parsed as a workflow
# command (::error::, ::add-mask::), the same reason 'Show run artifacts'
# neutralizes these files.
sed 's/::/;;/g' "${WORKDIR}/handoff.md"
# Agent-written content: both workflow-command syntaxes parse on step
# stdout — a line-start `::` (::error::, ::add-mask::) AND `##[` even
# mid-line (a quoted `##[add-matcher]` fails the step; measured on
#9761). The same reason 'Show run artifacts' neutralizes these files.
sed -e 's/::/;;/g' -e 's/##\[/##[/g' "${WORKDIR}/handoff.md"
echo "outcome=handoff" >> "${GITHUB_OUTPUT}"
echo "kiss_audit=${KISS_AUDIT:-false}" >> "${GITHUB_OUTPUT}"
if [[ "${AUDIT_VERDICT_RECORDED:-false}" == 'true' ]]; then
Expand Down Expand Up @@ -586,7 +590,9 @@ if git diff --quiet "origin/${BRANCH}...${BRANCH}"; then
# no-commit handoff was classified before the structural checks above.
if [[ -s "${WORKDIR}/no-action.md" ]]; then
echo "🟰 No action needed:"
cat "${WORKDIR}/no-action.md"
# Both command syntaxes, like every other echo of agent-written files
# (`##[` parses mid-line too — #9761).
sed -e 's/::/;;/g' -e 's/##\[/##[/g' "${WORKDIR}/no-action.md"
echo "verified_head=$(git rev-parse HEAD)" >> "${GITHUB_OUTPUT}"
echo "outcome=noop" >> "${GITHUB_OUTPUT}"
echo "kiss_audit=${KISS_AUDIT:-false}" >> "${GITHUB_OUTPUT}"
Expand Down
16 changes: 9 additions & 7 deletions .github/scripts/upsert-deferred-issue.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,10 @@ gh_reason() {
local r=''
[[ -n "${GH_ERR}" && -s "${GH_ERR}" ]] &&
r="$(tr '\r\n\t' ' ' < "${GH_ERR}" | head -c 200)"
# `::` neutralized like every other agent/API-derived echo: an API error
# body is not trusted to be free of workflow-command syntax.
r="$(printf '%s' "${r}" | sed 's/::/;;/g')"
# Both workflow-command syntaxes neutralized like every other
# agent/API-derived echo: an API error body is not trusted to be free of
# them (`##[` parses mid-line too — #9761).
r="$(printf '%s' "${r}" | sed -e 's/::/;;/g' -e 's/##\[/##[/g')"
[[ -n "${r// /}" ]] && printf '%s' "${r}" || printf 'no stderr captured'
}
gh_err_reset() { [[ -n "${GH_ERR}" ]] && : > "${GH_ERR}"; }
Expand All @@ -67,9 +68,10 @@ OWN_FINDINGS="${WORKDIR}/deferred-findings.json"
# filters this round's feedback out of every later round, and the next run's
# workspace reset deletes the file — nothing re-derives them. So each abort
# says so and dumps what it had, for manual recovery from the run log.
# `::` is neutralized in the dump: the content is agent-influenced and a
# raw `::` at line start would be parsed as a workflow command (same reason
# `<!--` is neutralized at every publish site).
# Both workflow-command syntaxes are neutralized in the dump: the content is
# agent-influenced and would otherwise be parsed as a command — `::` at line
# start AND `##[` even mid-line (measured on #9761). Same reason `<!--` is
# neutralized at every publish site.
dump_file() {
[[ -s "$1" ]] || return 0
local size
Expand All @@ -85,7 +87,7 @@ dump_file() {
else
echo "--- $1"
fi
head -c 4000 "$1" | sed 's/::/;;/g'
head -c 4000 "$1" | sed -e 's/::/;;/g' -e 's/##\[/##[/g'
echo
}
lost() {
Expand Down
47 changes: 33 additions & 14 deletions .github/workflows/qwen-autofix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1318,13 +1318,15 @@ jobs:
if [[ -f "${WORKDIR}/failure.md" && -n "$(git status --porcelain)" ]]; then
echo "❌ Agent wrote failure.md after leaving a dirty workspace:"
git status --short
cat "${WORKDIR}/failure.md"
# Agent-written content on step stdout: neutralize both command
# syntaxes (`##[` parses mid-line too — #9761).
sed -e 's/::/;;/g' -e 's/##\[/##[/g' "${WORKDIR}/failure.md"
exit 1
fi

if [[ -f "${WORKDIR}/failure.md" ]]; then
echo "🛑 Agent aborted intentionally:"
cat "${WORKDIR}/failure.md"
sed -e 's/::/;;/g' -e 's/##\[/##[/g' "${WORKDIR}/failure.md"
exit 1
fi

Expand Down Expand Up @@ -1395,12 +1397,14 @@ jobs:
for f in decision.json pr-title.txt pr-body.md e2e-report.md failure.md failure.zh.md fix.diff; do
if [[ -f "${WORKDIR}/${f}" ]]; then
echo "=============== ${f} ==============="
# Agent-written content on step STDOUT: a line-start `::` would
# be parsed as a workflow command (::error::, ::add-mask::), the
# same reason the PR-lane dump loop neutralizes it. (The two
# step-SUMMARY loops write to a file, where `::` is not
# Agent-written content on step STDOUT: both workflow-command
# syntaxes parse here — a line-start `::` (::error::,
# ::add-mask::) AND `##[` even mid-line (a quoted
# `##[add-matcher]` fails THIS step; measured on #9761). The
# same reason the PR-lane dump loop neutralizes both. (The two
# step-SUMMARY loops write to a file, where commands are not
# parsed.)
sed 's/::/;;/g' "${WORKDIR}/${f}"
sed -e 's/::/;;/g' -e 's/##\[/##[/g' "${WORKDIR}/${f}"
echo
fi
done
Expand Down Expand Up @@ -4699,7 +4703,17 @@ jobs:
fi
} > "${WORKDIR}/feedback.md"
echo '--- feedback.md ---'
cat "${WORKDIR}/feedback.md"
# Reviewer/bot comment bodies ride this file VERBATIM and this echo
# puts them on step stdout, which the runner scans for workflow
# commands in BOTH syntaxes: `::name::` AND the legacy `##[name]`,
# the latter parsed MID-line too — a quoted `##[add-matcher]` makes
# the runner load the rest of the line as a matcher file and fail
# THIS step before the agent runs. Measured on #9761: a review
# finding about that injection channel carried the payload strings
# as its example text, and five consecutive pre-agent crashes
# burned the takeover window in ~70 minutes. Neutralize both
# prefixes like every other untrusted echo.
cat "${WORKDIR}/feedback.md" | sed -e 's/::/;;/g' -e 's/##\[/##[/g'

# The agent below runs for up to 130 minutes and the verification gate adds
# more, but nothing reaches the PR thread until "Push and report" at the
Expand Down Expand Up @@ -5072,7 +5086,9 @@ jobs:
else
echo "::warning::could not merge carried deferrals across the repair (one of the two sets is unparseable); keeping the carried set and preserving this round's as deferred-findings.unmerged.json. Raw content follows:"
fi
head -c 4000 "${WORKDIR}/deferred-findings.json" | sed 's/::/;;/g'
# Both command syntaxes, like every other untrusted echo
# (`##[` parses mid-line too — #9761).
head -c 4000 "${WORKDIR}/deferred-findings.json" | sed -e 's/::/;;/g' -e 's/##\[/##[/g'
echo
rm -f "${WORKDIR}/deferred-findings.carry.next"
# Keep the discarded set ON DISK so the warning's pointer at
Expand Down Expand Up @@ -5300,10 +5316,12 @@ jobs:
for f in feedback.md address-summary.md no-action.md failure.md failure.zh.md handoff.md gate-rejection.md gate-advisories.md growth-audit.json agent-api-error agent-api-error-kind agent-timeout resolved-comments.txt comment-replies.json deferred-findings.json deferred-findings.carry.json deferred-findings.unmerged.json pr.diff; do
if [[ -f "${WORKDIR}/${f}" ]]; then
echo "=============== ${f} ==============="
# Agent-written content: a line-start `::` would be parsed as a
# workflow command (::error::, ::add-mask::), the same reason
# every other echo of these files neutralizes it.
sed 's/::/;;/g' "${WORKDIR}/${f}"
# Agent/reviewer-written content: both workflow-command syntaxes
# parse here — a line-start `::` (::error::, ::add-mask::) AND
# `##[` even mid-line (a quoted `##[add-matcher]` fails THIS
# step; measured on #9761 via the prepare echo of this same
# file). Neutralize both, like every other echo of these files.
sed -e 's/::/;;/g' -e 's/##\[/##[/g' "${WORKDIR}/${f}"
echo
fi
done
Expand Down Expand Up @@ -5995,7 +6013,8 @@ jobs:
elif [[ "${_upsert_line}" == __upsert_trusted__* ]]; then
printf '%s\n' "${_upsert_line#__upsert_trusted__}"
else
printf '%s\n' "${_upsert_line//::/;;}"
# Both command syntaxes (`##[` parses mid-line too — #9761).
printf '%s\n' "${_upsert_line//::/;;}" | sed 's/##\[/##[/g'
fi
done <<< "${UPSERT_OUT}"
fi
Expand Down
Loading
Loading