[bug-yhg8dqypwmar] fix(check-naming): reject hidden provenance #4

Merged
architect merged 12 commits from architect/bug-yhg8dqypwmar/reject-hidden-provenance into main 2026-08-27 17:53:56 +00:00
3 changed files with 10 additions and 3 deletions
Showing only changes of commit 79d6ba5be9 - Show all commits
+3 -1
View File
1
@@ -55,9 +55,11 @@ VISIBLE_BODY=$(printf '%s\n' "${RENDERED_BODY}" |
if (char == ">") { if (char == ">") {
lower=tolower(tag) lower=tolower(tag)
Review

You put canonical provenance inside <details open>; Gitea preserves open and shows both sections on load, but this branch increments details_depth and removes them. The check exits 1 claiming the visible sections are missing. Preserve open disclosure content unless a collapsed ancestor still hides it, and cover that recovery path.

You put canonical provenance inside `<details open>`; Gitea preserves `open` and shows both sections on load, but this branch increments `details_depth` and removes them. The check exits 1 claiming the visible sections are missing. Preserve open disclosure content unless a collapsed ancestor still hides it, and cover that recovery path.
if (lower ~ /^<details([[:space:]>])/) { if (lower ~ /^<details([[:space:]>])/) {
attributes=lower
gsub(/"[^"]*"/, "", attributes)
parent_hidden=(details_depth > 0 && hidden[details_depth]) parent_hidden=(details_depth > 0 && hidden[details_depth])
Review

Blocker: You submit <details title=" open "> with canonical Tracking and Attribution inside. Gitea preserves the attribute and the browser keeps the disclosure collapsed, but this substring match treats the title value as the boolean open attribute. Exact head returns check-naming: ok.

The checked <details open> path has an unchecked open-inside-an-attribute-value twin on this line, and it takes the same hidden provenance.

title isn't sanitized away: authenticated /markdown returned <details title=" open ">. This isn't malformed HTML; it is valid rendered markup and remains collapsed.

Parse attributes as tokens, then add this exact reproduction.

Blocker: You submit `<details title=" open ">` with canonical Tracking and Attribution inside. Gitea preserves the attribute and the browser keeps the disclosure collapsed, but this substring match treats the title value as the boolean `open` attribute. Exact head returns `check-naming: ok`. The checked `<details open>` path has an unchecked `open`-inside-an-attribute-value twin on this line, and it takes the same hidden provenance. `title` isn't sanitized away: authenticated `/markdown` returned `<details title=" open ">`. This isn't malformed HTML; it is valid rendered markup and remains collapsed. Parse attributes as tokens, then add this exact reproduction.
Review

Blocker: this regex matches open anywhere in the serialized tag, including a quoted attribute value. <details title=" open "> has no boolean open attribute, so the browser keeps its provenance collapsed; Gitea preserves that tag and exact-head execution accepts the hidden Tracking and Attribution. Recognize an actual attribute name boundary outside quoted values, then cover this exact body.

Blocker: this regex matches ` open ` anywhere in the serialized tag, including a quoted attribute value. `<details title=" open ">` has no boolean `open` attribute, so the browser keeps its provenance collapsed; Gitea preserves that tag and exact-head execution accepts the hidden Tracking and Attribution. Recognize an actual attribute name boundary outside quoted values, then cover this exact body.
Review

Blocker: open is searched across the whole serialized tag, so an ordinary attribute value containing whitespace-delimited open makes a collapsed disclosure visible to this filter. Gitea preserves <details title="x open y"> without the boolean attribute; putting canonical Tracking and Attribution inside it renders collapsed, but exact head exits 0 with check-naming: ok. Match the actual boolean attribute without accepting text inside quoted attribute values, then add this reproduction.

Blocker: `open` is searched across the whole serialized tag, so an ordinary attribute value containing whitespace-delimited `open` makes a collapsed disclosure visible to this filter. Gitea preserves `<details title="x open y">` without the boolean attribute; putting canonical Tracking and Attribution inside it renders collapsed, but exact head exits 0 with `check-naming: ok`. Match the actual boolean attribute without accepting text inside quoted attribute values, then add this reproduction.
details_depth++ details_depth++
hidden[details_depth]=(parent_hidden || lower !~ /[[:space:]]open([[:space:]=>]|$)/) hidden[details_depth]=(parent_hidden || attributes !~ /[[:space:]]open([[:space:]=>]|$)/)
} }
else if (lower ~ /^<\/details([[:space:]>])/) { else if (lower ~ /^<\/details([[:space:]>])/) {
if (details_depth > 0) { if (details_depth > 0) {
+4 -2
View File
@@ -62,8 +62,10 @@ printf '%s\n' "${PR_BODY}" | awk '
next next
} }
if (lower ~ /^[ ]{0,3}<details([[:blank:]>])/) { if (lower ~ /^[ ]{0,3}<details([[:blank:]>])/) {
if (lower ~ /[[:blank:]]open([[:blank:]=>]|$)/) print "<details open=\"\">" attributes=lower
else print "<details>" gsub(/"[^"]*"/, "", attributes)
if (attributes ~ /[[:blank:]]open([[:blank:]=>]|$)/) sub(/<details open>/, "<details open=\"\">", line)
print line
next next
} }
if (line ~ /^## Tracking[[:space:]]*$/) print "<h2>Tracking</h2>" if (line ~ /^## Tracking[[:space:]]*$/) print "<h2>Tracking</h2>"
+3
View File
@@ -185,6 +185,9 @@ check_contract_pass "open details preserve visible provenance" \
check_contract "open details inside collapsed details remain hidden" \ check_contract "open details inside collapsed details remain hidden" \
$'<details><summary>Release notes</summary>\n<details open><summary>Visible only after expansion</summary>\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</details>\n</details>' \ $'<details><summary>Release notes</summary>\n<details open><summary>Visible only after expansion</summary>\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</details>\n</details>' \
"$BASE" "$GOOD_HEAD" "PR body must contain a non-empty ## Tracking section" "$BASE" "$GOOD_HEAD" "PR body must contain a non-empty ## Tracking section"
check_contract "open text in another details attribute remains collapsed" \
$'<details title="x open y"><summary>Release notes</summary>\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</details>' \
"$BASE" "$GOOD_HEAD" "PR body must contain a non-empty ## Tracking section"
check_contract_pass "unrelated collapsed details remain available" \ check_contract_pass "unrelated collapsed details remain available" \
$'<details><summary>Logs</summary>\n\nSupporting output\n</details>\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>' \ $'<details><summary>Logs</summary>\n\nSupporting output\n</details>\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" "$BASE" "$GOOD_HEAD"