Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
10 changes: 7 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,10 @@ run_deferred_upsert() {
elif [[ "${_upsert_line}" == __upsert_trusted__* ]]; then
printf '%s\n' "${_upsert_line#__upsert_trusted__}"
else
printf '%s\n' "${_upsert_line//::/;;}"
# The canonical two-expression neutralizer, identical to every other
# echo site — one spelling for the whole family, so a syntax change
# cannot drift across two implementations.
printf '%s\n' "${_upsert_line}" | sed -e 's/::/;;/g' -e 's/##\[/##[/g'
Comment thread
wenshao marked this conversation as resolved.
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
50 changes: 36 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,11 @@ jobs:
elif [[ "${_upsert_line}" == __upsert_trusted__* ]]; then
printf '%s\n' "${_upsert_line#__upsert_trusted__}"
else
printf '%s\n' "${_upsert_line//::/;;}"
# The canonical two-expression neutralizer, identical to
# every other echo site — one spelling for the whole
# family, so a syntax change cannot drift across two
# implementations (`##[` parses mid-line too — #9761).
printf '%s\n' "${_upsert_line}" | sed -e 's/::/;;/g' -e 's/##\[/##[/g'
fi
done <<< "${UPSERT_OUT}"
fi
Expand Down
Loading
Loading