Skip to content

Add allowed-files strict allowlist for protected-file protection on PR safe outputs#20051

Merged
pelikhan merged 11 commits intomainfrom
copilot/add-allowed-files-to-pull-request
Mar 8, 2026
Merged

Add allowed-files strict allowlist for protected-file protection on PR safe outputs#20051
pelikhan merged 11 commits intomainfrom
copilot/add-allowed-files-to-pull-request

Conversation

Copy link
Contributor

Copilot AI commented Mar 8, 2026

  • Add AllowedFiles []string to Go structs and wire through compiler
  • checkAllowedFiles in manifest_file_helpers.cjs
  • Strict allowlist enforcement in both JS handlers
  • Tests for checkAllowedFiles, integration tests in push/create handlers
  • instructions-janitor.mdallowed-files: [.github/aw/**] + protected-files: allowed
  • changeset.mdallowed-files: [.changeset/**]
  • Refactor: checkFileProtection(patchContent, config) — encapsulates branching into a { action, source?, files } result
  • Orthogonal checks: allowed-files and protected-files run independently; both must pass
  • Fix TypeScript CI failure: added file-protection properties to HandlerConfig interface; updated checkFileProtection JSDoc param type to HandlerConfig
  • Fix stale JSDoc on checkAllowedFiles (removed "protected-files bypassed" statement)
  • Fix stale Go struct comments ("Takes priority" → orthogonal description)
  • Fix stale JSON schema descriptions ("Takes priority" → orthogonal description)
  • Fix stale docs ("completely bypassed/ignored" → orthogonal description)
  • Add 9 direct unit tests for checkFileProtection in manifest_file_helpers.test.cjs
Original prompt

Add a field safe-outputs.push-to-pull-request-branch.allowed-files that allows to specify a list of globs to allowed files. This has higher priority that the protected-files filter.

Also apply to create-pull-request.

Update suggested text if failed protected files to add file to allowed-files set.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

…-request-branch and create-pull-request

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Add allowed files feature for push to pull request branch Add allowed-files glob exemptions for protected-file protection on PR safe outputs Mar 8, 2026
@pelikhan
Copy link
Contributor

pelikhan commented Mar 8, 2026

@copilot configure allowed files in the instruction janitor agentic workflow and in the changeset generator

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 8, 2026

@copilot configure allowed files in the instruction janitor agentic workflow and in the changeset generator

Done in 3b1c57f.

  • instructions-janitor.md: Added allowed-files: [.github/aw/github-agentic-workflows.md] — the workflow creates PRs that modify this file under the protected .github/ path, so it was being blocked.
  • changeset.md: Added allowed-files: [.changeset/**] — the workflow pushes changeset files to PR branches.

@pelikhan
Copy link
Contributor

pelikhan commented Mar 8, 2026

@copilot once specified, allowed-files are an allow list (anything outside of allowed files is refused), and protected-files are overriden.

…ns, bypass protected-files

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 8, 2026

@copilot once specified, allowed-files are an allow list (anything outside of allowed files is refused), and protected-files are overriden.

Fixed in 303143b.

allowed-files is now a strict allowlist: when set, every file in the patch must match at least one pattern — anything outside the list is refused and protected-files checks are completely bypassed. filterAllowedFiles (which was filtering the protected-files list) was replaced with checkAllowedFiles(patchContent, patterns) which checks all changed paths against the allowlist directly.

Copilot AI changed the title Add allowed-files glob exemptions for protected-file protection on PR safe outputs Add allowed-files strict allowlist for protected-file protection on PR safe outputs Mar 8, 2026
@pelikhan
Copy link
Contributor

pelikhan commented Mar 8, 2026

@copilot add tests, add allowed files to instruction janitor to let it write instruction files.

…thub/aw/** files

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 8, 2026

@copilot add tests, add allowed files to instruction janitor to let it write instruction files.

Done in 0538d6f.

Tests added (push_to_pull_request_branch.test.cjs — 5 tests, create_pull_request.test.cjs — 4 tests):

  • Reject files outside the allowlist
  • Accept files matching the pattern
  • Bypass protected-files when allowed-files is set and matches
  • Still enforce protected-files when no allowed-files configured
  • Reject mixed patches where some files are outside the list

instructions-janitor.md: Changed allowed-files: [.github/aw/github-agentic-workflows.md]allowed-files: [.github/aw/**] so the workflow can update any instruction file under .github/aw/.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

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 (http block)
  • https://api.github.com/repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b
    • Triggering command: /usr/bin/gh gh api /repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b --jq .object.sha (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/a70c5eada06553e3510ac27f2c3bda9d3705bccb
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/a70c5eada06553e3510ac27f2c3bda9d3705bccb --jq .object.sha (http block)
  • https://api.github.com/repos/githubnext/agentics/git/ref/tags/
    • Triggering command: /usr/bin/gh gh api /repos/githubnext/agentics/git/ref/tags/# --jq .object.sha (http block)

If you need me to access, download, or install something from one of these locations, you can either:

@pelikhan
Copy link
Contributor

pelikhan commented Mar 8, 2026

@copilot refactor added code for clarity. Use functions, avoid too much code/branches.

…ching in handlers

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 8, 2026

@copilot refactor added code for clarity. Use functions, avoid too much code/branches.

Refactored in 4882a6c.

Added checkFileProtection(patchContent, config) to manifest_file_helpers.cjs — it encapsulates the entire two-tier policy logic (allowlist → protected-files → fallback) and returns a flat { action: 'allow' | 'deny' | 'fallback', source?, files } result.

Both handlers now replace the 40-line nested if/else with a flat 15-line block that just switches on protection.action.

@pelikhan
Copy link
Contributor

pelikhan commented Mar 8, 2026

@lpcox @dsyme we need an allow list which takes precedence.

@lpcox
Copy link
Collaborator

lpcox commented Mar 8, 2026

@pelikhan @dsyme precedence rules will invariably lead to bugs and misconfiguration because users will not understand them. do you have a use case in mind that justifies the cost?

@pelikhan
Copy link
Contributor

pelikhan commented Mar 8, 2026

@lpcox message for you above.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 8, 2026

Contribution Check Report — PR #20051

Hey @pelikhan 👋 — great work on the allowed-files strict allowlist feature! This is a well-scoped, security-relevant addition to the safe-outputs PR protection mechanism, and the implementation looks solid.

✅ Checklist

Check Result
On-topic ✅ yes
Follows process ✅ yes — created by Copilot agent, assigned to core team member
Focused ✅ yes — all 15 changed files relate to the allowed-files feature + supporting refactor
New deps ✅ no
Has tests ✅ yes — manifest_file_helpers.test.cjs, create_pull_request.test.cjs, push_to_pull_request_branch.test.cjs
Has description ✅ yes — checklist body with original prompt
Lines changed 556 (491 additions + 65 deletions)

🟢 Verdict: Aligned

Everything looks on track. The PR correctly follows the agentic development process and covers the full implementation surface:

  • Go struct changes and schema updates are consistent with each other
  • Both JS handlers (push_to_pull_request_branch.cjs and create_pull_request.cjs) adopt the new checkFileProtection unified interface
  • The two real-world workflows (changeset.md, instructions-janitor.md) have been updated to use the new allowed-files field
  • Documentation in safe-outputs-pull-requests.md has been updated

The PR is currently in draft status — once any remaining in-progress items are resolved, it looks ready for maintainer review. 🚀

Generated by Contribution Check ·

…pass, require explicit configuration

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 8, 2026

@copilot specifically I have agent that writes to protected files. But I see what you mean, it is a hidden rule. Better keep it explicitly and orthogonal.

Done in 753ab9a. allowed-files and protected-files are now fully orthogonal — both checks run independently and both must pass. The implicit bypass is removed. To allow writing to protected files, both fields must be set explicitly: allowed-files: [...] to scope which files the agent may touch, and protected-files: allowed to grant explicit permission. instructions-janitor.md is updated accordingly.

@pelikhan
Copy link
Contributor

pelikhan commented Mar 8, 2026

@lpcox

@pelikhan pelikhan marked this pull request as ready for review March 8, 2026 17:45
Copilot AI review requested due to automatic review settings March 8, 2026 17:45
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

This PR adds a new allowed-files field to both push-to-pull-request-branch and create-pull-request safe output configurations. It acts as a strict allowlist of glob patterns: when set, every file in a patch must match at least one pattern. The checks are orthogonal with the existing protected-files policy — both must pass independently.

Changes:

  • Adds AllowedFiles to Go structs and wires it through the compiler to JS handlers; adds checkAllowedFiles and checkFileProtection helpers to consolidate file protection logic
  • Refactors both handler files to use the new checkFileProtection function, replacing ~40 lines of nested logic with a flat ~15-line block
  • Adds unit tests for checkAllowedFiles, integration tests for both handlers, JSON schema entries, documentation, and workflow configuration updates

Reviewed changes

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

Show a summary per file
File Description
pkg/workflow/push_to_pull_request_branch.go Adds AllowedFiles field and its parsing
pkg/workflow/create_pull_request.go Adds AllowedFiles field (parsed via YAML unmarshal)
pkg/workflow/compiler_safe_outputs_config.go Wires allowed_files into handler config for both handlers
pkg/parser/schemas/main_workflow_schema.json Adds allowed-files schema for both safe outputs
docs/src/content/docs/reference/safe-outputs-pull-requests.md Documents allowed-files behavior
actions/setup/js/manifest_file_helpers.cjs New checkAllowedFiles and checkFileProtection helpers
actions/setup/js/manifest_file_helpers.test.cjs Unit tests for checkAllowedFiles
actions/setup/js/push_to_pull_request_branch.cjs Refactored to use checkFileProtection
actions/setup/js/push_to_pull_request_branch.test.cjs Integration tests for allowed-files
actions/setup/js/create_pull_request.cjs Refactored to use checkFileProtection
actions/setup/js/create_pull_request.test.cjs Integration tests for allowed-files
.github/workflows/instructions-janitor.md Configured allowed-files and protected-files: allowed
.github/workflows/instructions-janitor.lock.yml Updated lock file with new config
.github/workflows/changeset.md Configured allowed-files: [.changeset/**]
.github/workflows/changeset.lock.yml Updated lock file with new config
Comments suppressed due to low confidence (1)

pkg/parser/schemas/main_workflow_schema.json:6331

  • Same issue as the create-pull-request schema: the description says "Takes priority over the protected-files policy" but the implementation treats them as orthogonal checks that both must pass independently.
                "allowed-files": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "description": "List of glob patterns for files that are exempt from protected-file protection. Takes priority over the protected-files policy. Use to allow specific files (e.g. go.mod) without disabling all protected-file checks. Supports * (any characters except /) and ** (any characters including /)."

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

You can also share your feedback on Copilot code review. Take the survey.

const result = checkAllowedFiles(patch, [".changeset/**"]);
expect(result.hasDisallowedFiles).toBe(false);
});
});
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

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

The new checkFileProtection function (added in this PR in manifest_file_helpers.cjs) is tested indirectly via the integration tests in push_to_pull_request_branch.test.cjs and create_pull_request.test.cjs, but has no direct unit tests here. Given that checkAllowedFiles has its own unit test block here, checkFileProtection should have one as well — covering the various combinations of allowed_files, protected_files, protected_path_prefixes, and protected_files_policy.

Copilot uses AI. Check for mistakes.
@pelikhan
Copy link
Contributor

pelikhan commented Mar 8, 2026

… fix stale bypass/priority comments and add checkFileProtection unit tests

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 8, 2026

@copilot fix tests https://github.com/github/gh-aw/actions/runs/22825834637/job/66207312159

Fixed in e428693. The TypeScript errors were caused by HandlerConfig having no declared properties in common with checkFileProtection's inline config type (TS2559). Fixed by adding the file-protection properties (allowed_files, protected_files, protected_path_prefixes, protected_files_policy) to HandlerConfig in handler-factory.d.ts, and updating checkFileProtection's JSDoc param to use HandlerConfig. Also addressed all the reviewer comments about stale "bypasses/priority" language across docs, schema, Go struct comments, and JSDoc, and added 9 direct unit tests for checkFileProtection.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

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 (http block)
  • https://api.github.com/repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b
    • Triggering command: /usr/bin/gh gh api /repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b --jq .object.sha js/**/*.json&#39; --ignore-path ../../../.prettierignore (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/a70c5eada06553e3510ac27f2c3bda9d3705bccb
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/a70c5eada06553e3510ac27f2c3bda9d3705bccb --jq .object.sha js/**/*.json&#39; --ignore-path ../../../.prettierignore (http block)
  • https://api.github.com/repos/githubnext/agentics/git/ref/tags/
    • Triggering command: /usr/bin/gh gh api /repos/githubnext/agentics/git/ref/tags/# --jq .object.sha ath ../../../.pr**/*.json (http block)

If you need me to access, download, or install something from one of these locations, you can either:

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

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

Comments suppressed due to low confidence (1)

pkg/parser/schemas/main_workflow_schema.json:6331

  • Same issue as the create-pull-request schema: the description starts with "List of glob patterns for files that are exempt from protected-file protection" but the actual behavior is a strict allowlist where both checks must pass independently. The word "exempt" is misleading. Consider rephrasing to match the actual semantics, e.g., "Strict allowlist of glob patterns for files eligible for modification."
                  "description": "List of glob patterns for files that are exempt from protected-file protection. Acts as a strict allowlist checked independently of the protected-files policy; both checks must pass for a file to be allowed. To modify a protected file, it must both match allowed-files and be permitted by protected-files (e.g. protected-files: allowed). Supports * (any characters except /) and ** (any characters including /)."

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

dsyme and others added 3 commits March 8, 2026 18:45
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@pelikhan pelikhan merged commit 5ab3d52 into main Mar 8, 2026
51 checks passed
@pelikhan pelikhan deleted the copilot/add-allowed-files-to-pull-request branch March 8, 2026 20:03
github-actions bot added a commit that referenced this pull request Mar 9, 2026
…ence

Document the protected-files and allowed-files fields for both
create-pull-request and push-to-pull-request-branch in the comprehensive
frontmatter reference. These fields were introduced in #20051 (allowed-files
strict allowlist) but were missing from frontmatter-full.md even though they
were already described in safe-outputs-pull-requests.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
github-actions bot added a commit that referenced this pull request Mar 9, 2026
Add three new terms from recent changes:
- Guard Policy: experimental GitHub MCP server access control
  (repos + min-integrity fields, PR #20096 terminology update)
- Protected Files: security mechanism for PR safe outputs
  (blocks sensitive file changes, PR #20051)
- Allowed Files: strict scope filter for PR safe outputs
  (allowlist of permitted file patterns, PR #20051)

Co-authored-by: Copilot <223556219+Copilot@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.

5 participants