Skip to content

fix(workflows): allow nested source files and package-registry egress - #1744

Merged
bradygaster merged 2 commits into
devfrom
fix-worker-file-and-network-scope
Aug 18, 2026
Merged

bradygaster merged 2 commits into
devfrom
fix-worker-file-and-network-scope

Conversation

@bradygaster

Copy link
Copy Markdown
Collaborator

Closes #1743

Two configuration defects in the implementation worker, both found during a live end-to-end run against a real .NET repository (bradygaster/aspiregregator-squad-test). Neither is caught by compilation — both compile clean and fail only at agent runtime.

A. allowed-files matched the repository root only

The allowlist declared its 40 extension globs bare — *.cs, *.csproj, *.java, *.go. A * does not cross a /, so those patterns match only files sitting at the repository root. The supplementary directory globs are all lowercase conventional names (src/**, lib/**, app/**, api/**, …).

The effect: a repository that puts source in top-level project folders — the default .NET solution layout, and common in Java and Go — has no file the worker is permitted to change.

Observed live against AppHost/ Abstractions/ Grains/ Frontend/ FeedUpdater/ Defaults/. Every file in the worker's patch was rejected — 5 .csproj, 3 .cs, and .github/copilot-instructions.md. The run reported success. The pull request simply never appeared. That silence is what makes this worth fixing carefully: there is no failure signal to follow.

Every extension now carries a **/*.ext mirror alongside the root-level form. Keeping both is deliberate — whether **/ matches zero path segments is implementation-defined, and I did not want correctness resting on an assumption I had not verified. Dockerfile* and Makefile gained nested variants for the same reason.

*.razor was absent from the list entirely and has been added; Blazor components were unwritable at any depth, root included.

B. network.allowed granted no package-registry egress

[defaults] covers GitHub and certificate infrastructure, but no language package registry. An implementation agent that cannot restore dependencies cannot build or test what it just wrote.

Observed live: dotnet restore took a proxy 403 against api.nuget.org. The worker behaved correctly — it reported the work incomplete rather than guessing — but it could not finish. gh-aw's compiler emits a recommendation to add the dotnet ecosystem in precisely this case, and that recommendation disappears with this change.

Added containers, dotnet, go, java, node, python, ruby, rust.

Scoped to the worker only. workflows/squad.md plans and routes; it does not restore packages, so its network surface stays narrow. Widening it would trade real attack surface for nothing.

Verification

Compiled with real gh-aw (v0.86.2) and inspected the generated lock rather than trusting the source diff:

Check Result
api.nuget.org, registry.npmjs.org, pypi.org, repo.maven.apache.org, crates.io in resolved domains ✅ present
**/*.csproj, **/*.razor in resolved allowed_files ✅ present
Compile status 2 workflows, 2 succeeded
Warnings 1, pre-existing (slash_command + bots: in squad.md) — unrelated to this change
test/gh-aw-quality.test.ts 79 passed, 13 skipped

The nested-glob fix is not theoretical: the same widening applied ad hoc during the e2e is what unblocked the run that produced a real modernization pull request (Aspire 9.0.0-rc.1 → 13.4.6, Orleans → 9.2.1, plus a genuine FluentUI Icons breaking-change fix), green on ubuntu, windows, and macOS.

Security note

No new secrets, actions, or redirects. The only privilege change is outbound network scope, widened from defaults to defaults plus eight gh-aw-curated package-registry ecosystems. These are gh-aw's own maintained domain sets, not hand-written hosts, and they are read-only package fetches on the workflow that already holds edit: and bash:. The allowed-files change widens which paths may be written; protected-files and max-patch-files: 500 are unchanged, so sensitive manifests remain guarded.

Out of scope

Found in the same run, deliberately not fixed here:

  • protected-files: request_review logs that it will proceed with a request-changes review, then hard-refuses the push (Signed-commit payload violates file-protection policy). Soft policy, hard enforcement — this looks like a gh-aw upstream bug and belongs there.
  • Consumer repositories must enable Allow GitHub Actions to create and approve pull requests, or safe-output PR creation fails outright. Documentation or a preflight check, not code.
  • The slash_command + bots: warning in squad.md.

Two defects found during a live end-to-end run against a real .NET repository.
Both compile clean and fail only at agent runtime.

allowed-files matched the repository root only. The 40 extension globs were
declared bare (`*.cs`, `*.csproj`, `*.java`, ...), and `*` does not cross `/`,
so nothing outside the root matched. The supplementary directory globs are all
lowercase conventional names, so a repository using top-level project folders --
the default .NET solution layout -- had no file the worker was permitted to
change. Observed live: 5 `.csproj`, 3 `.cs`, and one dotfile path all rejected;
the run reported success and no pull request appeared. Each extension now has a
`**/*.ext` mirror alongside the root form, `Dockerfile*` and `Makefile` gained
nested variants, and `*.razor` was added -- it was missing entirely, which
blocked Blazor components at any depth.

network.allowed granted no package registry. `[defaults]` covers GitHub and
certificate infrastructure only, so the agent could not restore dependencies and
therefore could not build or test its own work. Observed live: `dotnet restore`
took a proxy 403 against api.nuget.org, and the worker correctly reported the
task incomplete rather than guessing. Added the ecosystem identifiers
containers, dotnet, go, java, node, python, ruby, and rust.

Scoped to the worker. `workflows/squad.md` plans and routes rather than
restoring packages, so its network surface stays narrow.

Closes #1743

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 090e9874-9835-489a-b38d-05a450b3fc53
Copilot AI lite review requested due to automatic review settings August 18, 2026 08:17
@github-actions

Copy link
Copy Markdown
Contributor

🟢 Impact Analysis — PR #1744

Risk tier: 🟢 LOW

📊 Summary

Metric Count
Files changed 1
Files added 0
Files modified 1
Files deleted 0
Modules touched 1

🎯 Risk Factors

  • 1 files changed (≤5 → LOW)
  • 1 module(s) touched (≤1 → LOW)

📦 Modules Affected

root (1 file)
  • workflows/squad-implement-worker.md

This report is generated automatically for every PR. See #733 for details.

@github-actions

github-actions Bot commented Aug 18, 2026 •

Copy link
Copy Markdown
Contributor

🛫 PR Readiness Check

ℹ️ This comment updates on each push. Last checked: commit 7251b14

PR Scope: 🔧 Infrastructure

⚠️ 3 item(s) to address before review

Status Check Details
❌ Single commit 2 commits — consider squashing before review
✅ Not in draft Ready for review
✅ Branch up to date Up to date with dev
❌ Copilot review No Copilot review yet — it may still be processing
✅ Changeset present No source files changed — changeset not required
✅ Scope clean No .squad/ or docs/proposals/ files
✅ No merge conflicts No merge conflicts
❌ Copilot threads resolved 1 unresolved Copilot thread(s) — fix and resolve before merging
✅ CI passing All checks passing

Files Changed (1 file, +69 −1)

File +/−
workflows/squad-implement-worker.md +69 −1

Total: +69 −1


This check runs automatically on every push. Fix any ❌ items and push again.
See CONTRIBUTING.md and PR Requirements for details.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 updates the Squad implement worker workflow configuration to (1) allow edits to source files located in nested directories (common in real-world repo layouts), and (2) grant outbound network egress to language package registries so the worker can restore/build/test during implementation.

Changes:

  • Expanded safe-outputs.create-pull-request.allowed-files by adding **/*.<ext> mirrors (and nested Dockerfile*/Makefile variants) plus *.razor to support nested source trees.
  • Broadened network.allowed for the worker to include curated gh-aw ecosystems (e.g., dotnet, node, python, etc.) for package-registry access.
