Skip to content

feat(safe-outputs): add allowed-events filter to submit-pull-request-review#25484

Merged
pelikhan merged 3 commits intomainfrom
copilot/allow-filtering-event-types
Apr 9, 2026
Merged

feat(safe-outputs): add allowed-events filter to submit-pull-request-review#25484
pelikhan merged 3 commits intomainfrom
copilot/allow-filtering-event-types

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 9, 2026

AI agents running as github-actions[bot] can submit APPROVE reviews that count toward branch protection requirements, bypassing human review gates. Prompt-level restrictions are a soft control vulnerable to injection or agent error.

Changes

  • Go struct + parser (submit_pr_review.go): Added AllowedEvents []string field; parses allowed-events from frontmatter, normalizing to uppercase and dropping invalid values. Fails closed: if allowed-events is present but not a list, or if all provided values are invalid, the config is rejected rather than falling back to allowing all events.
  • Compiler (compiler_safe_outputs_config.go): Passes allowed_events slice into handler config
  • JS handler (submit_pr_review.cjs): Enforces allowed_events set — rejects disallowed events without consuming the max count slot
  • Schema (main_workflow_schema.json): Added allowed-events property with enum [APPROVE, COMMENT, REQUEST_CHANGES] and minItems: 1 constraint
  • TypeScript types (safe-outputs-config.d.ts): Added "allowed-events"?: Array<"APPROVE" | "COMMENT" | "REQUEST_CHANGES">
  • Docs: Updated safe-outputs.md and frontmatter-full.md

Usage

safe-outputs:
  submit-pull-request-review:
    max: 1
    allowed-events: [COMMENT, REQUEST_CHANGES]  # infrastructure-level block on APPROVE

When allowed-events is omitted, all three event types remain allowed (backward compatible).

Copilot AI changed the title [WIP] Add filtering for allowed event types in submit-pull-request-review feat(safe-outputs): add allowed-events filter to submit-pull-request-review Apr 9, 2026
@pelikhan pelikhan marked this pull request as ready for review April 9, 2026 14:07
Copilot AI review requested due to automatic review settings April 9, 2026 14:07
Copy link
Copy Markdown
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

Adds an allowed-events allowlist to the submit-pull-request-review safe-output to prevent agent-submitted review events (notably APPROVE) from bypassing human review requirements.

Changes:

  • Extend Go safe-output config parsing to accept allowed-events and propagate it into handler config.
  • Enforce allowed_events at runtime in the JS submit_pr_review handler (blocked events don’t consume max).
  • Update schema, type definitions, tests, and docs to describe and validate the new option.
Show a summary per file
File Description
pkg/workflow/submit_pr_review.go Adds AllowedEvents to config and parses allowed-events from workflow frontmatter.
pkg/workflow/submit_pr_review_footer_test.go Adds unit tests for parsing/normalization/invalid filtering of allowed-events.
pkg/workflow/compiler_safe_outputs_config.go Emits allowed_events into JS handler configuration.
pkg/parser/schemas/main_workflow_schema.json Adds allowed-events to schema with enum validation.
docs/src/content/docs/reference/safe-outputs.md Documents allowed-events usage and intent.
docs/src/content/docs/reference/frontmatter-full.md Documents the new frontmatter field in the full reference.
actions/setup/js/types/safe-outputs-config.d.ts Adds TS type for allowed-events.
actions/setup/js/submit_pr_review.test.cjs Adds handler tests for allow/deny behavior and max-slot handling.
actions/setup/js/submit_pr_review.cjs Enforces allowed review event types via allowed_events.

Copilot's findings

Tip

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

  • Files reviewed: 8/9 changed files
  • Comments generated: 2

Comment on lines +79 to +91
if eventsSlice, ok := allowedEvents.([]any); ok {
validEvents := map[string]bool{"APPROVE": true, "COMMENT": true, "REQUEST_CHANGES": true}
for _, e := range eventsSlice {
if eventStr, ok := e.(string); ok {
upper := strings.ToUpper(eventStr)
if validEvents[upper] {
config.AllowedEvents = append(config.AllowedEvents, upper)
} else {
submitPRReviewLog.Printf("Ignoring invalid allowed-events value: %s", eventStr)
}
}
}
}
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

allowed-events currently fails open: if the key is present but all provided values are invalid/filtered out, AllowedEvents stays empty and the handler config omits allowed_events, which results in all review events being allowed. For a security control, this should fail closed (e.g., treat “allowed-events present but no valid values” as a configuration error, or explicitly encode an empty allowlist and have the JS handler interpret it as “deny all”).

Suggested change
if eventsSlice, ok := allowedEvents.([]any); ok {
validEvents := map[string]bool{"APPROVE": true, "COMMENT": true, "REQUEST_CHANGES": true}
for _, e := range eventsSlice {
if eventStr, ok := e.(string); ok {
upper := strings.ToUpper(eventStr)
if validEvents[upper] {
config.AllowedEvents = append(config.AllowedEvents, upper)
} else {
submitPRReviewLog.Printf("Ignoring invalid allowed-events value: %s", eventStr)
}
}
}
}
eventsSlice, ok := allowedEvents.([]any)
if !ok {
submitPRReviewLog.Printf("Invalid allowed-events configuration: must be a list of review event types")
return nil
}
validEvents := map[string]bool{"APPROVE": true, "COMMENT": true, "REQUEST_CHANGES": true}
for _, e := range eventsSlice {
if eventStr, ok := e.(string); ok {
upper := strings.ToUpper(eventStr)
if validEvents[upper] {
config.AllowedEvents = append(config.AllowedEvents, upper)
} else {
submitPRReviewLog.Printf("Ignoring invalid allowed-events value: %s", eventStr)
}
}
}
if len(config.AllowedEvents) == 0 {
submitPRReviewLog.Printf("Invalid allowed-events configuration: at least one valid event type is required when allowed-events is specified")
return nil
}

Copilot uses AI. Check for mistakes.
Comment on lines 461 to 466
AddIfNotEmpty("target", c.Target).
AddIfNotEmpty("target-repo", c.TargetRepoSlug).
AddStringSlice("allowed_repos", c.AllowedRepos).
AddStringSlice("allowed_events", c.AllowedEvents).
AddIfNotEmpty("github-token", c.GitHubToken).
AddStringPtr("footer", getEffectiveFooterString(c.Footer, cfg.Footer)).
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

There are JS + Go parse unit tests for allowed-events, but there’s no test asserting the compiler actually emits allowed_events into GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG for submit_pull_request_review. Add a focused test that sets SubmitPullRequestReview.AllowedEvents and verifies the generated handler config JSON contains the expected allowed_events array, to prevent regressions in the Go→JS config wiring.

Copilot uses AI. Check for mistakes.
@pelikhan
Copy link
Copy Markdown
Collaborator

pelikhan commented Apr 9, 2026

@copilot review comments

"description": "List of additional repositories in format 'owner/repo' that PR reviews can be submitted in. When specified, the agent can use a 'repo' field in the output to specify which repository to submit the review in. The target repository (current or target-repo) is always implicitly allowed."
},
"allowed-events": {
"type": "array",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@copilot add constraint for minimum 1

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added minItems: 1 to the allowed-events schema in commit 5b475a7. Also addressed the security reviewer's fail-closed feedback in the same commit: the parser now returns nil if allowed-events is present but not a list, or if all provided values are invalid (rather than silently falling back to allowing all events).

…a constraint, compiler test

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/f51da69c-737b-4d35-b3dc-c9ce3c172474

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
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.

submit-pull-request-review: allow filtering allowed event types (APPROVE, COMMENT, REQUEST_CHANGES)

3 participants