~bigbes/agents-dev · parade

main · last commit 13 days ago · 7g0stsfu

← Back to the parade

ah-1cx.5 vikunja markdown: URL autolink collides with bold / trailing-ampersand entity Past Stand

status: closed P4 bug milestone:v0.2.0
bd reopen ah-1cx.5
Created byEugene Blikh
Ownerbigbes@gmail.com
Created2026-07-19T23:37:48Z
Started2026-08-04T23:32:44Z
Updated2026-08-04T23:42:04Z
Closed2026-08-04T23:42:04Z
Description
renderInline (markdown.go:203-211) runs escape, then URL-autolink, then bold. urlRe greedily swallows a trailing ** into the URL and boldRe then matches across the emitted anchor markup, producing interleaved broken tags for input like: see **http://example.com/x** now. Separately a URL ending in a bare ampersand becomes a split, broken amp-entity. Both reproduced against the exact regexes; the realistic mid-URL query case renders fine, so severity is low. Fix: constrain the URL match at **/entity boundaries or reorder the passes; add cases to markdown_test.go. Adapter audit 2026-07-20.

Depends on

  • ah-1cx — Hardening: post-audit bug sweep (2026-07-20) parent-child open

Depended on by

Nothing depends on this issue.

No comments.

Close reason

Fixed in c2e29c1. renderInline ran escape → autolink → bold, and BOTH later passes collided with the anchor the middle pass had already emitted. urlRe treats '*' as an ordinary URL character, so 'see **http://example.com/x** now' swallowed the closing ** into both the href and the link text, and boldRe then matched from the opening ** across the emitted markup, yielding interleaved <strong>/<a> garbage. Separately, because the pass runs on ALREADY-ESCAPED text, a URL ending in a bare & became …&amp; and urlRe — which excludes a trailing ';' as sentence punctuation — stopped at …&amp, splitting the entity across </a>; same for a URL followed by > or '. Fix: reorder so bold runs FIRST (the ** markers are consumed while still adjacent to the URL, and urlRe's class already excludes the '<' of the resulting <strong> tag, so the link nests strictly inside the bold), and replace the ReplaceAllString autolink with autolinkURLs, which re-cuts every match through the new splitURLTail. splitURLTail alternates two rules until neither fires: push a trailing INCOMPLETE entity (an & with no ; after it) out of the anchor so the ; left in the surrounding text re-joins it, then re-apply the trailing-punctuation rule ('.,;:!?)]' plus '*', so an unpaired bold marker can never ride into an href) to the newly exposed last character. A complete entity mid-URL (?a=1&amp;b=2) contains its ; and is untouched, keeping the realistic query-string case rendering as before; a match trimmed down to a bare scheme (http://&) is left unlinked instead of emitting a dud anchor. Seven table cases added; all five collision cases were written first and confirmed RED against the old converter.
  • Eugene Blikh added under epic ah-1cx · 2026-07-20T02:37:48Z
  • Eugene Blikh created the issue · 2026-07-20T02:37:48Z
  • Eugene Blikh added label milestone:hardening · 2026-07-20T03:08:20Z
  • Eugene Blikh removed label milestone:hardening · 2026-07-20T03:10:16Z
  • Eugene Blikh added label milestone:v0.1.0 · 2026-07-20T03:11:24Z
  • Eugene Blikh removed label milestone:v0.1.0 · 2026-07-20T03:13:45Z
  • Eugene Blikh added label milestone:v0.2.0 · 2026-07-20T03:13:46Z
  • Eugene Blikh changed status to in_progress · 2026-08-05T02:32:43Z
  • Eugene Blikh closed the issue · 2026-08-05T02:42:04Z
    Fixed in c2e29c1. renderInline ran escape → autolink → bold, and BOTH later passes collided with the anchor the middle pass had already emitted. urlRe treats '*' as an ordinary URL character, so 'see **http://example.com/x** now' swallowed the closing ** into both the href and the link text, and boldRe then matched from the opening ** across the emitted markup, yielding interleaved <strong>/<a> garbage. Separately, because the pass runs on ALREADY-ESCAPED text, a URL ending in a bare & became …&amp; and urlRe — which excludes a trailing ';' as sentence punctuation — stopped at …&amp, splitting the entity across </a>; same for a URL followed by > or '. Fix: reorder so bold runs FIRST (the ** markers are consumed while still adjacent to the URL, and urlRe's class already excludes the '<' of the resulting <strong> tag, so the link nests strictly inside the bold), and replace the ReplaceAllString autolink with autolinkURLs, which re-cuts every match through the new splitURLTail. splitURLTail alternates two rules until neither fires: push a trailing INCOMPLETE entity (an & with no ; after it) out of the anchor so the ; left in the surrounding text re-joins it, then re-apply the trailing-punctuation rule ('.,;:!?)]' plus '*', so an unpaired bold marker can never ride into an href) to the newly exposed last character. A complete entity mid-URL (?a=1&amp;b=2) contains its ; and is untouched, keeping the realistic query-string case rendering as before; a match trimmed down to a bare scheme (http://&) is left unlinked instead of emitting a dud anchor. Seven table cases added; all five collision cases were written first and confirmed RED against the old converter.
Stored rows — what this pane was built from, as read
issues 1 row
id ah-1cx.5
content_hash 3b52211a9bdaa7c6e5ae2ecf70e7f8f7402cd28f4f4ed3ee2da728743e935122
title vikunja markdown: URL autolink collides with bold / trailing-ampersand entity
description renderInline (markdown.go:203-211) runs escape, then URL-autolink, then bold. urlRe greedily swallows a trailing ** into the URL and boldRe then matches across the emitted anchor markup, producing interleaved broken tags for input like: see **http://example.com/x** now. Separately a URL ending in a bare ampersand becomes a split, broken amp-entity. Both reproduced against the exact regexes; the realistic mid-URL query case renders fine, so severity is low. Fix: constrain the URL match at **/entity boundaries or reorder the passes; add cases to markdown_test.go. Adapter audit 2026-07-20.
design
acceptance_criteria
notes
status closed
priority 4
issue_type bug
assignee NULL
estimated_minutes NULL
created_at 2026-07-19T23:37:48Z
created_by Eugene Blikh
owner bigbes@gmail.com
updated_at 2026-08-04T23:42:04Z
closed_at 2026-08-04T23:42:04Z
closed_by_session
external_ref NULL
spec_id
compaction_level 0
compacted_at NULL
compacted_at_commit NULL
original_size NULL
sender
ephemeral 0
wisp_type
pinned 0
is_template 0
mol_type
work_type
source_system
metadata �{}
source_repo
close_reason Fixed in c2e29c1. renderInline ran escape → autolink → bold, and BOTH later passes collided with the anchor the middle pass had already emitted. urlRe treats '*' as an ordinary URL character, so 'see **http://example.com/x** now' swallowed the closing ** into both the href and the link text, and boldRe then matched from the opening ** across the emitted markup, yielding interleaved <strong>/<a> garbage. Separately, because the pass runs on ALREADY-ESCAPED text, a URL ending in a bare & became …&amp; and urlRe — which excludes a trailing ';' as sentence punctuation — stopped at …&amp, splitting the entity across </a>; same for a URL followed by > or '. Fix: reorder so bold runs FIRST (the ** markers are consumed while still adjacent to the URL, and urlRe's class already excludes the '<' of the resulting <strong> tag, so the link nests strictly inside the bold), and replace the ReplaceAllString autolink with autolinkURLs, which re-cuts every match through the new splitURLTail. splitURLTail alternates two rules until neither fires: push a trailing INCOMPLETE entity (an & with no ; after it) out of the anchor so the ; left in the surrounding text re-joins it, then re-apply the trailing-punctuation rule ('.,;:!?)]' plus '*', so an unpaired bold marker can never ride into an href) to the newly exposed last character. A complete entity mid-URL (?a=1&amp;b=2) contains its ; and is untouched, keeping the realistic query-string case rendering as before; a match trimmed down to a bare scheme (http://&) is left unlinked instead of emitting a dud anchor. Seven table cases added; all five collision cases were written first and confirmed RED against the old converter.
event_kind
actor
target
payload
await_type
await_id
timeout_ns 0
waiters
hook_bead
role_bead
agent_state
last_activity NULL
role_type
rig
due_at NULL
defer_until NULL
no_history 0
started_at 2026-08-04T23:32:44Z
is_blocked 0
labels 1 row
issue_id ah-1cx.5
label milestone:v0.2.0
dependencies 1 row
id dd81dc70-6c53-505c-b9cd-6ef452f0b93a
issue_id ah-1cx.5
type parent-child
created_at 2026-07-20T02:37:48Z
created_by Eugene Blikh
metadata �{}
thread_id
depends_on_issue_id ah-1cx
depends_on_wisp_id NULL
depends_on_external NULL
events 8 rows
id 019f7cbe-35a4-7a12-8407-175c75a23c29
issue_id ah-1cx.5
event_type created
actor Eugene Blikh
old_value
new_value
comment NULL
created_at 2026-07-20T02:37:48Z
id 019f7cda-2a1f-7ce8-8d6a-43feb177a5ba
issue_id ah-1cx.5
event_type label_added
actor Eugene Blikh
old_value NULL
new_value NULL
comment Added label: milestone:hardening
created_at 2026-07-20T03:08:20Z
id 019f7cdb-ef13-7bb0-ba3b-491a68f49ca7
issue_id ah-1cx.5
event_type label_removed
actor Eugene Blikh
old_value NULL
new_value NULL
comment Removed label: milestone:hardening
created_at 2026-07-20T03:10:16Z
id 019f7cdc-faeb-70da-aea2-4813f4c92a2c
issue_id ah-1cx.5
event_type label_added
actor Eugene Blikh
old_value NULL
new_value NULL
comment Added label: milestone:v0.1.0
created_at 2026-07-20T03:11:24Z
id 019f7cdf-21e2-78f8-b388-bf2883e5ccc4
issue_id ah-1cx.5
event_type label_removed
actor Eugene Blikh
old_value NULL
new_value NULL
comment Removed label: milestone:v0.1.0
created_at 2026-07-20T03:13:45Z
id 019f7cdf-22e3-7a0a-a510-312881de1312
issue_id ah-1cx.5
event_type label_added
actor Eugene Blikh
old_value NULL
new_value NULL
comment Added label: milestone:v0.2.0
created_at 2026-07-20T03:13:46Z
id 019fcf1f-5107-7674-9f10-a86672b359ad
issue_id ah-1cx.5
event_type status_changed
actor Eugene Blikh
old_value {"id":"ah-1cx.5","title":"vikunja markdown: URL autolink collides with bold / trailing-ampersand entity","description":"renderInline (markdown.go:203-211) runs escape, then URL-autolink, then bold. urlRe greedily swallows a trailing ** into the URL and boldRe then matches across the emitted anchor markup, producing interleaved broken tags for input like: see **http://example.com/x** now. Separately a URL ending in a bare ampersand becomes a split, broken amp-entity. Both reproduced against the exact regexes; the realistic mid-URL query case renders fine, so severity is low. Fix: constrain the URL match at **/entity boundaries or reorder the passes; add cases to markdown_test.go. Adapter audit 2026-07-20.","status":"open","priority":4,"issue_type":"bug","owner":"bigbes@gmail.com","created_at":"2026-07-19T23:37:48Z","created_by":"Eugene Blikh","updated_at":"2026-07-19T23:37:48Z","labels":["milestone:v0.2.0"]}
new_value {"status":"in_progress"}
comment NULL
created_at 2026-08-05T02:32:43Z
id 019fcf27-dd07-78a2-8108-ab6252ec3812
issue_id ah-1cx.5
event_type closed
actor Eugene Blikh
old_value
new_value Fixed in c2e29c1. renderInline ran escape → autolink → bold, and BOTH later passes collided with the anchor the middle pass had already emitted. urlRe treats '*' as an ordinary URL character, so 'see **http://example.com/x** now' swallowed the closing ** into both the href and the link text, and boldRe then matched from the opening ** across the emitted markup, yielding interleaved <strong>/<a> garbage. Separately, because the pass runs on ALREADY-ESCAPED text, a URL ending in a bare & became …&amp; and urlRe — which excludes a trailing ';' as sentence punctuation — stopped at …&amp, splitting the entity across </a>; same for a URL followed by > or '. Fix: reorder so bold runs FIRST (the ** markers are consumed while still adjacent to the URL, and urlRe's class already excludes the '<' of the resulting <strong> tag, so the link nests strictly inside the bold), and replace the ReplaceAllString autolink with autolinkURLs, which re-cuts every match through the new splitURLTail. splitURLTail alternates two rules until neither fires: push a trailing INCOMPLETE entity (an & with no ; after it) out of the anchor so the ; left in the surrounding text re-joins it, then re-apply the trailing-punctuation rule ('.,;:!?)]' plus '*', so an unpaired bold marker can never ride into an href) to the newly exposed last character. A complete entity mid-URL (?a=1&amp;b=2) contains its ; and is untouched, keeping the realistic query-string case rendering as before; a match trimmed down to a bare scheme (http://&) is left unlinked instead of emitting a dud anchor. Seven table cases added; all five collision cases were written first and confirmed RED against the old converter.
comment NULL
created_at 2026-08-05T02:42:04Z