Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/dev-hawk.lock.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .github/workflows/dev-hawk.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
types:
- completed
branches:
- 'copilot/**'
- 'copilot/*'
if: ${{ github.event.workflow_run.event == 'workflow_dispatch' }}
permissions:
contents: read
Expand Down
34 changes: 0 additions & 34 deletions docs/src/content/docs/reference/frontmatter-full.md
Original file line number Diff line number Diff line change
Expand Up @@ -1239,7 +1239,6 @@ safe-outputs:
# (optional)
max: 1


# Target repository in format 'owner/repo' for cross-repository issue creation.
# Takes precedence over trial target repo settings.
# (optional)
Expand Down Expand Up @@ -1269,10 +1268,6 @@ safe-outputs:
# (optional)
max: 1

# Minimum number of agent tasks to create (default: 0 - no requirement)
# (optional)
min: 1

# Target repository in format 'owner/repo' for cross-repository agent task
# creation. Takes precedence over trial target repo settings.
# (optional)
Expand Down Expand Up @@ -1313,10 +1308,6 @@ safe-outputs:
# (optional)
max: 1

# Minimum number of discussions to create (default: 0 - no requirement)
# (optional)
min: 1

# Target repository in format 'owner/repo' for cross-repository discussion
# creation. Takes precedence over trial target repo settings.
# (optional)
Expand All @@ -1340,10 +1331,6 @@ safe-outputs:
# (optional)
max: 1

# Minimum number of comments to create (default: 0 - no requirement)
# (optional)
min: 1

# Target for comments: 'triggering' (default), '*' (any issue), or explicit issue
# number
# (optional)
Expand Down Expand Up @@ -1431,10 +1418,6 @@ safe-outputs:
# (optional)
max: 1

# Minimum number of review comments to create (default: 0 - no requirement)
# (optional)
min: 1

# Side of the diff for comments: 'LEFT' or 'RIGHT' (default: 'RIGHT')
# (optional)
side: "LEFT"
Expand Down Expand Up @@ -1467,10 +1450,6 @@ safe-outputs:
# (optional)
max: 1

# Minimum number of security findings to include (default: 0 - no requirement)
# (optional)
min: 1

# Driver name for SARIF tool.driver.name field (default: 'GitHub Agentic Workflows
# Security Scanner')
# (optional)
Expand Down Expand Up @@ -1504,10 +1483,6 @@ safe-outputs:
# (optional)
max: 1

# Minimum number of labels to add (default: 0 - no requirement)
# (optional)
min: 1

# Target for labels: 'triggering' (default), '*' (any issue/PR), or explicit
# issue/PR number
# (optional)
Expand Down Expand Up @@ -1550,10 +1525,6 @@ safe-outputs:
# (optional)
max: 1

# Minimum number of issues to update (default: 0 - no requirement)
# (optional)
min: 1

# Target repository in format 'owner/repo' for cross-repository issue updates.
# Takes precedence over trial target repo settings.
# (optional)
Expand Down Expand Up @@ -1621,10 +1592,6 @@ safe-outputs:
# (optional)
max: 1

# Minimum number of missing tool reports (default: 0 - no requirement)
# (optional)
min: 1

# GitHub token to use for this specific output type. Overrides global github-token
# if specified.
# (optional)
Expand Down Expand Up @@ -1659,7 +1626,6 @@ safe-outputs:
# (optional)
max: 1


