Development record
memory lint's run-log report.md (renderLintReportMD, internal/core/memory/lint.go) renders a finding's file, message and suggestion through termsafe.Sanitize alone, so a page name or a pii.json pattern name carrying an HTML comment opener or link syntax reaches the markdown report live; the memory renderers fixed for iss-2609020539188868 and the lifeboat renderers fixed for iss-2609251355497247 route the same kind of field through termsafe.CleanProse and set a path off with termsafe.CodeSpan.
issueresolvedminoriss-2609262148072415
memory lint's run-log report.md (renderLintReportMD, internal/core/memory/lint.go) renders a finding's file, message and suggestion through termsafe.Sanitize alone, so a page name or a pii.json pattern name carrying an HTML comment opener or link syntax reaches the markdown report live; the memory renderers fixed for iss-2609020539188868 and the lifeboat renderers fixed for iss-2609251355497247 route the same kind of field through termsafe.CleanProse and set a path off with termsafe.CodeSpan.
Grounds
- pursued: a finding whose file, message and suggestion carry a comment opener, a script tag and link syntax renders none of them live in report.md and its file inside a code span; any of the three appearing live would show it wrong
Frontmatter
| id | iss-2609262148072415 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | minor |
.abcd/work/issues/resolved/iss-2609262148072415-memory-lint-s-run-log-report-md.md
open on GitHub ↗ · commit history ↗
mentions2
- iss-2609020539188868Three markdown renderers re-escape or re-wrap a value termsafe already cleaned, which is the class the intent audit's renderEvidence just had fixed. termsafe's guarantees hold over the exact string CleanProse returned; a caller that adds its own delimiters is parsing a different string than the cleaner reasoned about. memory.RenderIndex and memory.RenderContradictions (internal/core/memory/schema.go, the two backtick-wrapped format strings) wrap a cleaned page filename in their own backticks, so a filename carrying a backtick shifts code-span parity in the committed .abcd/memory/index.md and contradictions.md and can move a sheltered angle bracket out of its span; memory.Ask's match render has the same shape over a value cleaned only by Sanitize; lifeboat's synthesis_review severity bracket and press-release subhead emphasis are the weaker form (neither delimiter affects span parity, and the artefact is not a committed record), and synthesis_review renders f.ID through Sanitize alone, never CleanProse, so it can still carry an HTML comment opener or link syntax; lifeboat's synthesis_principles writes a cleaned principle as a bare paragraph with no leading-marker escape. Out of scope for the code-span fix that found them (a different package, a different caller, and none is a defect that change introduced). What the fix DID close for all of them is the same-line embedding half: no cleaned field can carry an unpaired backtick run any more, so two cleaned values on one line cannot re-pair. The fix must establish that no renderer alters a cleaned value's bytes, and that every untrusted field on a committed markdown line goes through CleanProse rather than Sanitize alone.
- iss-2609251355497247The lifeboat half of iss-2609020539188868 is still open after the memory renderers were fixed: synthesis_review renders a finding id through termsafe.Sanitize alone, never CleanProse, so it can still carry an HTML comment opener or link syntax, and wraps a severity in its own bracket; the press-release subhead wraps a cleaned value in its own emphasis; synthesis_principles writes a cleaned principle as a bare paragraph with no leading-marker escape. The fix is the one applied to memory: every untrusted field on a markdown line through CleanProse, and no renderer adding delimiters around a cleaned value (termsafe.CodeSpan where a code span is wanted).