Skip to content

Guard coverage: block all modifying gh repo operations#2806

Merged
lpcox merged 2 commits intomainfrom
copilot/guard-coverage-add-cli-operations
Mar 30, 2026
Merged

Guard coverage: block all modifying gh repo operations#2806
lpcox merged 2 commits intomainfrom
copilot/guard-coverage-add-cli-operations

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 29, 2026

The guard had archive_repository classified as a write op but not blocked, and was missing rename_repository and unarchive_repository entirely — creating an asymmetry where transfer_repository was blocked but its sibling repo-mutating operations were not.

Changes

tools.rs

  • Add unarchive_repository and rename_repository to WRITE_OPERATIONS
  • Expand is_blocked_tool() to cover all modifying gh repo operations:
    matches!(
        tool_name,
        "transfer_repository" | "archive_repository" | "unarchive_repository" | "rename_repository"
    )
  • Add tests for the new blocked/write-classified operations

labels/tool_rules.rs

  • Add a match arm for the three newly blocked tools applying repo-visibility secrecy (same pattern as transfer_repository); integrity blocking is enforced downstream via is_blocked_tool() in label_resource

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:

  • example.com
    • Triggering command: /tmp/go-build2882961169/b338/launcher.test /tmp/go-build2882961169/b338/launcher.test -test.testlogfile=/tmp/go-build2882961169/b338/testlog.txt -test.paniconexit0 -test.timeout=10m0s guar�� g_.a guard-d6a03f414dc506a0.1b9hao6thgithub.com/tetratelabs/wazero/internal/sys cal/bin/as guard-d6a03f414d/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet ernal/logger/san-unsafeptr=false guard-d6a03f414d-unreachable=false ache/go/1.25.8/x/tmp/go-build2882961169/b098/vet.cfg 9916�� 6r2N21naL ache/go/1.25.8/x64/src/internal/-nolocalimports x_amd64/vet guard-d6a03f414d/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet guard-d6a03f414d-atomic /home/REDACTED/wor-bool x_amd64/vet (dns block)
  • invalid-host-that-does-not-exist-12345.com
    • Triggering command: /tmp/go-build2882961169/b320/config.test /tmp/go-build2882961169/b320/config.test -test.testlogfile=/tmp/go-build2882961169/b320/testlog.txt -test.paniconexit0 -test.timeout=10m0s ortc�� 1.4.1/jsonrpc/jsonrpc.go 64/src/crypto/sha256/sha256.go x_amd64/compile -gnu/lib/librust/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet 9916148/b009/ /home/REDACTED/.ru-unreachable=false x_amd64/compile --no�� 9916148/b147/_pkg_.a /home/REDACTED/.rustup/toolchains/GOAMD64_v1 x_amd64/vet bug/build/serde-/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet guard-d6a03f414d-unsafeptr=false 64-REDACTED-linux-unreachable=false x_amd64/vet (dns block)
  • nonexistent.local
    • Triggering command: /tmp/go-build2882961169/b338/launcher.test /tmp/go-build2882961169/b338/launcher.test -test.testlogfile=/tmp/go-build2882961169/b338/testlog.txt -test.paniconexit0 -test.timeout=10m0s guar�� g_.a guard-d6a03f414dc506a0.1b9hao6thgithub.com/tetratelabs/wazero/internal/sys cal/bin/as guard-d6a03f414d/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet ernal/logger/san-unsafeptr=false guard-d6a03f414d-unreachable=false ache/go/1.25.8/x/tmp/go-build2882961169/b098/vet.cfg 9916�� 6r2N21naL ache/go/1.25.8/x64/src/internal/-nolocalimports x_amd64/vet guard-d6a03f414d/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet guard-d6a03f414d-atomic /home/REDACTED/wor-bool x_amd64/vet (dns block)
  • slow.example.com
    • Triggering command: /tmp/go-build2882961169/b338/launcher.test /tmp/go-build2882961169/b338/launcher.test -test.testlogfile=/tmp/go-build2882961169/b338/testlog.txt -test.paniconexit0 -test.timeout=10m0s guar�� g_.a guard-d6a03f414dc506a0.1b9hao6thgithub.com/tetratelabs/wazero/internal/sys cal/bin/as guard-d6a03f414d/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet ernal/logger/san-unsafeptr=false guard-d6a03f414d-unreachable=false ache/go/1.25.8/x/tmp/go-build2882961169/b098/vet.cfg 9916�� 6r2N21naL ache/go/1.25.8/x64/src/internal/-nolocalimports x_amd64/vet guard-d6a03f414d/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet guard-d6a03f414d-atomic /home/REDACTED/wor-bool x_amd64/vet (dns block)
  • this-host-does-not-exist-12345.com
    • Triggering command: /tmp/go-build2882961169/b347/mcp.test /tmp/go-build2882961169/b347/mcp.test -test.testlogfile=/tmp/go-build2882961169/b347/testlog.txt -test.paniconexit0 -test.timeout=10m0s go_.�� ache/go/1.25.8/x64/src/runtime/cgo ache/go/1.25.8/x64/src/slices/iter.go x_amd64/vet ut-1243131759.c 64-REDACTED-linux-o 64-REDACTED-linux/tmp/go-build2882961169/b331/_pkg_.a x_amd64/vet go_.�� 64/src/net internal/httpcomgithub.com/github/gh-aw-mcpg/internal/guard x_amd64/compile -p weak -lang=go1.25 x_amd64/compile (dns block)

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


🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

…ive/archive)

- Add `unarchive_repository` and `rename_repository` to WRITE_OPERATIONS
- Block `archive_repository`, `unarchive_repository`, `rename_repository` in is_blocked_tool()
  alongside the existing `transfer_repository` entry
- Add match arms in tool_rules.rs for the three new blocked operations
  (repo-visibility secrecy, same pattern as transfer_repository)
- Add tests for newly blocked and write-classified operations

Agent-Logs-Url: https://github.com/github/gh-aw-mcpg/sessions/844d1229-ef7e-493a-a187-398e882d4f68

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Copilot AI changed the title [WIP] Add guard coverage for 2 CLI write operations Guard coverage: block all modifying gh repo operations Mar 29, 2026
Copilot AI requested a review from lpcox March 29, 2026 23:47
@lpcox lpcox marked this pull request as ready for review March 30, 2026 00:21
Copilot AI review requested due to automatic review settings March 30, 2026 00:21
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

This PR closes a guard-policy gap by ensuring all repo-mutating gh repo operations are consistently classified as write operations and unconditionally blocked, aligning behavior across sibling operations (archive/unarchive/rename/transfer).

Changes:

  • Extend WRITE_OPERATIONS and is_blocked_tool() to include archive_repository, unarchive_repository, and rename_repository.
  • Add unit tests in tools.rs to validate blocked + write classification for the new operations.
  • Update tool-label rules to apply repo-visibility secrecy for the newly blocked repo-modifying tools (matching transfer_repository behavior).

Reviewed changes

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

File Description
guards/github-guard/rust-guard/src/tools.rs Adds new repo-modifying tool names to write + blocked classification and tests for them.
guards/github-guard/rust-guard/src/labels/tool_rules.rs Applies repo-visibility secrecy for newly blocked repo-modifying operations to keep resource classification consistent.

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

Comment on lines 127 to +131
pub fn is_blocked_tool(tool_name: &str) -> bool {
matches!(tool_name, "transfer_repository")
matches!(
tool_name,
"transfer_repository" | "archive_repository" | "unarchive_repository" | "rename_repository"
)
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

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

Consider adding unit tests at the label_resource level (in lib.rs tests) for the newly blocked tools (archive/unarchive/rename), similar to the existing transfer_repository_integrity_is_blocked_after_ensure_baseline test. The current tests here validate is_blocked_tool(), but they don’t exercise the end-to-end blocked-integrity override that actually enforces the policy in runtime.

Copilot uses AI. Check for mistakes.
Comment on lines +174 to +182
// === Modifying Repository Operations (blocked: unsupported gh repo operations) ===
"archive_repository" | "unarchive_repository" | "rename_repository" => {
// All modifying `gh repo` operations (archive, unarchive, rename) are treated as
// unsupported for automated agents — the same policy as transfer_repository.
// Blocking is enforced in label_resource via is_blocked_tool(); this arm applies
// repo-visibility secrecy so the resource is correctly classified before the
// integrity override happens in label_resource.
secrecy = apply_repo_visibility_secrecy(&owner, &repo, repo_id, secrecy, ctx);
}
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

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

There are existing apply_tool_labels unit tests for transfer_repository in labels/mod.rs, but none covering this new match arm. Add tests that call apply_tool_labels("archive_repository"|"unarchive_repository"|"rename_repository", …) to verify the secrecy behavior matches transfer_repository (and that the call completes deterministically in cfg(test) without relying on the backend host).

Copilot uses AI. Check for mistakes.
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.

[guard-coverage] Guard coverage gap: 2 CLI write operations not modeled in guard

3 participants