Show a summary per file
File Description
workflows/squad-implement-worker.md Adds package-registry egress and widens the worker’s editable-file allowlist to support nested source layouts.

Review details

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Suppressed comments (1)

workflows/squad-implement-worker.md:142

  • Adding **/*.yaml / **/*.yml makes it possible for the implement worker to modify YAML anywhere, including .github/workflows/, which the workflow instructions explicitly prohibit changing later in this file. If the intent is to keep workflow/agent metadata immutable from the implement worker, consider keeping YAML allowlisted only at the repo root and within the explicitly named directories (e.g. config/**, src/**, etc.).
      - "*.yaml"
      - "**/*.yaml"
      - "*.yml"
      - "**/*.yml"
  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment on lines 101 to +102
- "*.md"
- "**/*.md"

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Agreed, and thanks — this is a real regression I introduced. Before the widening, root-anchored *.md never matched .squad/team.md or .github/workflows/*.md, so the prose rule at L231-232 was backed by a structural guarantee. Adding **/*.md (and **/*.yml, **/*.json) quietly demoted that to instruction-following, on the one workflow that must not be able to rewrite its own definition.

Rather than special-case .github/copilot-instructions.md, fixed in 7251b14 with excluded-files, which strips matching paths from the patch before the commit is created. That restores the structural guarantee for all four forbidden directories while keeping the nested globs this PR exists to add. .github/copilot-instructions.md stays writable because only the named subdirectories are excluded. Verified excluded_files reaches the compiled lock.

…lowlist

Adding nested `**/*.md`, `**/*.yml`, and `**/*.json` patterns made paths
writable that root-anchored globs had blocked structurally -- among them
.github/workflows/, .github/agents/, .github/aw/, and .squad/. The prompt
already forbids changing those in prose, but that turned a structural guarantee
into instruction-following, and it would let the worker rewrite its own workflow
definition or the squad configuration that routes it.

excluded-files strips those paths from the patch before the commit is created,
restoring the guarantee without narrowing the nested globs that the widening
exists to provide. .github/copilot-instructions.md stays writable, since only
the four named subdirectories are excluded.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 090e9874-9835-489a-b38d-05a450b3fc53
@bradygaster
bradygaster merged commit 1e09d9c into dev Aug 18, 2026
16 checks passed
@bradygaster
bradygaster deleted the fix-worker-file-and-network-scope branch August 18, 2026 16:09
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.

Implement worker cannot edit files outside the repo root, and has no package-registry egress

2 participants