Reject hidden PR body content
test / test (pull_request) Successful in 6s

Authored-By: Codex (GPT-5) <noreply@openai.com>
This commit is contained in:
2026-08-27 17:11:21 +00:00
parent 5ce83cdf13
commit 0d768ef75b
3 changed files with 23 additions and 97 deletions
+2 -1
View File
@@ -73,7 +73,8 @@ The check validates four things for every non-break-glass Agent PR:
`Fixes bug-<id>` automation token and the matching navigable
`https://agenthub.fritzlab.net/bug-<id>` URL. Every PR has a separate
`## Attribution` section containing the canonical `Authored-By`
product/model watermark.
product/model watermark. Agent-authored PR bodies cannot contain HTML
comment delimiters, so required provenance cannot be hidden from readers.
4. **Commit attribution** — every commit in `base-sha..head-sha`, including
commits on `chore/` branches, ends with
+9 -84
View File
@@ -11,90 +11,6 @@ BODY="${PR_BODY:-}"
BASE="${BASE_SHA:-}"
HEAD="${HEAD_SHA:-}"
# Gitea renders HTML comments as hidden. Validate the visible body so required
# tracking and attribution cannot exist only in comment source.
VISIBLE_BODY=$(printf '%s\n' "${BODY}" | awk '
{
line=$0
fence_pos=1
while (fence_pos <= 3 && substr(line, fence_pos, 1) == " ") fence_pos++
fence_char=substr(line, fence_pos, 1)
fence_run=0
if (fence_char == "`" || fence_char == "~") {
while (substr(line, fence_pos + fence_run, 1) == fence_char) fence_run++
}
if (!in_comment && in_fence) {
print line
if (fence_char == active_fence_char && fence_run >= active_fence_run) in_fence=0
next
}
fence_info=substr(line, fence_pos + fence_run)
valid_fence_info=(fence_char == "~" || index(fence_info, "`") == 0)
if (!in_comment && fence_run >= 3 && valid_fence_info) {
in_fence=1
active_fence_char=fence_char
active_fence_run=fence_run
print line
next
}
visible=""
pos=1
backslash_run=0
while (pos <= length(line)) {
if (in_comment) {
rest=substr(line, pos)
comment_end=index(rest, "-->")
if (comment_end == 0) {
pos=length(line) + 1
break
}
visible=visible " "
pos += comment_end + 2
in_comment=0
backslash_run=0
continue
}
if (substr(line, pos, 1) == "`" && backslash_run % 2 == 0) {
ticks=1
while (substr(line, pos + ticks, 1) == "`") ticks++
close_pos=pos + ticks
found_close=0
while (close_pos <= length(line)) {
if (substr(line, close_pos - 1, 1) != "`" &&
substr(line, close_pos, ticks) == substr(line, pos, ticks) &&
substr(line, close_pos + ticks, 1) != "`") {
found_close=1
break
}
close_pos++
}
if (found_close) {
visible=visible substr(line, pos, close_pos + ticks - pos)
pos=close_pos + ticks
backslash_run=0
continue
}
}
if (substr(line, pos, 4) == "<!--") {
visible=visible " "
in_comment=1
pos += 4
backslash_run=0
continue
}
char=substr(line, pos, 1)
visible=visible char
if (char == "\\") backslash_run++
else backslash_run=0
pos++
}
print visible
}
')
# Break-glass: dfritz is exempt from all naming checks.
if [ "${AUTHOR}" = "dfritz" ]; then
echo "check-naming: dfritz break-glass — exempt"
@@ -105,6 +21,15 @@ FAILED=0
BRANCH_KIND="invalid"
BRANCH_BUG=""
# Gitea hides HTML comments. Reject their delimiters so required provenance is
# always visible, then parse the raw body without a second Markdown renderer.
VISIBLE_BODY="${BODY}"
if printf '%s\n' "${BODY}" | grep -Fq '<!--' ||
printf '%s\n' "${BODY}" | grep -Fq -- '-->'; then
echo "FAIL[check-naming]: PR body must not contain HTML comment delimiters"
FAILED=1
fi
# ---- branch form ----
# <role>/bug-<id>/<kebab>
if echo "${BRANCH}" | grep -qE "^(dev|ux|ops|security|perf|architect|support)/bug-[a-z0-9]+/[a-z0-9][a-z0-9-]*$"; then
+12 -12
View File
@@ -140,30 +140,30 @@ check_contract "attribution must be in its own section" \
"$BASE" "$GOOD_HEAD" "## Attribution must contain"
check_contract "hidden provenance does not satisfy the visible contract" \
$'<!--\n## Tracking\n- Fixes bug-x7k2m9 — https://agenthub.fritzlab.net/bug-x7k2m9\n\n## Attribution\n- Authored-By: Codex (GPT-5) <noreply@openai.com>\n-->' \
"$BASE" "$GOOD_HEAD" "PR body must contain a non-empty ## Tracking section"
"$BASE" "$GOOD_HEAD" "PR body must not contain HTML comment delimiters"
check_contract "comment removal cannot synthesize section headings" \
$'<!-- hidden -->## Tracking\n- Fixes bug-x7k2m9 — https://agenthub.fritzlab.net/bug-x7k2m9\n\n<!-- hidden -->## Attribution\n- Authored-By: Codex (GPT-5) <noreply@openai.com>' \
"$BASE" "$GOOD_HEAD" "PR body must contain a non-empty ## Tracking section"
"$BASE" "$GOOD_HEAD" "PR body must not contain HTML comment delimiters"
check_contract "four-space indented backticks do not expose comments" \
$' ````\n<!--\n## Tracking\n- Fixes bug-x7k2m9 — https://agenthub.fritzlab.net/bug-x7k2m9\n\n## Attribution\n- Authored-By: Codex (GPT-5) <noreply@openai.com>\n-->' \
"$BASE" "$GOOD_HEAD" "PR body must contain a non-empty ## Tracking section"
"$BASE" "$GOOD_HEAD" "PR body must not contain HTML comment delimiters"
check_contract "unequal backtick runs do not expose comments" \
$'`<!--``\n## Tracking\n- Fixes bug-x7k2m9 — https://agenthub.fritzlab.net/bug-x7k2m9\n\n## Attribution\n- Authored-By: Codex (GPT-5) <noreply@openai.com>\n-->' \
"$BASE" "$GOOD_HEAD" "PR body must contain a non-empty ## Tracking section"
"$BASE" "$GOOD_HEAD" "PR body must not contain HTML comment delimiters"
check_contract "invalid backtick fence info does not expose comments" \
$'```html`oops\n<!--\n## Tracking\n- Fixes bug-x7k2m9 — https://agenthub.fritzlab.net/bug-x7k2m9\n\n## Attribution\n- Authored-By: Codex (GPT-5) <noreply@openai.com>\n-->' \
"$BASE" "$GOOD_HEAD" "PR body must contain a non-empty ## Tracking section"
"$BASE" "$GOOD_HEAD" "PR body must not contain HTML comment delimiters"
check_contract "invalid fence closer does not expose comments" \
$'```html\n```oops\n```\n<!--\n## Tracking\n- Fixes bug-x7k2m9 — https://agenthub.fritzlab.net/bug-x7k2m9\n\n## Attribution\n- Authored-By: Codex (GPT-5) <noreply@openai.com>\n-->' \
"$BASE" "$GOOD_HEAD" "PR body must not contain HTML comment delimiters"
check_contract "fences inside comments do not expose provenance" \
$'<!--\n```html\n## Tracking\n- Fixes bug-x7k2m9 — https://agenthub.fritzlab.net/bug-x7k2m9\n\n## Attribution\n- Authored-By: Codex (GPT-5) <noreply@openai.com>\n-->' \
"$BASE" "$GOOD_HEAD" "PR body must contain a non-empty ## Tracking section"
"$BASE" "$GOOD_HEAD" "PR body must not contain HTML comment delimiters"
check_contract "escaped backticks do not hide a comment opener" \
$'\\`<!--\\`\n## Tracking\n- Fixes bug-x7k2m9 — https://agenthub.fritzlab.net/bug-x7k2m9\n\n## Attribution\n- Authored-By: Codex (GPT-5) <noreply@openai.com>\n-->' \
"$BASE" "$GOOD_HEAD" "PR body must contain a non-empty ## Tracking section"
check_contract_pass "inline code containing comment opener stays visible" \
$'Use `<!--` when documenting an HTML comment opener.\n\n## Tracking\n- Fixes bug-x7k2m9 — https://agenthub.fritzlab.net/bug-x7k2m9\n\n## Attribution\n- Authored-By: Codex (GPT-5) <noreply@openai.com>' \
"$BASE" "$GOOD_HEAD"
check_contract_pass "fenced code containing comments stays visible" \
$'```html\n<!-- example -->\n```\n\n## Tracking\n- Fixes bug-x7k2m9 — https://agenthub.fritzlab.net/bug-x7k2m9\n\n## Attribution\n- Authored-By: Codex (GPT-5) <noreply@openai.com>' \
"$BASE" "$GOOD_HEAD" "PR body must not contain HTML comment delimiters"
check_contract_pass "fenced code without comments remains valid" \
$'```text\nvisible example\n```\n\n## Tracking\n- Fixes bug-x7k2m9 — https://agenthub.fritzlab.net/bug-x7k2m9\n\n## Attribution\n- Authored-By: Codex (GPT-5) <noreply@openai.com>' \
"$BASE" "$GOOD_HEAD"
git -C "${FIXTURES}" commit --allow-empty -q -m "unwatermarked change"