You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Don't filter "<...>" in code paragraphs or inline code in markdown posted to issues, issue comments and PR descriptions #18829
Generated markdown in safe outputs gets heavily filtered/redacted. THere are good reasons for this
However one major problem is the redaction of <Abc> --> (Abc) in code blocks (inline and paragraph) in issue, issue comments, PR descriptions etc. This is too strong - it's OK to remove these in regular markdown but not formatted code.
If necessary we should try to use a good quality markdown parser to help guide this process - parse the markdown, then filter the actual text sections but be less aggressive on the code filtering.
Some code filtering should still stay in place e.g. URLs. It's just the <Abc> --> (Abc) that's too strong at the moment. But we should do an assessment of the filtering rules implemented, compare to what's documented, and decide
The issue is confirmed: sanitize_content_core.cjs applies XML/HTML filtering functions (removeXmlComments and convertXmlTags) as raw string operations across the entire markdown output — including code fences and inline code spans. This means generic type parameters like `List(String)` become `List(String)`, and `` style comments inside code blocks get silently removed. The fix is to parse markdown into an AST first and apply the aggressive filters only to prose text nodes, not code nodes. The unified/`remark` ecosystem (`@pelikhan`'s suggestion) is the right tool for this.
Root Cause Analysis
Current Sanitization Pipeline
In actions/setup/js/sanitize_content_core.cjs, the main sanitizeContentCore() function runs at lines 776–803 in this order, all against the raw string:
removeXmlComments(s) (line 322): Uses `` in a code block disappears silently.
convertXmlTags(s) (line 340): Uses /<(\/?[A-Za-z!][^>]*?)>/g globally — converts any (Tag) not on the allowed list to (Tag). Code blocks with generics like (T), (String), (int), (MyType) etc. are all hit. None of these are in the GFM allowlist.
Both functions have no awareness of markdown code regions.
Recommended Solution: AST-Aware Sanitization with unified/remark
Approach
Parse the markdown into an mdast AST, walk only the appropriate node types, apply filters selectively, then re-serialize.
import{unified}from'unified';importremarkParsefrom'remark-parse';importremarkStringifyfrom'remark-stringify';import{visit,SKIP}from'unist-util-visit';functionsanitizeMarkdownAware(content,opts){constprocessor=unified().use(remarkParse).use(()=>(tree)=>{// Apply aggressive XML/comment filters ONLY to prose text nodesvisit(tree,'text',(node)=>{node.value=removeXmlComments(node.value);node.value=convertXmlTags(node.value);node.value=neutralizeTemplateDelimiters(node.value);});// URL filtering applies to link/image URLs (structural), not textvisit(tree,['link','image'],(node)=>{node.url=sanitizeUrlProtocols(node.url);node.url=sanitizeUrlDomains(node.url,opts.allowedDomains);});// 'code' and 'inlineCode' nodes are intentionally skipped}).use(remarkStringify);returnString(processor.processSync(content));}
Node types to skip (code content):code (fenced blocks), inlineCode (backtick spans), html
Key Tools
Package
Purpose
unified + remark-parse
Parse markdown → mdast AST
unist-util-visit
Walk the AST, visit specific node types
remark-stringify / mdast-util-to-markdown
Re-serialize AST → markdown string
All are already part of the unified ecosystem; unified is already referenced in the comments in this repo.
Known Challenges to Address
Round-trip fidelity: remark-stringify may normalize some markdown formatting (fence style, list markers, trailing spaces). The output is semantically identical but may look slightly different. Evaluate whether this is acceptable or if a custom stringifier is needed.
neutralizeAllMentions and neutralizeBotTriggers: These currently operate on the raw string with lookaheads/lookbehinds to skip backtick-quoted mentions. In an AST approach, they would naturally only touch text nodes, which is cleaner — but the existing tests should be verified.
Raw HTML in markdown: The html node type in mdast represents raw embedded HTML. This currently gets processed by convertXmlTags. A policy decision is needed: should raw HTML in markdown be filtered (current behavior) or preserved?
URL filtering in text: URLs that appear as plain text (not as [text](url) links) may be parsed as text nodes rather than link nodes in some markdown flavors. The URL sanitizers need to continue handling these.
If AST round-tripping is deemed too risky for output fidelity, a lighter approach would be to split the input string into code and non-code regions first, apply filters only to non-code regions, and rejoin. The existing markdown_code_region_balancer.cjs already contains infrastructure for detecting code fences.
This is more brittle than proper AST parsing (edge cases around nested fences, escaped backticks) but avoids the serialization fidelity concern. However, given that balanceCodeRegions already rewrites the code fence structure, using the full AST approach is likely cleaner and more maintainable.
Recommendations
Use unified/remark-parse + unist-util-visit to make the sanitization AST-aware, as suggested by @pelikhan. This is the cleanest fix.
Apply removeXmlComments and convertXmlTags only to text nodes, skipping code and inlineCode node types entirely.
Refactor URL filtering to operate on link/image node .url properties rather than raw string regex, while keeping a text-level URL scanner for bare URLs.
Retain all current filters for non-code text — the security rationale for filtering (script) and similar tags in prose remains valid.
Write regression tests covering: generic type parameters in inline code (`List(T)`), generic types in code fences, HTML comments in code blocks, and bare URLs in both code and prose.
Key Sources
unist-util-visit — walk specific node types in the AST (supports SKIP to avoid descending into code nodes)
threat detection engine error
The threat detection engine encountered an error and could not complete analysis. This is a tooling failure, not a security finding.
Details
The threat detection engine failed to produce results.
Status (2026-10-07; Needs progress check): The issue reports that safe-output sanitization changes angle-bracketed text inside Markdown code, and a maintainer suggested unified on February 28 as a possible approach. No fix is verified in this discussion; the next step is to check current behavior and assess a code-aware change while retaining necessary URL filtering.
Current-state refresher (2026-10-16): apparently resolved for the reported angle-bracket corruption.#22005 merged on March 21. Current sanitization applies XML-comment removal and tag conversion only to non-code regions; fenced code and inline code retain angle brackets. Regression cases cover backtick/tilde fences, inline and multi-backtick spans, generic types, and XML comments inside versus outside code.
I also executed a focused local check against the current core sanitizer: inline List<T>, fenced Array<string> and a code comment were preserved, while a prose <Abc> tag was neutralized and an untrusted URL was filtered. Thus preserving code did not simply disable the remaining filters. This was a targeted reproduction check, not the full test suite or a live issue-posting workflow.
The October 7 refresher's lack of a verified fix is superseded by this implementation/merge evidence. Any remaining failure should be narrowed to a specific Markdown edge case.
Activity
dsyme commentedon Feb 28, 2026
/scout Please investigate this and get back to me
pelikhan commentedon Feb 28, 2026
/scout Please investigate this and get back to me
pelikhan commentedon Feb 28, 2026
we can probably use unified
github-actions commentedon Feb 28, 2026
🔍 Scout Research Report
Triggered by
@pelikhanExecutive Summary
The issue is confirmed:
sanitize_content_core.cjsapplies XML/HTML filtering functions (removeXmlCommentsandconvertXmlTags) as raw string operations across the entire markdown output — including code fences and inline code spans. This means generic type parameters like`List(String)`become`List(String)`, and `` style comments inside code blocks get silently removed. The fix is to parse markdown into an AST first and apply the aggressive filters only to prose text nodes, not code nodes. Theunified/`remark` ecosystem (`@pelikhan`'s suggestion) is the right tool for this.Root Cause Analysis
Current Sanitization Pipeline
In
actions/setup/js/sanitize_content_core.cjs, the mainsanitizeContentCore()function runs at lines 776–803 in this order, all against the raw string:The Two Problematic Functions
removeXmlComments(s)(line 322): Uses `` in a code block disappears silently.convertXmlTags(s)(line 340): Uses/<(\/?[A-Za-z!][^>]*?)>/gglobally — converts any(Tag)not on the allowed list to(Tag). Code blocks with generics like(T),(String),(int),(MyType)etc. are all hit. None of these are in the GFM allowlist.Both functions have no awareness of markdown code regions.
Recommended Solution: AST-Aware Sanitization with unified/remark
Approach
Parse the markdown into an mdast AST, walk only the appropriate node types, apply filters selectively, then re-serialize.
Node types to filter (prose text):
text,heading,paragraph,blockquote,list,listItemNode types to skip (code content):
code(fenced blocks),inlineCode(backtick spans),htmlKey Tools
unified+remark-parseunist-util-visitremark-stringify/mdast-util-to-markdownAll are already part of the unified ecosystem;
unifiedis already referenced in the comments in this repo.Known Challenges to Address
Round-trip fidelity:
remark-stringifymay normalize some markdown formatting (fence style, list markers, trailing spaces). The output is semantically identical but may look slightly different. Evaluate whether this is acceptable or if a custom stringifier is needed.neutralizeAllMentionsandneutralizeBotTriggers: These currently operate on the raw string with lookaheads/lookbehinds to skip backtick-quoted mentions. In an AST approach, they would naturally only touchtextnodes, which is cleaner — but the existing tests should be verified.Raw HTML in markdown: The
htmlnode type in mdast represents raw embedded HTML. This currently gets processed byconvertXmlTags. A policy decision is needed: should raw HTML in markdown be filtered (current behavior) or preserved?URL filtering in text: URLs that appear as plain text (not as
[text](url)links) may be parsed astextnodes rather thanlinknodes in some markdown flavors. The URL sanitizers need to continue handling these.Simpler Alternative: Code-Region-Aware String Splitting
If AST round-tripping is deemed too risky for output fidelity, a lighter approach would be to split the input string into code and non-code regions first, apply filters only to non-code regions, and rejoin. The existing
markdown_code_region_balancer.cjsalready contains infrastructure for detecting code fences.This is more brittle than proper AST parsing (edge cases around nested fences, escaped backticks) but avoids the serialization fidelity concern. However, given that
balanceCodeRegionsalready rewrites the code fence structure, using the full AST approach is likely cleaner and more maintainable.Recommendations
unified/remark-parse+unist-util-visitto make the sanitization AST-aware, as suggested by@pelikhan. This is the cleanest fix.removeXmlCommentsandconvertXmlTagsonly totextnodes, skippingcodeandinlineCodenode types entirely.link/imagenode.urlproperties rather than raw string regex, while keeping a text-level URL scanner for bare URLs.(script)and similar tags in prose remains valid.`List(T)`), generic types in code fences, HTML comments in code blocks, and bare URLs in both code and prose.Key Sources
unist-util-visit— walk specific node types in the AST (supportsSKIPto avoid descending into code nodes)mdast-util-to-markdown— serialize mdast back to markdownReferences: §22522220094
github-actions commentedon Jul 31, 2026
Warning
threat detection engine error
The threat detection engine encountered an error and could not complete analysis. This is a tooling failure, not a security finding.
Details
The threat detection engine failed to produce results.
Review the workflow run logs for details.
Assigning to
@pelikhan, the most active recent contributor to this repo, since this is the oldest open issue without an assignee.github-actions commentedon Aug 1, 2026
Assigning to
@pelikhan, the most recently active human contributor with merged PRs in this repo, as this is the oldest unassigned open issue.pelikhan commentedon Oct 7, 2026
Status (2026-10-07; Needs progress check): The issue reports that safe-output sanitization changes angle-bracketed text inside Markdown code, and a maintainer suggested
unifiedon February 28 as a possible approach. No fix is verified in this discussion; the next step is to check current behavior and assess a code-aware change while retaining necessary URL filtering.pelikhan commentedon Oct 16, 2026
Current-state refresher (2026-10-16): apparently resolved for the reported angle-bracket corruption. #22005 merged on March 21. Current sanitization applies XML-comment removal and tag conversion only to non-code regions; fenced code and inline code retain angle brackets. Regression cases cover backtick/tilde fences, inline and multi-backtick spans, generic types, and XML comments inside versus outside code.
I also executed a focused local check against the current core sanitizer: inline
List<T>, fencedArray<string>and a code comment were preserved, while a prose<Abc>tag was neutralized and an untrusted URL was filtered. Thus preserving code did not simply disable the remaining filters. This was a targeted reproduction check, not the full test suite or a live issue-posting workflow.The October 7 refresher's lack of a verified fix is superseded by this implementation/merge evidence. Any remaining failure should be narrowed to a specific Markdown edge case.