Skip to content

Annotate read tools with ifc labels#2671

Merged
SamMorrowDrums merged 5 commits into
mainfrom
add-ifc-tool-annotations
Jun 11, 2026
Merged

Annotate read tools with ifc labels#2671
SamMorrowDrums merged 5 commits into
mainfrom
add-ifc-tool-annotations

Conversation

@JoannaaKL

Copy link
Copy Markdown
Collaborator

What changed

Added ifc annotations to additional read tools. Behind a ifc_labels insiders flag.

MCP impact

  • No tool or API changes
  • Tool schema or behavior changed
  • New tool added

Security / limits

  • No security or limits impact
  • Auth / permissions considered
  • Data exposure, filtering, or token/size limits considered

Tool renaming

  • I am renaming tools as part of this PR (e.g. a part of a consolidation effort)
    • I have added the new tool aliases in deprecated_tool_aliases.go
  • I am not renaming tools as part of this PR

Note: if you're renaming tools, you must add the tool aliases. For more information on how to do so, please refer to the official docs.

Lint & tests

  • Linted locally with ./script/lint
  • Tested locally with ./script/test

Docs

  • Not needed
  • Updated (README / docs / examples)
Copilot AI review requested due to automatic review settings June 11, 2026 09:58
@JoannaaKL JoannaaKL requested a review from a team as a code owner June 11, 2026 09:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds/expands IFC (Information Flow Control) labeling across additional read-only GitHub MCP tools, gated behind the ifc_labels insiders feature flag, to help downstream clients reason about confidentiality/integrity of tool outputs.

Changes:

  • Adds new IFC label constructors for additional GitHub data domains (repo metadata, commit content, Actions results, advisories, gists, projects, teams, notifications).
  • Introduces shared helpers (attach*IFCLabel, newRepoVisibilityIFCLabeler) to consistently gate/attach labels and avoid repeated visibility lookups.
  • Wires IFC label attachment into more read tools (repos, search, PRs, Actions, discussions, labels, security tools) and adds/extends unit tests.
Show a summary per file
File Description
pkg/ifc/ifc.go Adds new IFC label functions for additional resource types.
pkg/ifc/ifc_test.go Adds unit tests covering the new IFC label functions.
pkg/github/ifc_labels.go Centralizes IFC label attachment helpers and feature-flag gating.
pkg/github/security_advisories.go Attaches IFC labels to advisory tools (global/repo/org).
pkg/github/secret_scanning.go Attaches static private-untrusted IFC labels to secret scanning results.
pkg/github/dependabot.go Attaches static private-untrusted IFC labels to Dependabot alert results.
pkg/github/code_scanning.go Attaches static private-untrusted IFC labels to code scanning alert results.
pkg/github/search.go Centralizes search-related IFC labeling and adds IFC labeling for more search tools.
pkg/github/repositories.go Attaches repo-visibility-derived IFC labels to commit/branch/tag/release/collaborator read tools and refactors get_file_contents labeling to shared helper.
pkg/github/repositories_test.go Adds a feature-flag/visibility-lookup behavior test for IFC labeling on get_commit.
pkg/github/issues.go Refactors IFC label attachment to shared helper and labels additional issue metadata tools.
pkg/github/issue_fields.go Labels issue field definition results (repo-scoped vs org-scoped).
pkg/github/pullrequests.go Attaches repo-visibility-derived IFC labels for pull request read methods and search.
pkg/github/actions.go Attaches repo-visibility-derived IFC labels across GitHub Actions list/get/log tools.
pkg/github/discussions.go Attaches repo-visibility-derived IFC labels to discussion read tools and category listing.
pkg/github/labels.go Attaches repo-visibility-derived IFC labels to label read tools (GraphQL-backed).
pkg/github/git.go Attaches commit-contents IFC label to repository tree tool results.
pkg/github/gists.go Attaches gist/gist-list IFC labels to gist read tools.
pkg/github/projects.go Attaches conservative project IFC labels to project read tools.
pkg/github/context_tools.go Refactors to shared static IFC label attachment for user/team tools.
pkg/github/notifications.go Attaches static IFC label to notification details tool results.

Copilot's findings

  • Files reviewed: 21/21 changed files
  • Comments generated: 1
Comment thread pkg/github/security_advisories.go
Repository security advisory listings can include draft/triage/closed
advisories (via the state filter), which are not world-readable even on a
public repository. Deriving confidentiality from repo visibility alone
under-classified those results as public.

LabelRepositorySecurityAdvisory now takes an allPublished flag and only
returns a public label when the repo is public AND every returned advisory
is published; otherwise it is private. list_repository_security_advisories
computes allPublished from the response state; the org-wide listing stays
private-untrusted. Adds unit + handler regression tests covering the
draft-advisory-on-public-repo case.

Addresses PR review feedback.
…ors, get_me

Audit for the same bug class as the repo-advisory fix (confidentiality
derived from a coarse signal that misses access-restricted items) found
three more under-classifications:

- Releases (list_releases, get_latest_release, get_release_by_tag): draft
  releases are visible only to push-access users and are not world-readable
  even on a public repo. New LabelRelease(isPrivate, hasDraft) returns public
  only for a non-draft release on a public repo; handlers compute hasDraft
  from the response (Draft flag / per-item scan).
- list_repository_collaborators: a collaborator roster requires push access
  to list, so it is never world-readable, not even on a public repo. New
  LabelCollaboratorRoster() is always PrivateTrusted (mirrors LabelTeam),
  replacing the repo-visibility-derived label.
- get_me: the result includes private_gists / total_private_repos /
  owned_private_repos, which are not part of the public profile. LabelGetMe
  is now PrivateTrusted instead of PublicTrusted.

Verified the remaining public-capable labels are sound: Actions logs are
world-readable on public repos; branches/tags are public metadata; gist,
project, search, and starred-repo labels read per-item visibility and join.

Adds ifc unit tests for the new/changed labels and a get_release_by_tag
handler regression test (draft on public repo -> private); updates the
get_me handler test to assert private.
Explain on LabelSearchIssues (and cross-ref from LabelGistList) that a tool
result is delivered as one opaque payload and the IFC engine makes one
allow/deny decision per flow at egress, so the only sound bound for a list is
the meet of every item's label. Per-item labels would only be load-bearing if
the engine could partition a result and route items to different sinks; until
then they would invite unsafe declassification of a public item that arrived
alongside private data. Doc-only change.

@SamMorrowDrums SamMorrowDrums left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed and approving. The IFC label model is well-reasoned — the join-as-meet documentation on LabelSearchIssues and the "omit on visibility-lookup failure rather than risk misclassification" invariant in the attach* helpers are exactly right.

Two things I checked specifically:

  • Context cost when disabled: nil. The attach* helpers early-return on !IsFeatureEnabled, labels live in _meta.ifc (not schemas/descriptions), so output is byte-identical when the flag is off.
  • The InsidersFeatureFlags removal: this demotes ifc_labels to opt-in-only (still in AllowedFeatureFlags), so insiders builds no longer auto-pay the extra repo-visibility lookups / _meta bytes. Good call as the labeled-tool surface grows — though note the PR description still says "behind an insiders flag," which is now slightly stale (it's opt-in via --features ifc_labels).

CI green across all 19 checks, good test coverage in ifc_test.go and the per-tool tests. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants