feat(guard): add DIFC labeling for GitHub Projects tools#2095
Conversation
- Add explicit match arms in tool_rules.rs for list_projects, get_project, list_project_fields, and list_project_items using owner-scoped approved integrity. Fixes scope-mismatch bug (bare "none" vs "none:<owner>") and integrity-level bug (now approved instead of none). - Add per-item path labeling in response_paths.rs for list_project_items: ISSUE/PULL_REQUEST items use repository_url secrecy + author_association integrity; DRAFT_ISSUE items use org-scoped approved integrity. - Add unit tests covering all four tools and three item types. Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR updates the GitHub guard’s DIFC labeling rules to properly scope and elevate integrity for GitHub Projects read tools, and adds fine-grained (per-item) response labeling for heterogeneous project items to avoid integrity-scope mismatches and incorrect integrity floors.
Changes:
- Add explicit
tool_rulesmatch arm for GitHub Projects read tools to scope integrity to the org owner and set an approved-level baseline. - Add
response_pathshandler forlist_project_itemsto label items differently based on whether they represent repo-backed issues/PRs vs draft/unknown item types. - Add unit tests covering scope alignment and integrity level expectations for Projects tools and
list_project_itemspath labeling.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| guards/github-guard/rust-guard/src/labels/tool_rules.rs | Adds explicit Projects tool labeling to fix scope alignment and raise integrity to org-approved. |
| guards/github-guard/rust-guard/src/labels/response_paths.rs | Introduces per-item path labeling for list_project_items to handle mixed item types. |
| guards/github-guard/rust-guard/src/labels/mod.rs | Adds tests validating Projects tool integrity/scope behavior and list_project_items path labeling. |
💡 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.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
|
@copilot I'm worried that the remnants of the old integrity hierarchy are still around. Make sure that "writer" has been replaced with "approved" and "reader" with "unapproved" when referring to integrity levels |
…d in comments Update all comment references to integrity levels to use the correct label terminology: "approved" instead of "writer" and "unapproved" instead of "reader". Fixes the incorrect policy_private_scope_label call in the fail-secure fallback path for list_project_items. Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Done in e415f2f. All uses of "writer" and "reader" when referring to integrity levels in comments have been updated to "approved" and "unapproved" respectively — including function docstrings in |
The four GitHub Projects read tools (
list_projects,get_project,list_project_fields,list_project_items) fell through to the default case intool_rules.rs, causing two independent failures: (1) bare"none"integrity vs. scoped"none:github"on the agent — exact-match comparison always fails, blocking all project access even withmin-integrity: none; (2) even with scope fixed, projects gotnoneintegrity rather than theapprovedlevel warranted by org-membership requirements.Changes
tool_rules.rsownerfrom tool args; setbaseline_scope = ownersoensure_integrity_baselineuses the correct scope tokenwriter_integrity(&baseline_scope, ctx)→approved:<owner>(creating/managing projects requires org membership)response_paths.rslist_project_items(heterogeneous collection)ISSUE/PULL_REQUEST: secrecy from repo visibility viarepository_url; integrity fromauthor_associationDRAFT_ISSUE/ unknown: empty secrecy; org-scopedapprovedintegrityReproduction matrix (from upstream)
reposmin-integrity"all"none["github/*"]none"none" ≠ "none:github""none:github""all"approved"none""approved"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/tmp/go-build1091184930/b332/launcher.test /tmp/go-build1091184930/b332/launcher.test -test.testlogfile=/tmp/go-build1091184930/b332/testlog.txt -test.paniconexit0 -test.timeout=10m0s stup�� g_.a stup/toolchains/stable-x86_64-un/tmp/go-build3339158387/b269/ x_amd64/compile(dns block)invalid-host-that-does-not-exist-12345.com/tmp/go-build1091184930/b317/config.test /tmp/go-build1091184930/b317/config.test -test.testlogfile=/tmp/go-build1091184930/b317/testlog.txt -test.paniconexit0 -test.timeout=10m0s c4d6�� ternal/engine/wazevo/wazevoapi/debug_options.go ternal/engine/wazevo/wazevoapi/exitcode.go x_amd64/compile(dns block)nonexistent.local/tmp/go-build1091184930/b332/launcher.test /tmp/go-build1091184930/b332/launcher.test -test.testlogfile=/tmp/go-build1091184930/b332/testlog.txt -test.paniconexit0 -test.timeout=10m0s stup�� g_.a stup/toolchains/stable-x86_64-un/tmp/go-build3339158387/b269/ x_amd64/compile(dns block)slow.example.com/tmp/go-build1091184930/b332/launcher.test /tmp/go-build1091184930/b332/launcher.test -test.testlogfile=/tmp/go-build1091184930/b332/testlog.txt -test.paniconexit0 -test.timeout=10m0s stup�� g_.a stup/toolchains/stable-x86_64-un/tmp/go-build3339158387/b269/ x_amd64/compile(dns block)this-host-does-not-exist-12345.com/tmp/go-build1091184930/b341/mcp.test /tmp/go-build1091184930/b341/mcp.test -test.testlogfile=/tmp/go-build1091184930/b341/testlog.txt -test.paniconexit0 -test.timeout=10m0s /tmp/go-build1091184930/b268/vet.cfg ypass.go ommon.go x_amd64/compile erive-f8a9da973e/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet g/x/net/dns/dnsm-unsafeptr=false erive-f8a9da973e-unreachable=false x_amd64/compile 9158�� 9158387/b093/_pkgo1.25.8 J6jg/M1uOXhMTrsT-c=4 x_amd64/vet erive-f8a9da973e/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet erive-f8a9da973e-atomic -Wl,-Bstatic x_amd64/vet(dns block)If you need me to access, download, or install something from one of these locations, you can either:
💡 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.