Add ifc label for list_issues tool#2453
Merged
Merged
Conversation
Emits an IFC SecurityLabel on the list_issues tool result when the InsidersMode flag is enabled, mirroring the pattern landed for get_me in #2432. Public repositories are labelled PublicUntrusted; private repositories are labelled PrivateUntrusted with the repository owner as a placeholder reader (full collaborator enumeration is intentionally deferred to a follow-up shared helper). A new IsPrivate field is added to the ListIssues GraphQL query types so visibility is available without a second round trip. Refs github/copilot-mcp-core#1623, github/copilot-mcp-core#1389.
Contributor
There was a problem hiding this comment.
Pull request overview
Adds Information Flow Control (IFC) _meta.ifc labeling to the list_issues MCP tool output when InsidersMode is enabled, matching the existing get_me pattern and enabling downstream enforcement/telemetry to reason about tool-output integrity/confidentiality.
Changes:
- Added reusable IFC label constructors in
pkg/ifc(public/private × trusted/untrusted) and refactoredLabelGetMe()to delegate toPublicTrusted(). - Extended
list_issuesGraphQL query types to fetch repositoryisPrivate, and emits an IFC label ontoCallToolResult.Meta["ifc"]in insiders mode. - Added
Test_ListIssues_IFC_InsidersModeand updated existing list_issues GraphQL test fixtures/query strings to includeisPrivate.
Show a summary per file
| File | Description |
|---|---|
pkg/ifc/ifc.go |
Adds shared IFC label constructors and a LabelListIssues helper used by tools to attach consistent labels. |
pkg/github/issues.go |
Fetches repository.isPrivate in list_issues queries and conditionally attaches _meta.ifc when InsidersMode is enabled. |
pkg/github/issues_test.go |
Updates list_issues GraphQL expectations for isPrivate and adds coverage for IFC meta emission in insiders mode. |
Copilot's findings
- Files reviewed: 3/3 changed files
- Comments generated: 0
JoannaaKL
reviewed
May 12, 2026
Addresses Joanna's review feedback: for private repositories, populate the IFC confidentiality reader set with the repository's collaborator logins instead of the [owner] placeholder. Adds an exported FetchRepoCollaborators helper in pkg/github/repositories.go that paginates through Repositories.ListCollaborators. Mirrors the helper in github-mcp-server-remote (without the cache for now; cache can land in a follow-up). The lookup is invoked only for private repos under InsidersMode; if it fails we fall back to [owner] so the reader set is never empty for a private repo.
JoannaaKL
approved these changes
May 12, 2026
This was referenced May 12, 2026
gokhanarkan
added a commit
that referenced
this pull request
May 12, 2026
Emits an IFC SecurityLabel on the issue_read tool result when the InsidersMode flag is enabled, mirroring the pattern landed for get_me in #2432, list_issues in #2453, get_file_contents in #2454, and search_issues in #2456. issue_read operates on a single issue in a single repository so the label has the same per-repo semantics as list_issues; the helper ifc.LabelListIssues is reused directly. Integrity is always untrusted (issue contents, comments, and label descriptions are user-authored). Public repos are labelled PublicUntrusted; private repos are labelled PrivateUntrusted with the repository's collaborator logins, falling back to [owner] when the collaborators lookup fails. The IssueRead handler dispatches to four sub-functions (GetIssue, GetIssueComments, GetSubIssues, GetIssueLabels). The IFC label is attached at the dispatch site via a single attachIFC closure, so all four method branches emit the label without changes to the underlying helpers. Visibility-lookup failures cause the label to be omitted entirely (consistent with get_file_contents and search_issues). A future cleanup PR can extract attachIFC into a shared helper now that get_file_contents, search_issues, and issue_read use near-identical closures; intentionally not bundled here to keep the diff minimal. Refs github/copilot-mcp-core#1623, github/copilot-mcp-core#1389. Note: chained on #2456 (gokhanarkan/fides-search-issues), which is in turn chained on #2454. GitHub will retarget the base to main once those merge.
gokhanarkan
added a commit
that referenced
this pull request
May 12, 2026
Emits an IFC SecurityLabel on the search_issues tool result when the InsidersMode flag is enabled, mirroring the pattern landed for get_me in #2432, list_issues in #2453, and get_file_contents in #2454. Search results may span multiple repositories, so the label is the IFC join of the per-repository labels: - Integrity is always untrusted (issues are user-authored). - If any matched repository is public, the joined readers are ["public"] (the public side dominates the lub). - Otherwise the joined readers are the intersection of the collaborator sets across all matched private repositories. - Empty result sets are labelled public-untrusted (no data leaked). The shared searchHandler in search_utils.go gains an additive variadic 'searchOption' hook so SearchIssues can attach _meta.ifc without duplicating the search call. SearchPullRequests is unaffected; it does not pass any options. If any per-repository visibility or collaborators lookup fails the label is omitted entirely, consistent with get_file_contents, to avoid misclassifying the result. Refs github/copilot-mcp-core#1623, github/copilot-mcp-core#1389. Note: this PR is chained on #2454 (gokhanarkan/fides-get-file-contents) because it depends on the FetchRepoIsPrivate and FetchRepoCollaborators helpers introduced there. GitHub will retarget the base to main once #2454 merges.
gokhanarkan
added a commit
that referenced
this pull request
May 12, 2026
Emits an IFC SecurityLabel on the issue_read tool result when the InsidersMode flag is enabled, mirroring the pattern landed for get_me in #2432, list_issues in #2453, get_file_contents in #2454, and search_issues in #2456. issue_read operates on a single issue in a single repository so the label has the same per-repo semantics as list_issues; the helper ifc.LabelListIssues is reused directly. Integrity is always untrusted (issue contents, comments, and label descriptions are user-authored). Public repos are labelled PublicUntrusted; private repos are labelled PrivateUntrusted with the repository's collaborator logins, falling back to [owner] when the collaborators lookup fails. The IssueRead handler dispatches to four sub-functions (GetIssue, GetIssueComments, GetSubIssues, GetIssueLabels). The IFC label is attached at the dispatch site via a single attachIFC closure, so all four method branches emit the label without changes to the underlying helpers. Visibility-lookup failures cause the label to be omitted entirely (consistent with get_file_contents and search_issues). A future cleanup PR can extract attachIFC into a shared helper now that get_file_contents, search_issues, and issue_read use near-identical closures; intentionally not bundled here to keep the diff minimal. Refs github/copilot-mcp-core#1623, github/copilot-mcp-core#1389. Note: chained on #2456 (gokhanarkan/fides-search-issues), which is in turn chained on #2454. GitHub will retarget the base to main once those merge.
pachecocordovamoiseseduardo-byte
approved these changes
May 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Emits an IFC
SecurityLabelon thelist_issuestool result when theInsidersModeflag is enabled, mirroring the pattern landed forget_mein #2432.Refs github/copilot-mcp-core#1623, github/copilot-mcp-core#1389. This is one of the ingress tools listed in #1623's tool table.
What this PR does
_meta.ifconto thelist_issuesCallToolResultwhendeps.GetFlags(ctx).InsidersModeis true. No behaviour change when the flag is off.PublicUntrusted()(issue contents are attacker-controllable, so integrity isuntrusted; readers are["public"]).PrivateUntrusted([owner])as a placeholder for the reader set. See limitation below.IsPrivatefield to all fourListIssues*Query*GraphQL types so visibility is available without an extra REST round trip.IssueQueryResultgains aGetIsPrivate() boolmethod.New shared helpers
Adds four general label constructors in
pkg/ifc/ifc.goto seed reuse for upcoming ingress tools (get_file_contents,search_issues, …):PublicTrusted()PublicUntrusted()PrivateTrusted([]string)PrivateUntrusted([]string)LabelGetMe()is refactored to delegate toPublicTrusted(); output is byte-for-byte identical (covered by the existingTest_GetMe_IFC_InsidersModetest). Flagging this for reviewers in case duplication concerns come up — happy to slim back to a singleLabelListIssueshelper if preferred.Known limitation (called out for reviewers)
For private repositories, the confidentiality reader set is currently
[owner]rather than the full collaborator list. Fetching collaborators requires a paginated REST call perlist_issuesinvocation; rather than bake that into this PR, I'd like to land a shared visibility/collaborators helper in a follow-up thatget_file_contentsandsearch_issuescan also share. There's aTODO(fides)comment at the call site.Tests
Test_ListIssues_IFC_InsidersModemirrorsTest_GetMe_IFC_InsidersModewith three subtests:result.Meta == nil.integrity=untrusted,confidentiality=["public"].integrity=untrusted,confidentiality=["<owner>"].Existing
Test_ListIssuesGraphQL query strings and mock responses were updated to include the newisPrivatefield.Validation
go test -race ./...— green.gofmt -sclean;go vet ./...clean../script/lintitself fails locally with a pre-existing golangci-lint Go-version mismatch unrelated to this change.)