Skip to content

Centralize sanitization of untrusted GitHub response fields - #3114

Merged
SamMorrowDrums merged 2 commits into
mainfrom
sammorrowdrums-issue-3106-apply-consistent-sanitization-to-untrust-18354a
Aug 19, 2026
Merged

Centralize sanitization of untrusted GitHub response fields#3114
SamMorrowDrums merged 2 commits into
mainfrom
sammorrowdrums-issue-3106-apply-consistent-sanitization-to-untrust-18354a

Conversation

@SamMorrowDrums

Copy link
Copy Markdown
Collaborator

Problem

Sanitization (pkg/sanitize.Sanitize) was applied ad hoc at a handful of tool call sites (GetIssue, GetPullRequest, ListPullRequests) instead of in the shared conversion layer. As a result, equivalent user-authored text returned by other tools — issue comments, PR reviews, review comments, releases, commit messages, discussions, project item titles — was returned completely unsanitized, and search_issues/search_pull_requests bypassed the converters entirely by marshaling raw *github.Issue objects.

Fix

Moved sanitization into the shared convertToMinimal* converters in pkg/github/minimal_types.go, which is the single conversion point used by nearly every read tool. This one change now consistently covers:

  • Issue/PR titles and bodies (REST and project-item paths)
  • Issue comments
  • PR reviews and review comments
  • Releases (name + body)
  • Commit messages (get_commit, list_commits, search_commits, list_pull_request_commits, file-commit responses, workflow run head commit)
  • Project item content titles and project pull-request-ref titles

Additional targeted fixes for paths that don't go through minimal_types.go:

  • Added a sanitizeIssueTitleAndBody helper used by search_issues (SearchIssueResult.MarshalJSON) and search_pull_requests (searchHandler), the only two tools that marshal a raw *github.Issue directly.
  • Discussions (list_discussions, get_discussion, get_discussion_comments) previously had no sanitization at all — fixed via a new newMinimalDiscussionComment constructor and inline fixes.
  • Project status update bodies.

Removed the now-redundant scattered sanitize calls in GetIssue, GetPullRequest, and ListPullRequests since the shared converters handle it now.

Fidelity preserved: patch/diff fields (MinimalCommitFile.Patch, MinimalPRFile.Patch) and raw file contents are intentionally left untouched — these must remain byte-exact so patches stay applicable and code isn't corrupted.

Testing

  • Added pkg/github/sanitize_coverage_test.go: table-driven regression tests covering every converter touched above, the search_issues/search_pull_requests raw-passthrough paths, the shared helper's nil-safety, and a fidelity check confirming patches/diffs are not altered.
  • Added a malicious-payload case to the existing Test_GetDiscussion table in discussions_test.go.
  • script/lint — 0 issues.
  • go test -race ./... (via script/test) — all packages pass.
  • No tool schemas changed, so no toolsnap or README/docs regeneration was required (verified via script/generate-docs producing no diff).

Fixes #3106

Copilot AI balanced review requested due to automatic review settings August 19, 2026 12:31
@SamMorrowDrums
SamMorrowDrums requested a review from a team as a code owner August 19, 2026 12:31

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

Centralizes sanitization of user-authored GitHub response fields while preserving patch and file-content fidelity.

Changes:

  • Sanitizes text in shared minimal-response converters.
  • Covers raw search and discussion response paths.
  • Adds broad sanitization regression tests.
Show a summary per file
File Description
pkg/github/minimal_types.go Sanitizes shared minimal response types.
pkg/github/issues.go Sanitizes raw issue-search results.
pkg/github/pullrequests.go Removes redundant call-site sanitization.
pkg/github/search_utils.go Sanitizes raw PR search results.
pkg/github/discussions.go Sanitizes discussion titles, bodies, and comments.
pkg/github/projects.go Sanitizes project status bodies.
pkg/github/sanitize_coverage_test.go Adds converter and fidelity regression tests.
pkg/github/discussions_test.go Tests malicious discussion content.

Review details

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

  • Files reviewed: 8/8 changed files
  • Comments generated: 3
  • Review effort level: Balanced

Comment thread pkg/github/minimal_types.go
Comment thread pkg/github/minimal_types.go
Comment thread pkg/github/projects.go
SamMorrowDrums and others added 2 commits August 19, 2026 14:53
Sanitization was previously applied ad hoc at a handful of tool call
sites (GetIssue, GetPullRequest, ListPullRequests) rather than in the
shared convertToMinimal* converters, so equivalent user-authored text
returned by other tools (issue comments, PR reviews, review comments,
releases, commit messages, discussions, project item titles) was
returned unsanitized.

- Apply sanitize.Sanitize inside the convertToMinimal* helpers in
  minimal_types.go for issue/PR titles and bodies, issue comments, PR
  reviews, review comments, releases, commit messages, and project
  item content titles. This is the single, shared conversion point
  used by nearly every read tool, so fixing it there covers get/list
  issues, pull requests, comments, reviews, review comments, releases,
  commits, and project items consistently.
- Add a sanitizeIssueTitleAndBody helper and use it for the two
  response paths that marshal a raw *github.Issue directly instead of
  a Minimal* type: search_issues (SearchIssueResult.MarshalJSON) and
  search_pull_requests (searchHandler).
- Sanitize discussion titles/bodies/comments (list_discussions,
  get_discussion, get_discussion_comments), which previously had no
  sanitization at all, via a new newMinimalDiscussionComment
  constructor and inline fixes.
- Sanitize project status update bodies.
- Remove the now-redundant scattered sanitize calls in GetIssue,
  GetPullRequest, and ListPullRequests now that the shared converters
  sanitize on their own.

Patches, diffs, and raw file contents are intentionally left
untouched to preserve fidelity.

Adds table-driven regression tests covering every touched converter,
the search_issues/search_pull_requests raw-passthrough paths, and a
fidelity check that patches/diffs are not altered.

Fixes #3106

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Route every MinimalIssueRef/MinimalPullRequestRef construction through shared
constructors that sanitize the user-authored title, so issue_dependency_read,
issue_dependency_write and find_duplicate no longer forward raw issue titles.

Also sanitize the get_file_blame commit message headline, after truncation so
the headline is still cut at the author's real first line break.

Extends the sanitization regression suite with the project status update body,
both ref constructors and the dependency ref, and adds tool-level regression
tests for find_duplicate and get_file_blame.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@SamMorrowDrums
SamMorrowDrums force-pushed the sammorrowdrums-issue-3106-apply-consistent-sanitization-to-untrust-18354a branch from 4f4917b to af11e05 Compare August 19, 2026 12:54
@SamMorrowDrums
SamMorrowDrums merged commit 912cce6 into main Aug 19, 2026
19 checks passed
@SamMorrowDrums
SamMorrowDrums deleted the sammorrowdrums-issue-3106-apply-consistent-sanitization-to-untrust-18354a branch August 19, 2026 13:20
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.

Apply consistent sanitization to untrusted GitHub response fields

2 participants