From 01fdec92af11e52d7a4cf7acc91533be88d3f596 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Feb 2026 02:19:03 +0000 Subject: [PATCH 1/2] Initial plan From d6e9683d61e2056a78dd2b7ce3a5301b16f0bcde Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Feb 2026 02:24:06 +0000 Subject: [PATCH 2/2] Skip HTML comment content in security scanning - comments are erased during compilation Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/workflow/markdown_security_scanner.go | 32 ++++++------------- .../markdown_security_scanner_test.go | 8 +++-- 2 files changed, 15 insertions(+), 25 deletions(-) diff --git a/pkg/workflow/markdown_security_scanner.go b/pkg/workflow/markdown_security_scanner.go index 97b9d4b290..96dcef1bdf 100644 --- a/pkg/workflow/markdown_security_scanner.go +++ b/pkg/workflow/markdown_security_scanner.go @@ -78,10 +78,10 @@ func countCategories(findings []SecurityFinding) int { } // ScanMarkdownSecurity scans markdown content for dangerous or malicious patterns. -// It automatically strips YAML frontmatter (delimited by ---) so that only the -// markdown body is scanned. Line numbers in returned findings are adjusted to -// match the original file. Returns a list of findings. If non-empty, the content -// should be rejected. +// It automatically strips YAML frontmatter (delimited by ---) and HTML/XML comments +// so that only the active markdown content is scanned. Line numbers in returned findings +// are adjusted to match the original file. Returns a list of findings. If non-empty, +// the content should be rejected. func ScanMarkdownSecurity(content string) []SecurityFinding { markdownSecurityLog.Printf("Scanning markdown content (%d bytes) for security issues", len(content)) @@ -89,6 +89,12 @@ func ScanMarkdownSecurity(content string) []SecurityFinding { markdownBody, lineOffset := stripFrontmatter(content) markdownSecurityLog.Printf("Stripped frontmatter: %d line(s) removed, scanning %d bytes of markdown", lineOffset, len(markdownBody)) + // Strip HTML/XML comments since they are removed during workflow compilation anyway + // (see removeXMLComments in xml_comments.go). This prevents false positives from + // documentation comments and avoids flagging content that won't be in the final workflow. + markdownBody = removeXMLComments(markdownBody) + markdownSecurityLog.Printf("Stripped XML comments, scanning %d bytes of markdown after comment removal", len(markdownBody)) + var findings []SecurityFinding markdownSecurityLog.Print("Running unicode abuse detection") @@ -264,24 +270,6 @@ func scanHiddenContent(content string) []SecurityFinding { var findings []SecurityFinding lines := strings.Split(content, "\n") - // Check for HTML comments containing suspicious content - matches := htmlCommentPattern.FindAllStringSubmatchIndex(content, -1) - for _, match := range matches { - commentBody := content[match[2]:match[3]] - commentLine := lineNumberAt(content, match[0]) - - // Flag comments that contain code-like content, URLs, or suspicious keywords - lowerComment := strings.ToLower(commentBody) - if containsSuspiciousCommentContent(lowerComment) { - findings = append(findings, SecurityFinding{ - Category: CategoryHiddenContent, - Description: "HTML comment contains suspicious content (code, URLs, or executable instructions)", - Line: commentLine, - Snippet: truncateSnippet(strings.TrimSpace(commentBody), 80), - }) - } - } - // Check for CSS-hidden elements for lineNum, line := range lines { lineNo := lineNum + 1 diff --git a/pkg/workflow/markdown_security_scanner_test.go b/pkg/workflow/markdown_security_scanner_test.go index 25280003eb..75ad2ca224 100644 --- a/pkg/workflow/markdown_security_scanner_test.go +++ b/pkg/workflow/markdown_security_scanner_test.go @@ -147,8 +147,9 @@ func TestScanMarkdownSecurity_HiddenContent_SuspiciousHTMLComments(t *testing.T) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { findings := ScanMarkdownSecurity(tt.content) - require.NotEmpty(t, findings, "should detect suspicious HTML comment") - assert.Equal(t, CategoryHiddenContent, findings[0].Category, "category should be hidden-content") + // HTML comments are removed during workflow compilation (see xml_comments.go), + // so suspicious content in comments won't make it to the final workflow + assert.Empty(t, findings, "should not flag HTML comments since they are removed during compilation") }) } } @@ -876,7 +877,8 @@ func TestScanMarkdownSecurity_RealisticAttack_HiddenPromptInjection(t *testing.T // Hidden prompt injection in a comment content := "# Good Workflow\n\n\n\nDo normal analysis." findings := ScanMarkdownSecurity(content) - require.NotEmpty(t, findings, "should detect hidden prompt injection in comment") + // HTML comments are removed during workflow compilation, so this should not be flagged + assert.Empty(t, findings, "should not flag prompt injection in HTML comments since they are removed during compilation") } func TestScanMarkdownSecurity_RealisticAttack_ClickjackingForm(t *testing.T) {