Harden external plugin gate comment output safety (#2265)

* Harden external plugin gate comment rendering

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Fix gate output truncation after HTML escaping

Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com>

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com>
This commit is contained in:
Aaron Powell
2026-07-10 16:20:01 +10:00
committed by GitHub
parent 1af733e9df
commit 30472ecf0f
@@ -200,15 +200,37 @@ jobs:
: qualityResult.overall_status === 'pass' || !shouldRun
? '## ✅ External plugin PR checks passed'
: '## ⚠️ External plugin PR checks need maintainer follow-up';
const MAX_GATE_OUTPUT_CHARS = 2000;
const escapeHtml = (value) =>
String(value || '')
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
const TRUNCATED_OUTPUT_MARKER = '\n...output truncated...';
const truncateGateOutput = (rawOutput) => {
const normalized = escapeHtml(String(rawOutput || '').trim());
if (!normalized) {
return '_No output captured._';
}
if (normalized.length <= MAX_GATE_OUTPUT_CHARS) {
return normalized;
}
return `${normalized.slice(0, Math.max(0, MAX_GATE_OUTPUT_CHARS - TRUNCATED_OUTPUT_MARKER.length))}${TRUNCATED_OUTPUT_MARKER}`;
};
const formatGateOutput = (pluginName, gateName, gateStatus, rawOutput) => {
const output = String(rawOutput || '').trim() || '_No output captured._';
const summaryPluginName = escapeHtml(String(pluginName || 'unknown'));
const summaryGateName = escapeHtml(String(gateName || 'gate'));
const summaryGateStatus = escapeHtml(String(gateStatus || 'not_run'));
const output = truncateGateOutput(rawOutput);
return [
'<details>',
`<summary>${pluginName} ${gateName} (${gateStatus || 'not_run'})</summary>`,
`<summary>${summaryPluginName} - ${summaryGateName} (${summaryGateStatus})</summary>`,
'',
'```text',
'<pre><code>',
output,
'```',
'</code></pre>',
'</details>',
].join('\n');
};