Skip to content

Add ifc label for get_file_contents tool#2454

Merged
gokhanarkan merged 2 commits into
mainfrom
gokhanarkan/fides-get-file-contents
May 12, 2026
Merged

Add ifc label for get_file_contents tool#2454
gokhanarkan merged 2 commits into
mainfrom
gokhanarkan/fides-get-file-contents

Conversation

@gokhanarkan
Copy link
Copy Markdown
Member

Emits an IFC SecurityLabel on the get_file_contents tool result when the InsidersMode flag is enabled, mirroring the pattern landed for get_me in #2432 and list_issues in #2453.

Refs github/copilot-mcp-core#1623, github/copilot-mcp-core#1389. One of the ingress tools listed in #1623's tool table.

Chained on #2453. Base is currently gokhanarkan/fides-list-issues because that PR adds the shared Public*/Private* label constructors in pkg/ifc/ifc.go. Once #2453 merges, GitHub will auto-retarget this PR's base to main.

What this PR does

  • Wires _meta.ifc onto the get_file_contents CallToolResult when deps.GetFlags(ctx).InsidersMode is true. No behaviour change when the flag is off.
  • Public repos → PublicUntrusted() (file contents can be authored by anyone via PRs, so integrity is untrusted; readers are ["public"]).
  • Private repos → PrivateTrusted([owner]) — only collaborators can land changes in private repos, so integrity is trusted. [owner] is a placeholder reader set; full collaborator enumeration is deferred (see limitation).
  • The label is attached at every success return path (text file, binary file, empty file, large-file resource link, directory, and the matchFiles Git-tree fallback) via a small attachIFC closure to avoid duplicating the insiders block five times.

New shared helper

FetchRepoIsPrivate(ctx, client, owner, repo) (bool, error) in pkg/github/repositories.go. Thin wrapper around client.Repositories.Get. Exported so upcoming ingress tools (search_issues, issue_read) can reuse the same visibility lookup. Flagging this for reviewers in case the export surface is a concern.

The lookup is invoked lazily and only when InsidersMode is on, so non-insiders pay no extra round trip. If the lookup fails, we skip the label rather than fail the user-facing call (label is best-effort metadata, not security gating yet).

LabelGetFileContents(isPrivate, readers) is a new helper in pkg/ifc/ifc.go that composes the existing PublicUntrusted/PrivateTrusted constructors.

Known limitation (called out for reviewers)

Same as #2453: private-repo confidentiality currently uses [owner] rather than the full collaborator list. Fetching collaborators requires a paginated REST call; rather than bake that into this PR, a shared visibility/collaborators helper is intended as a follow-up that get_file_contents, list_issues, search_issues, and issue_read can all share. TODO(fides) marker is at the call site.

Tests

Test_GetFileContents_IFC_InsidersMode mirrors Test_ListIssues_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=trusted, confidentiality=["<owner>"].

Existing Test_GetFileContents cases are unchanged (the GetReposByOwnerByRepo mock is already wired in those cases — its response is just inspected only when insiders is on).

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.

Copilot AI review requested due to automatic review settings May 11, 2026 16:43
@gokhanarkan gokhanarkan requested a review from a team as a code owner May 11, 2026 16:43
@gokhanarkan gokhanarkan self-assigned this May 11, 2026
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 IFC SecurityLabel annotations to the get_file_contents tool result behind InsidersMode, aligning this ingress tool with the existing _meta.ifc pattern used by other tools (e.g., get_me, list_issues).

Changes:

  • Add ifc.LabelGetFileContents(isPrivate, readers) helper for computing labels for get_file_contents.
  • Add FetchRepoIsPrivate(ctx, client, owner, repo) helper and use it (lazily) to determine repo visibility when attaching IFC metadata.
  • Add unit tests covering insiders off / insiders on (public) / insiders on (private) label emission for get_file_contents.
Show a summary per file
File Description
pkg/ifc/ifc.go Adds LabelGetFileContents helper to compute IFC labels for file-content results.
pkg/github/repositories.go Adds FetchRepoIsPrivate and attaches _meta.ifc to successful get_file_contents responses in insiders mode.
pkg/github/repositories_test.go Adds Test_GetFileContents_IFC_InsidersMode to validate label emission behavior.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 4

Comment thread pkg/github/repositories.go Outdated
Comment thread pkg/github/repositories.go
Comment thread pkg/github/repositories_test.go
Comment thread pkg/github/repositories.go Outdated
@gokhanarkan gokhanarkan force-pushed the gokhanarkan/fides-get-file-contents branch from 41cf9f1 to 0803f48 Compare May 12, 2026 08:57
Base automatically changed from gokhanarkan/fides-list-issues to main May 12, 2026 09:55
Emits an IFC SecurityLabel on the get_file_contents tool result when the
InsidersMode flag is enabled, mirroring the pattern landed for get_me in

Public repositories are labelled PublicUntrusted (anyone can author file
content via pull requests). Private repositories are labelled
PrivateTrusted with the repository owner as a placeholder reader, since
only collaborators can land changes there. Full collaborator enumeration
is intentionally deferred to a follow-up shared helper.

A new exported FetchRepoIsPrivate helper wraps Repositories.Get for
visibility lookups; it is invoked lazily and only when InsidersMode is
on, so non-insiders pay no extra round trip. Visibility lookup failures
skip the label rather than fail the user-facing call.

Refs github/copilot-mcp-core#1623, github/copilot-mcp-core#1389.
- FetchRepoIsPrivate: tighten doc to 'returns whether a repository is
  private' and close the underlying *github.Response body.
- attachIFC: skip emitting the ifc label when the repository visibility
  lookup fails, instead of falling through to PublicUntrusted (which
  would mislabel a private or unknown-visibility repo as public). The
  failure is no longer cached so a subsequent return path can retry.
- Add a test asserting the tool still succeeds and omits result.Meta  ["ifc"] when the visibility lookup returns 500.
@gokhanarkan gokhanarkan force-pushed the gokhanarkan/fides-get-file-contents branch from 0803f48 to 4fc24be Compare May 12, 2026 10:46
@gokhanarkan gokhanarkan merged commit 0cdcd4a into main May 12, 2026
18 checks passed
@gokhanarkan gokhanarkan deleted the gokhanarkan/fides-get-file-contents branch May 12, 2026 14:42
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.

3 participants