diff --git a/src/comment.ts b/src/comment.ts index 1cc40a1..fa06497 100644 --- a/src/comment.ts +++ b/src/comment.ts @@ -379,7 +379,7 @@ export class CommentHandler { async postComment( context: Context, - message: LogReturn | Error, + message: LogReturn | Error | string, options: CommentOptions = { updateComment: true, raw: false } ): Promise | null> { await this._applyCommandResponsePolicy(context); @@ -390,8 +390,13 @@ export class CommentHandler { return null; } + // Convert string to LogReturn-like object + const logMessage: LogReturn | Error = typeof message === "string" + ? ({ raw: message, diff: message, metadata: {} } as LogReturn) + : message; + const shouldTagCommandResponse = this._shouldApplyCommandResponsePolicy(context); - const body = this._createCommentBody(context, message, { + const body = this._createCommentBody(context, logMessage, { ...options, commentKind: options.commentKind ?? (shouldTagCommandResponse ? COMMAND_RESPONSE_KIND : undefined), }); diff --git a/src/util.ts b/src/util.ts index 538f985..f355833 100644 --- a/src/util.ts +++ b/src/util.ts @@ -21,7 +21,17 @@ export interface Options/g, ">").replace(/--/g, "--"); + if (!obj) return "null"; + // Extract callstack-related fields that should be preserved unescaped for linking + const { stack, callstack, caller, ...content } = obj; + // Escape content fields normally + const escapedContent = JSON.stringify(content, null, 2).replace(//g, ">").replace(/--/g, "--"); + const contentObj = JSON.parse(escapedContent); + // Merge callstack fields back without additional escaping (they are safe values) + if (stack !== undefined) contentObj.stack = stack; + if (callstack !== undefined) contentObj.callstack = callstack; + if (caller !== undefined) contentObj.caller = caller; + return JSON.stringify(contentObj, null, 2); } /** diff --git a/tests/sanitize-metadata.test.ts b/tests/sanitize-metadata.test.ts new file mode 100644 index 0000000..dd5626d --- /dev/null +++ b/tests/sanitize-metadata.test.ts @@ -0,0 +1,45 @@ +import { describe, expect, it } from "@jest/globals"; +import { sanitizeMetadata } from "../src/util"; + +describe("sanitizeMetadata", () => { + it("escapes dangerous characters in content fields", () => { + const obj = { + message: "", + status: 200, + }; + const result = sanitizeMetadata(obj); + expect(result).toContain("<script>"); + expect(result).not.toContain("