# GitHub token to use for this specific output type. Overrides global github-token
# if specified.
# (optional)
Expand Down
5 changes: 4 additions & 1 deletion docs/src/content/docs/status.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ Browse the [workflow source files](https://github.com/githubnext/gh-aw/tree/main
| [Basic Research Agent](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/research.md) | copilot | [![Basic Research Agent](https://github.com/githubnext/gh-aw/actions/workflows/research.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/research.lock.yml) | - | - |
| [Blog Auditor](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/blog-auditor.md) | claude | [![Blog Auditor](https://github.com/githubnext/gh-aw/actions/workflows/blog-auditor.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/blog-auditor.lock.yml) | `0 12 * * 3` | - |
| [Brave Web Search Agent](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/brave.md) | copilot | [![Brave Web Search Agent](https://github.com/githubnext/gh-aw/actions/workflows/brave.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/brave.lock.yml) | - | `/brave` |
| [Changeset Generator](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/changeset-generator.firewall.md) | copilot | [![Changeset Generator](https://github.com/githubnext/gh-aw/actions/workflows/changeset-generator.firewall.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/changeset-generator.firewall.lock.yml) | - | - |
| [Changeset Generator](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/changeset.md) | copilot | [![Changeset Generator](https://github.com/githubnext/gh-aw/actions/workflows/changeset.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/changeset.lock.yml) | - | - |
| [CI Failure Doctor](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/ci-doctor.md) | copilot | [![CI Failure Doctor](https://github.com/githubnext/gh-aw/actions/workflows/ci-doctor.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/ci-doctor.lock.yml) | - | - |
| [CLI Version Checker](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/cli-version-checker.md) | copilot | [![CLI Version Checker](https://github.com/githubnext/gh-aw/actions/workflows/cli-version-checker.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/cli-version-checker.lock.yml) | `0 15 * * *` | - |
| [Commit Changes Analyzer](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/commit-changes-analyzer.md) | claude | [![Commit Changes Analyzer](https://github.com/githubnext/gh-aw/actions/workflows/commit-changes-analyzer.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/commit-changes-analyzer.lock.yml) | - | - |
| [Copilot Agent PR Analysis](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/copilot-agent-analysis.md) | claude | [![Copilot Agent PR Analysis](https://github.com/githubnext/gh-aw/actions/workflows/copilot-agent-analysis.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/copilot-agent-analysis.lock.yml) | `0 18 * * *` | - |
| [Copilot Agent Prompt Clustering Analysis](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/prompt-clustering-analysis.md) | claude | [![Copilot Agent Prompt Clustering Analysis](https://github.com/githubnext/gh-aw/actions/workflows/prompt-clustering-analysis.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/prompt-clustering-analysis.lock.yml) | `0 19 * * *` | - |
| [Copilot PR Prompt Pattern Analysis](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/copilot-pr-prompt-analysis.md) | copilot | [![Copilot PR Prompt Pattern Analysis](https://github.com/githubnext/gh-aw/actions/workflows/copilot-pr-prompt-analysis.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/copilot-pr-prompt-analysis.lock.yml) | `0 9 * * *` | - |
| [Copilot Session Insights](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/copilot-session-insights.md) | claude | [![Copilot Session Insights](https://github.com/githubnext/gh-aw/actions/workflows/copilot-session-insights.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/copilot-session-insights.lock.yml) | `0 16 * * *` | - |
| [Daily Documentation Updater](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/daily-doc-updater.md) | claude | [![Daily Documentation Updater](https://github.com/githubnext/gh-aw/actions/workflows/daily-doc-updater.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/daily-doc-updater.lock.yml) | `0 6 * * *` | - |
| [Daily Firewall Logs Collector and Reporter](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/daily-firewall-report.md) | copilot | [![Daily Firewall Logs Collector and Reporter](https://github.com/githubnext/gh-aw/actions/workflows/daily-firewall-report.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/daily-firewall-report.lock.yml) | `0 10 * * *` | - |
| [Daily News](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/daily-news.md) | copilot | [![Daily News](https://github.com/githubnext/gh-aw/actions/workflows/daily-news.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/daily-news.lock.yml) | `0 9 * * 1-5` | - |
Expand All @@ -47,6 +48,7 @@ Browse the [workflow source files](https://github.com/githubnext/gh-aw/tree/main
| [Mergefest](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/mergefest.md) | copilot | [![Mergefest](https://github.com/githubnext/gh-aw/actions/workflows/mergefest.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/mergefest.lock.yml) | - | `/mergefest` |
| [Plan Command](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/plan.md) | copilot | [![Plan Command](https://github.com/githubnext/gh-aw/actions/workflows/plan.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/plan.lock.yml) | - | `/plan` |
| [Poem Bot - A Creative Agentic Workflow](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/poem-bot.md) | copilot | [![Poem Bot - A Creative Agentic Workflow](https://github.com/githubnext/gh-aw/actions/workflows/poem-bot.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/poem-bot.lock.yml) | - | `/poem` |
| [Python Data Visualization Generator](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/python-data-charts.md) | copilot | [![Python Data Visualization Generator](https://github.com/githubnext/gh-aw/actions/workflows/python-data-charts.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/python-data-charts.lock.yml) | - | - |
| [Q](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/q.md) | copilot | [![Q](https://github.com/githubnext/gh-aw/actions/workflows/q.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/q.lock.yml) | - | `/q` |
| [Repository Tree Map Generator](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/repo-tree-map.md) | copilot | [![Repository Tree Map Generator](https://github.com/githubnext/gh-aw/actions/workflows/repo-tree-map.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/repo-tree-map.lock.yml) | - | - |
| [Resource Summarizer Agent](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/pdf-summary.md) | copilot | [![Resource Summarizer Agent](https://github.com/githubnext/gh-aw/actions/workflows/pdf-summary.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/pdf-summary.lock.yml) | - | `/summarize` |
Expand All @@ -67,6 +69,7 @@ Browse the [workflow source files](https://github.com/githubnext/gh-aw/tree/main
| [Test Post-Steps Workflow](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/test-post-steps.md) | copilot | [![Test Post-Steps Workflow](https://github.com/githubnext/gh-aw/actions/workflows/test-post-steps.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/test-post-steps.lock.yml) | - | - |
| [Test Secret Masking Workflow](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/test-secret-masking.md) | copilot | [![Test Secret Masking Workflow](https://github.com/githubnext/gh-aw/actions/workflows/test-secret-masking.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/test-secret-masking.lock.yml) | - | - |
| [Test Svelte MCP](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/test-svelte.md) | copilot | [![Test Svelte MCP](https://github.com/githubnext/gh-aw/actions/workflows/test-svelte.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/test-svelte.lock.yml) | - | - |
| [Test Workflow Timestamp Check](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/test-timestamp-js.md) | copilot | [![Test Workflow Timestamp Check](https://github.com/githubnext/gh-aw/actions/workflows/test-timestamp-js.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/test-timestamp-js.lock.yml) | - | - |
| [The Daily Repository Chronicle](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/daily-repo-chronicle.md) | copilot | [![The Daily Repository Chronicle](https://github.com/githubnext/gh-aw/actions/workflows/daily-repo-chronicle.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/daily-repo-chronicle.lock.yml) | `0 16 * * 1-5` | - |
| [Tidy](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/tidy.md) | copilot | [![Tidy](https://github.com/githubnext/gh-aw/actions/workflows/tidy.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/tidy.lock.yml) | - | - |
| [Video Analysis Agent](https://github.com/githubnext/gh-aw/blob/main/.github/workflows/video-analyzer.md) | copilot | [![Video Analysis Agent](https://github.com/githubnext/gh-aw/actions/workflows/video-analyzer.lock.yml/badge.svg)](https://github.com/githubnext/gh-aw/actions/workflows/video-analyzer.lock.yml) | - | - |
Expand Down
6 changes: 6 additions & 0 deletions pkg/workflow/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,12 @@ func (c *Compiler) CompileWorkflowData(workflowData *WorkflowData, markdownPath
return err
}

// Validate workflow_run triggers have branch restrictions
log.Printf("Validating workflow_run triggers for branch restrictions")
if err := c.validateWorkflowRunBranches(workflowData, markdownPath); err != nil {
return err
}

// Validate permissions against GitHub MCP toolsets
log.Printf("Validating permissions for GitHub MCP toolsets")
if githubTool, hasGitHub := workflowData.Tools["github"]; hasGitHub {
Expand Down
97 changes: 97 additions & 0 deletions pkg/workflow/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -683,3 +683,100 @@ func (c *Compiler) validateAgentFile(workflowData *WorkflowData, markdownPath st

return nil
}

// validateWorkflowRunBranches validates that workflow_run triggers include branch restrictions
// This is a security best practice to avoid running on all branches
func (c *Compiler) validateWorkflowRunBranches(workflowData *WorkflowData, markdownPath string) error {
if workflowData.On == "" {
return nil
}

validationLog.Print("Validating workflow_run triggers for branch restrictions")

// Parse the On field as YAML to check for workflow_run
// The On field is a YAML string that starts with "on:" key
var parsedData map[string]any
if err := yaml.Unmarshal([]byte(workflowData.On), &parsedData); err != nil {
// If we can't parse the YAML, skip this validation
validationLog.Printf("Could not parse On field as YAML: %v", err)
return nil
}

// Extract the actual "on" section from the parsed data
onData, hasOn := parsedData["on"]
if !hasOn {
// No "on" key found, skip validation
return nil
}

onMap, isMap := onData.(map[string]any)
if !isMap {
// "on" is not a map, skip validation
return nil
}

// Check if workflow_run is present
workflowRunVal, hasWorkflowRun := onMap["workflow_run"]
if !hasWorkflowRun {
// No workflow_run trigger, no validation needed
return nil
}

// Check if workflow_run has branches field
workflowRunMap, isMap := workflowRunVal.(map[string]any)
if !isMap {
// workflow_run is not a map (unusual), skip validation
return nil
}

_, hasBranches := workflowRunMap["branches"]
if hasBranches {
// Has branch restrictions, validation passed
if c.verbose {
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("✓ workflow_run trigger has branch restrictions"))
}
return nil
Comment on lines +732 to +738
Copy link

Copilot AI Nov 1, 2025

Choose a reason for hiding this comment

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

The validation incorrectly passes when the branches field exists but is empty. According to test case "workflow_run with empty branches array", an empty branches array (branches: []) should NOT trigger a warning, but the current logic treats it as valid branch restrictions. The check should verify that branches not only exists but also contains at least one branch pattern, or explicitly handle empty arrays as a special case if they're intentionally allowed.

Suggested change
_, hasBranches := workflowRunMap["branches"]
if hasBranches {
// Has branch restrictions, validation passed
if c.verbose {
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("✓ workflow_run trigger has branch restrictions"))
}
return nil
branchesVal, hasBranches := workflowRunMap["branches"]
if hasBranches {
// Check that branches is a non-empty array
if branchesSlice, ok := branchesVal.([]any); ok && len(branchesSlice) > 0 {
// Has branch restrictions, validation passed
if c.verbose {
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("✓ workflow_run trigger has branch restrictions"))
}
return nil
}
// branches exists but is empty or not an array, treat as missing restrictions

Copilot uses AI. Check for mistakes.
}

// workflow_run without branches - this is a warning or error depending on mode
message := "workflow_run trigger should include branch restrictions for security and performance.\n\n" +
"Without branch restrictions, the workflow will run for workflow runs on ALL branches,\n" +
"which can cause unexpected behavior and security issues.\n\n" +
"Suggested fix: Add branch restrictions to your workflow_run trigger:\n" +
"on:\n" +
" workflow_run:\n" +
" workflows: [\"your-workflow\"]\n" +
" types: [completed]\n" +
" branches:\n" +
" - main\n" +
" - develop"

if c.strictMode {
// In strict mode, this is an error
formattedErr := console.FormatError(console.CompilerError{
Position: console.ErrorPosition{
File: markdownPath,
Line: 1,
Column: 1,
},
Type: "error",
Message: message,
})
return errors.New(formattedErr)
}

// In normal mode, this is a warning
formattedWarning := console.FormatError(console.CompilerError{
Position: console.ErrorPosition{
File: markdownPath,
Line: 1,
Column: 1,
},
Type: "warning",
Message: message,
})
fmt.Fprintln(os.Stderr, formattedWarning)
c.IncrementWarningCount()

return nil
}
Loading
Loading