Repository navigation
Enforce configured targets in safe-output handlers - #62447
Conversation
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
@copilot update safe-outputs specification and specification enforcing scripts |
|
Great work on this security boundary hardening! 🎯 The safe-output target enforcement refactor looks solid — consistent application of target validation across merge, comment, close, review, assignment, milestone, and issue-field handlers, plus rigorous boundary checks for cross-repository and review-thread operations. The changes are well-focused (35 files covering a single concern), comprehensive, and include test coverage. This is ready for review by the maintainers. Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
To allow these domains, add them to the network:
allowed:
- defaults
- "github.com"See Network Configuration for more information.
|
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Target enforcement still has parent-type, forwarded-context, effective sub-issue, and PR-assignment correctness gaps.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 1
Open (5)
Match triggering target by parent kind, not just repository and ID · New Skip ignored ID exclusivity checks for fixed and triggering targets · New Validate effective target parent and sub-issue pair · New Resolve forwarded invocation context before triggering PR validation · New Allow unassign-from-user to target pull requests · New
What changed in this PR
Enforces configured safe-output targets before model-provided IDs and strengthens comment, review-thread, and sub-issue boundaries.
Changes:
- Applies target resolution consistently across issue and pull-request handlers.
- Adds parent/repository validation for comments, review threads, and sub-issues.
- Expands compiler validation and regression coverage.
| File | Description |
|---|---|
pkg/workflow/safe_outputs_validation.go |
Expands target validation. |
pkg/workflow/safe_outputs_target_validation_test.go |
Tests added validators. |
pkg/workflow/safe_outputs_handler_registry_issues.go |
Propagates sub-issue target. |
pkg/workflow/link_sub_issue_handler_config_test.go |
Tests target propagation. |
actions/setup/js/unassign_from_user.test.cjs |
Updates target tests. |
actions/setup/js/unassign_from_user.cjs |
Enforces assignment target. |
actions/setup/js/set_issue_type.test.cjs |
Updates target scenarios. |
actions/setup/js/set_issue_type.cjs |
Enforces issue-type target. |
actions/setup/js/set_issue_field.test.cjs |
Updates target scenarios. |
actions/setup/js/set_issue_field.cjs |
Enforces issue-field target. |
actions/setup/js/safe_output_helpers.cjs |
Clarifies target API documentation. |
actions/setup/js/resolve_pr_review_thread.test.cjs |
Tests thread boundaries. |
actions/setup/js/resolve_pr_review_thread.cjs |
Enforces review-thread targets. |
actions/setup/js/merge_pull_request.test.cjs |
Updates merge target setup. |
actions/setup/js/merge_pull_request.cjs |
Enforces merge target. |
actions/setup/js/mark_pull_request_as_ready_for_review.test.cjs |
Updates ready-for-review tests. |
actions/setup/js/mark_pull_request_as_ready_for_review.cjs |
Enforces PR target. |
actions/setup/js/link_sub_issue.test.cjs |
Tests sub-issue targeting. |
actions/setup/js/link_sub_issue.cjs |
Targets parent issue. |
actions/setup/js/hide_comment.test.cjs |
Tests parent lookup behavior. |
actions/setup/js/hide_comment.cjs |
Validates comment parent. |
actions/setup/js/close_pull_request.test.cjs |
Updates close-PR tests. |
actions/setup/js/close_pull_request.cjs |
Enforces close-PR target. |
actions/setup/js/close_issue.test.cjs |
Updates close-issue tests. |
actions/setup/js/close_issue.cjs |
Enforces close-issue target. |
actions/setup/js/assign_to_user.test.cjs |
Updates assignment tests. |
actions/setup/js/assign_to_user.cjs |
Enforces assignee target. |
actions/setup/js/assign_to_agent.test.cjs |
Updates agent target tests. |
actions/setup/js/assign_to_agent.cjs |
Enforces agent target. |
actions/setup/js/assign_milestone.test.cjs |
Updates milestone tests. |
actions/setup/js/assign_milestone.cjs |
Enforces milestone target. |
actions/setup/js/add_reviewer.test.cjs |
Updates reviewer tests. |
actions/setup/js/add_reviewer.cjs |
Enforces reviewer target. |
actions/setup/js/add_comment.test.cjs |
Updates comment target tests. |
actions/setup/js/add_comment.cjs |
Enforces comment target. |
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
| let expectedNumber; | ||
| if (targetConfig === "triggering") { | ||
| const invocationContext = resolveInvocationContext(context); | ||
| expectedNumber = invocationContext.eventPayload?.issue?.number ?? invocationContext.eventPayload?.pull_request?.number ?? invocationContext.eventPayload?.discussion?.number; |
There was a problem hiding this comment.
Fixed in de83120: resolveCommentNodeId() now tracks the resolved parent's kind ("issue" or "discussion") alongside its number, and the target: "triggering" check rejects mismatches between the two independent numbering sequences.
| // Defer if issue_number is a temporary ID that hasn't been resolved yet | ||
| // Strip leading '#' so both 'aw_abc1' and '#aw_abc1' (canonical validator form) are handled | ||
| if (message.issue_number != null) { | ||
| if (targetConfig === "*" && message.issue_number != null) { |
There was a problem hiding this comment.
Fixed in de83120: the issue_number/pull_number mutual-exclusivity check now only runs when targetConfig === "*".
| const subIssueNumber = subResolved.resolved?.number; | ||
| const parentTarget = resolveTarget({ | ||
| targetConfig, | ||
| item: targetItem, | ||
| context, | ||
| itemType: HANDLER_TYPE, | ||
| supportsIssue: true, | ||
| }); | ||
| if (!parentTarget.success) { | ||
| return { | ||
| parent_issue_number: item.parent_issue_number, | ||
| sub_issue_number: item.sub_issue_number, | ||
| success: false, | ||
| error: parentTarget.error, | ||
| }; | ||
| } | ||
| const parentIssueNumber = parentTarget.number; |
There was a problem hiding this comment.
Fixed in de83120: added a post-target-resolution check that rejects when the effective parent/sub-issue numbers are equal, instead of only validating the raw model-provided parent.
| if (resolveTarget === "triggering") { | ||
| if (!triggeringPRNumber) { | ||
| core.warning("Cannot resolve review thread: not running in a pull request context"); | ||
| return { | ||
| success: false, | ||
| error: repoValidation.error, | ||
| error: "Cannot resolve review threads outside of a pull request context", |
There was a problem hiding this comment.
Fixed in de83120: triggeringPRNumber is now derived from resolveInvocationContext(context).eventPayload so forwarded invocations (workflow_dispatch/aw_context, repository_dispatch) are correctly recognized.
| item: unassignItem, | ||
| context, | ||
| itemType: HANDLER_TYPE, | ||
| supportsIssue: true, |
There was a problem hiding this comment.
Fixed in de83120: switched to the helper's both-issue-and-PR mode (supportsPR: true) so the default target continues to work for triggering PRs.
|
Please address the open review follow-ups below, refresh the branch if needed, and then run the Open review follow-ups (newest first):
I also requested a branch refresh for this PR.
|
| let expectedNumber; | ||
| if (targetConfig === "triggering") { | ||
| const invocationContext = resolveInvocationContext(context); | ||
| expectedNumber = invocationContext.eventPayload?.issue?.number ?? invocationContext.eventPayload?.pull_request?.number ?? invocationContext.eventPayload?.discussion?.number; | ||
| if (!expectedNumber) { | ||
| return { | ||
| success: false, | ||
| error: 'Target is "triggering" but not running in issue, pull request, or discussion context', | ||
| }; | ||
| } | ||
| } else if (targetConfig !== "*") { | ||
| expectedNumber = Number(targetConfig); | ||
| if (!Number.isInteger(expectedNumber) || expectedNumber <= 0) { | ||
| return { | ||
| success: false, | ||
| error: `Invalid target configuration: ${targetConfig}`, | ||
| }; | ||
| } | ||
| } | ||
| if (expectedNumber && resolvedComment.itemNumber !== expectedNumber) { | ||
| return { | ||
| success: false, | ||
| error: `Comment belongs to item #${resolvedComment.itemNumber}, but target is #${expectedNumber}`, | ||
| }; | ||
| } |
There was a problem hiding this comment.
Addressed in de83120 and reinforced by e5380ea: hide_comment now validates the resolved comment parent kind as well as repository/number, and the shared target regression suite/conformance checks cover configured-target enforcement.
…get Authorization sections Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
|
@copilot update safe-outputs specification and specification enforcing scripts |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Updated the safe-output specification and added enforcement tests for
Updated the safe-output specification and added enforcement tests for
Ran the PR-finisher pass. Local validation is green; existing Copilot review threads already have substantive responses but remain unresolved, and the current GitHub Advanced Security check is still in progress. |
|
@copilot ensure systematic test suite and fail safe runtime assertion to prevent regression |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Implemented in |
|
🎉 This pull request is included in a new release. Release: |


Several safe-output handlers selected model-provided IDs before applying their configured
target, allowing operations to escape the default triggering item or a fixed numeric target.link-sub-issuealso dropped its parsed target during handler configuration.Changes
Target enforcement
targetbefore model-provided IDs across merge, comment, close, review, assignment, milestone, and issue-field handlers.target: "*".target: triggering.Boundary validation
hide-commenttargets against the comment’s parent item and repository.Sub-issue configuration
link-sub-issue.targetinto runtime configuration.Compiler validation
unassign-from-user,set-issue-type,set-issue-field, andresolve-pull-request-review-thread.pr-sous-chefRun: https://github.com/github/gh-aw/actions/runs/35656487865