Skip to content

Comments

Skip HTML comment security checks - comments are stripped during compilation#16505

Closed
Copilot wants to merge 2 commits intomainfrom
copilot/disable-suspicious-content-checks
Closed

Skip HTML comment security checks - comments are stripped during compilation#16505
Copilot wants to merge 2 commits intomainfrom
copilot/disable-suspicious-content-checks

Conversation

Copy link
Contributor

Copilot AI commented Feb 18, 2026

Security scanner was rejecting workflows with documentation in HTML comments, even though these comments are removed by removeXMLComments() during compilation and never reach the final workflow.

Changes

  • Strip HTML/XML comments before security scanning in ScanMarkdownSecurity() by calling removeXMLComments() after frontmatter stripping
  • Remove redundant HTML comment checking from scanHiddenContent() since comments are now pre-stripped
  • Update tests to verify suspicious content in HTML comments is ignored while content outside comments is still caught

Example

This now passes security scanning:

---
engine: copilot
---

# Shared Configuration

<!--
**Usage:**
```yaml
imports:
  - shared/config.md

Contains URLs like http://example.com and code examples that previously
triggered security alerts but are stripped during compilation.
-->

Actual workflow content...


> [!WARNING]
>
> <details>
> <summary>Firewall rules blocked me from connecting to one or more addresses (expand for details)</summary>
>
> #### I tried to connect to the following addresses, but was blocked by firewall rules:
>
> - `https://api.github.com/graphql`
>   - Triggering command: `/usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) {
		repository(owner: $owner, name: $name) {
			hasDiscussionsEnabled
		}
	} -f owner=github -f name=gh-aw -c=4 -nolocalimports git comm�� rite &#39;../../../*--detach Skip HTML comment content in security scanning - comments are erased during compilation

Co-authrev-parse ache/node/24.13.0/x64/bin/bash` (http block)
> - `https://api.github.com/repos/actions/ai-inference/git/ref/tags/v1`
>   - Triggering command: `/usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq .object.sha -unreachable=false /tmp/go-build3285019064/b133/vet.cfg 64b5b38c59eecc403aa97ab81a6f1b227d95728ff18d6e8a-d -c=4 -nolocalimports -importcfg /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linupkg/workflow/engine_helpers_secrets_test.go -ato�� */*.json&#39; &#39;!../../../pkg/workflow/js/**/*.json&#39; --ignore-path ../../../.prettierignore t content in security scanning - comments are erased during compilation

Co-authored-by: pelikharev-parse 64/pkg/tool/linux_amd64/vet -errorsas -ifaceassert -nilfunc 64/pkg/tool/linux_amd64/vet` (http block)
> - `https://api.github.com/repos/actions/checkout/git/ref/tags/v3`
>   - Triggering command: `/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq .object.sha 5019064/b285/_pkg_.a --local sh ty_HiddenContentgit bracelet/lipglosrev-parse` (http block)
> - `https://api.github.com/repos/actions/checkout/git/ref/tags/v4`
>   - Triggering command: `/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v4 --jq .object.sha /tmp/go-build3285019064/b281/_pkg_.a -trimpath ules/.bin/sh -p n &lt;4175913&#43;pelikrev-parse -lang=go1.23 /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linu**/*.cjs -uns�� &#39;**/*.ts&#39; &#39;**/*.json&#39; --ignore-path ../../../.pr**/*.json /tmp/go-build3285019064/b051/vet.cfg ode -c=4 -nolocalimports -importcfg /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/vet` (http block)
>   - Triggering command: `/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v4 --jq .object.sha /tmp/go-build3285019064/b322/_pkg_.a -trimpath de/node/bin/sh -p golang.org/x/texrev-parse -lang=go1.24 /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linu**/*.cjs ogs.�� &#39;**/*.ts&#39; &#39;**/*.json&#39; --ignore-path ../../../.pr**/*.json /tmp/go-build3285019064/b054/vet.cfg h yAccounting=yes ota=5% yHigh=170M` (http block)
>   - Triggering command: `/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v4 --jq .object.sha husky` (http block)
> - `https://api.github.com/repos/actions/checkout/git/ref/tags/v5`
>   - Triggering command: `/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha ath ../../../.pr**/*.json .cfg 64/pkg/tool/linu../../../.prettierignore` (http block)
>   - Triggering command: `/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha *.json&#39; &#39;!../../../pkg/workflow/js/**/*.json&#39; --ignore-path ../../../.prettierignore -buildtags ache/go/1.25.0/x64/pkg/tool/linux_amd64/compile -errorsas -ifaceassert -nilfunc ache/go/1.25.0/x64/pkg/tool/linux_amd64/compile -###�� -x c k/gh-aw/gh-aw/actions/node_modules/.bin/node -` (http block)
>   - Triggering command: `/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha --no-audit --include=dev /opt/hostedtoolcache/go/1.25.0/x64/bin/node --include=optiongit --no-package-locrev-parse --no-dry-run node /hom�� --write **/*.cjs /home/REDACTED/work/gh-aw/gh-aw/node_modules/.bin/node **/*.json --ignore-path ../../../.pretti--show-toplevel node` (http block)
> - `https://api.github.com/repos/actions/github-script/git/ref/tags/v8`
>   - Triggering command: `/usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha 5019064/b001/_pkg_.a -trimpath 5019064/b001=&gt; -p github.com/githurev-parse -lang=go1.25 /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linu**/*.cjs -uns�� &#39;**/*.ts&#39; &#39;**/*.json&#39; --ignore-path ../../../.pr**/*.json /tmp/go-build3285019064/b057/vet.cfg 0/x64/bin/node -c=4 -nolocalimports -importcfg /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linu../../../**/*.json` (http block)
>   - Triggering command: `/usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha /tmp/go-build3285019064/b292/_pkg_.a -trimpath d-run -p github.com/goccyrev-parse -lang=go1.21 /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linuscripts/**/*.js ogs.�� &#39;**/*.ts&#39; &#39;**/*.json&#39; --ignore-path ../../../.pr.prettierignore /tmp/go-build3285019064/b079/vet.cfg counting=yes yAccounting=yes ota=5% yHigh=170M` (http block)
>   - Triggering command: `/usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha husky` (http block)
> - `https://api.github.com/repos/actions/setup-go/git/ref/tags/v4`
>   - Triggering command: `/usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq .object.sha 5019064/b339/_pkg_.a -trimpath ash -p b/gh-aw/pkg/workrev-parse -lang=go1.25 /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linu**/*.cjs -uns�� &#39;**/*.ts&#39; &#39;**/*.json&#39; --ignore-path ../../../.pr**/*.json /tmp/go-build3285019064/b068/vet.cfg rgo/bin/sh -c=4 -nolocalimports -importcfg 5019064/b339/importcfg` (http block)
> - `https://api.github.com/repos/actions/setup-node/git/ref/tags/v4`
>   - Triggering command: `/usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq .object.sha /tmp/go-build3285019064/b283/_pkg_.a -trimpath h -p github.com/charmrev-parse -lang=go1.24 /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linu**/*.cjs -uns�� &#39;**/*.ts&#39; &#39;**/*.json&#39; --ignore-path ../../../.pr**/*.json /tmp/go-build3285019064/b059/vet.cfg cal/bin/sh -c=4 -nolocalimports -importcfg /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/vet` (http block)
> - `https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.0.0`
>   - Triggering command: `/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq .object.sha g_.a` (http block)
>
> If you need me to access, download, or install something from one of these locations, you can either:
>
> - Configure [Actions setup steps](https://gh.io/copilot/actions-setup-steps) to set up my environment, which run before the firewall is enabled
> - Add the appropriate URLs or hosts to the custom allowlist in this repository's [Copilot coding agent settings](https://github.com/github/gh-aw/settings/copilot/coding_agent) (admins only)
>
> </details>

<!-- START COPILOT CODING AGENT TIPS -->
---

✨ Let Copilot coding agent [set things up for you](https://github.com/github/gh-aw/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo.

…during compilation

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Disable checks for suspicious content in XML comments Skip HTML comment security checks - comments are stripped during compilation Feb 18, 2026
Copilot AI requested a review from pelikhan February 18, 2026 02:26
@pelikhan pelikhan marked this pull request as ready for review February 18, 2026 02:29
Copilot AI review requested due to automatic review settings February 18, 2026 02:29
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adjusts the markdown security scanner to ignore HTML/XML comments that are stripped during workflow compilation, reducing false positives for documentation content.

Changes:

  • Strip HTML/XML comments in ScanMarkdownSecurity() after frontmatter removal (via removeXMLComments()).
  • Remove the redundant HTML-comment payload detection from scanHiddenContent().
  • Update tests to expect no findings when suspicious content appears only inside HTML comments.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
pkg/workflow/markdown_security_scanner.go Strips XML comments prior to scanning and removes in-scanner HTML comment checks.
pkg/workflow/markdown_security_scanner_test.go Updates expectations so suspicious content inside HTML comments is ignored.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +81 to 85
// 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 {
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ScanMarkdownSecurity now strips XML/HTML comments via removeXMLComments, but line-number adjustment still only accounts for stripped frontmatter. removeXMLComments can drop lines for multi-line comments (see xml_comments.go: it continues for lines fully inside a comment), which will shift subsequent line numbers and make findings point at the wrong place in the original file.

Consider either (a) making the comment-stripping step preserve the original newline count (replace removed comment lines with empty lines), or (b) tracking a line mapping/offset introduced by comment stripping and applying it to all findings. If you keep stripping comments here, adding a regression test for line numbers after a multi-line HTML comment would help prevent future drift.

Copilot uses AI. Check for mistakes.
Comment on lines 269 to 273
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
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After removing the HTML-comment scanning logic from scanHiddenContent, the related regex/helpers (htmlCommentPattern, suspiciousCommentWordPatterns, and containsSuspiciousCommentContent) are no longer referenced anywhere in the package. Keeping them (and their comments) around makes the hidden-content implementation harder to understand and can mislead future changes.

Recommend deleting the unused pattern/helpers (or repurposing them elsewhere if still needed) so the remaining hidden-content checks reflect the new behavior (CSS hiding + entity obfuscation only).

Copilot uses AI. Check for mistakes.
@pelikhan pelikhan closed this Feb 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants