diff --git a/pkg/github/issues.go b/pkg/github/issues.go index 62db8d48d..d950652e3 100644 --- a/pkg/github/issues.go +++ b/pkg/github/issues.go @@ -1243,6 +1243,10 @@ func AddIssueComment(t translations.TranslationHelperFunc) inventory.ServerTool var commentResponse *MinimalResponse if hasBody { + body = sanitize.FilterInvisibleCharacters(body) + if body == "" { + return utils.NewToolResultError("body cannot be empty after removing invisible characters"), nil, nil + } comment := &github.IssueComment{ Body: github.Ptr(body), } diff --git a/pkg/github/issues_test.go b/pkg/github/issues_test.go index 3be4fe1b5..a2ae1dde5 100644 --- a/pkg/github/issues_test.go +++ b/pkg/github/issues_test.go @@ -4154,6 +4154,32 @@ func TestAddIssueComment(t *testing.T) { "body": "This is a comment", }, }, + { + name: "strips invisible characters from comment body before posting", + mockedClient: MockHTTPClientWithHandlers(map[string]http.HandlerFunc{ + PostReposIssuesCommentsByOwnerByRepoByIssueNumber: expect(t, expectations{ + path: "/repos/owner/repo/issues/42/comments", + requestBody: map[string]any{"body": "@dependabot rebase"}, + }).andThen(mockResponse(t, http.StatusCreated, mockComment)), + }), + requestArgs: map[string]any{ + "owner": "owner", + "repo": "repo", + "issue_number": float64(42), + "body": "\u2068@\u2069\u2068d\u2069ependabot rebase", + }, + }, + { + name: "rejects comment body that is only invisible characters", + requestArgs: map[string]any{ + "owner": "owner", + "repo": "repo", + "issue_number": float64(42), + "body": "\u200B\u2068\u2069", + }, + expectToolError: true, + expectedToolErrMsg: "body cannot be empty after removing invisible characters", + }, { name: "successful reaction to issue", mockedClient: MockHTTPClientWithHandlers(map[string]http.HandlerFunc{