Skip to content

Add ifc label for list_issues tool#2453

Merged
gokhanarkan merged 2 commits into
mainfrom
gokhanarkan/fides-list-issues
May 12, 2026
Merged

Add ifc label for list_issues tool#2453
gokhanarkan merged 2 commits into
mainfrom
gokhanarkan/fides-list-issues

Conversation

@gokhanarkan
Copy link
Copy Markdown
Member

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.

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

  • Wires _meta.ifc onto the list_issues CallToolResult when deps.GetFlags(ctx).InsidersMode is true. No behaviour change when the flag is off.
  • Public repos → PublicUntrusted() (issue contents are attacker-controllable, so integrity is untrusted; readers are ["public"]).
  • Private repos → PrivateUntrusted([owner]) as a placeholder for the reader set. See limitation below.
  • Adds an IsPrivate field to all four ListIssues*Query* GraphQL types so visibility is available without an extra REST round trip. IssueQueryResult gains a GetIsPrivate() bool method.

New shared helpers

Adds four general label constructors in pkg/ifc/ifc.go to seed reuse for upcoming ingress tools (get_file_contents, search_issues, …):

  • PublicTrusted()
  • PublicUntrusted()
  • PrivateTrusted([]string)
  • PrivateUntrusted([]string)

LabelGetMe() is refactored to delegate to PublicTrusted(); output is byte-for-byte identical (covered by the existing Test_GetMe_IFC_InsidersMode test). Flagging this for reviewers in case duplication concerns come up — happy to slim back to a single LabelListIssues helper 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 per list_issues invocation; rather than bake that into this PR, I'd like to land a shared visibility/collaborators helper in a follow-up that get_file_contents and search_issues can also share. There's a TODO(fides) comment at the call site.

Tests

Test_ListIssues_IFC_InsidersMode mirrors Test_GetMe_IFC_InsidersMode with three subtests:

  1. Insiders off → result.Meta == nil.
  2. Insiders on, public repo → integrity=untrusted, confidentiality=["public"].
  3. Insiders on, private repo → integrity=untrusted, confidentiality=["<owner>"].

Existing Test_ListIssues GraphQL query strings and mock responses were updated to include the new isPrivate field.

Validation

  • go test -race ./... — green.
  • gofmt -s clean; go vet ./... clean.
  • (./script/lint itself fails locally with a pre-existing golangci-lint Go-version mismatch unrelated to this change.)
  • No tool schema/annotation changes → no toolsnap or README regeneration needed.

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.
Copilot AI review requested due to automatic review settings May 11, 2026 15:48
@gokhanarkan gokhanarkan requested a review from a team as a code owner May 11, 2026 15:48
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

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 refactored LabelGetMe() to delegate to PublicTrusted().
  • Extended list_issues GraphQL query types to fetch repository isPrivate, and emits an IFC label onto CallToolResult.Meta["ifc"] in insiders mode.
  • Added Test_ListIssues_IFC_InsidersMode and updated existing list_issues GraphQL test fixtures/query strings to include isPrivate.
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

Comment thread pkg/github/issues.go
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.
@gokhanarkan gokhanarkan merged commit 5259513 into main May 12, 2026
18 checks passed
@gokhanarkan gokhanarkan deleted the gokhanarkan/fides-list-issues branch May 12, 2026 09:55
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.
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.

4 participants