From c6c19e0fb7898c6c32d557ee38ed003a40f57472 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 24 Feb 2026 17:42:20 +0000 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=94=92=20[security=20fix]=20Fix=20sen?= =?UTF-8?q?sitive=20data=20exposure=20in=20logs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Change core.info to core.debug for model responses in src/inference.ts - Change core.info to core.debug for tool execution details in src/mcp.ts - Change core.info to core.debug for custom header logging in src/helpers.ts - Remove sensitive response previews from error messages in src/inference.ts - Update tests to reflect changes from core.info to core.debug --- __tests__/helpers.test.ts | 26 +++++++++++++------------- __tests__/inference.test.ts | 4 ++-- __tests__/mcp.test.ts | 4 ++-- src/helpers.ts | 4 ++-- src/inference.ts | 10 ++++------ src/mcp.ts | 4 ++-- 6 files changed, 25 insertions(+), 27 deletions(-) diff --git a/__tests__/helpers.test.ts b/__tests__/helpers.test.ts index fe22b76..fddd05d 100644 --- a/__tests__/helpers.test.ts +++ b/__tests__/helpers.test.ts @@ -150,9 +150,9 @@ X-Custom-Header: custom-value` header2: 'value2', 'X-Custom-Header': 'custom-value', }) - expect(core.info).toHaveBeenCalledWith('Custom header added: header1: value1') - expect(core.info).toHaveBeenCalledWith('Custom header added: header2: value2') - expect(core.info).toHaveBeenCalledWith('Custom header added: X-Custom-Header: custom-value') + expect(core.debug).toHaveBeenCalledWith('Custom header added: header1: value1') + expect(core.debug).toHaveBeenCalledWith('Custom header added: header2: value2') + expect(core.debug).toHaveBeenCalledWith('Custom header added: X-Custom-Header: custom-value') }) it('parses JSON format headers correctly', () => { @@ -165,9 +165,9 @@ X-Custom-Header: custom-value` header2: 'value2', 'X-Team': 'engineering', }) - expect(core.info).toHaveBeenCalledWith('Custom header added: header1: value1') - expect(core.info).toHaveBeenCalledWith('Custom header added: header2: value2') - expect(core.info).toHaveBeenCalledWith('Custom header added: X-Team: engineering') + expect(core.debug).toHaveBeenCalledWith('Custom header added: header1: value1') + expect(core.debug).toHaveBeenCalledWith('Custom header added: header2: value2') + expect(core.debug).toHaveBeenCalledWith('Custom header added: X-Team: engineering') }) it('returns empty object for empty input', () => { @@ -194,13 +194,13 @@ password: pass123` }) // Sensitive headers should be masked - expect(core.info).toHaveBeenCalledWith('Custom header added: Ocp-Apim-Subscription-Key: ***MASKED***') - expect(core.info).toHaveBeenCalledWith('Custom header added: X-Api-Token: ***MASKED***') - expect(core.info).toHaveBeenCalledWith('Custom header added: Authorization: ***MASKED***') - expect(core.info).toHaveBeenCalledWith('Custom header added: password: ***MASKED***') + expect(core.debug).toHaveBeenCalledWith('Custom header added: Ocp-Apim-Subscription-Key: ***MASKED***') + expect(core.debug).toHaveBeenCalledWith('Custom header added: X-Api-Token: ***MASKED***') + expect(core.debug).toHaveBeenCalledWith('Custom header added: Authorization: ***MASKED***') + expect(core.debug).toHaveBeenCalledWith('Custom header added: password: ***MASKED***') // Non-sensitive headers should not be masked - expect(core.info).toHaveBeenCalledWith('Custom header added: serviceName: my-service') + expect(core.debug).toHaveBeenCalledWith('Custom header added: serviceName: my-service') }) it('validates header names and skips invalid ones', () => { @@ -367,8 +367,8 @@ systemID: terraform-ci` }) // Only the subscription key should be masked - expect(core.info).toHaveBeenCalledWith('Custom header added: Ocp-Apim-Subscription-Key: ***MASKED***') - expect(core.info).toHaveBeenCalledWith('Custom header added: serviceName: terraform-plan-workflow') + expect(core.debug).toHaveBeenCalledWith('Custom header added: Ocp-Apim-Subscription-Key: ***MASKED***') + expect(core.debug).toHaveBeenCalledWith('Custom header added: serviceName: terraform-plan-workflow') }) }) }) diff --git a/__tests__/inference.test.ts b/__tests__/inference.test.ts index 5c10fc6..c90214c 100644 --- a/__tests__/inference.test.ts +++ b/__tests__/inference.test.ts @@ -58,7 +58,7 @@ describe('inference.ts', () => { expect(result).toBe('Hello, user!') expect(core.info).toHaveBeenCalledWith('Running simple inference without tools') - expect(core.info).toHaveBeenCalledWith('Model response: Hello, user!') + expect(core.debug).toHaveBeenCalledWith('Model response: Hello, user!') // Verify the request structure expect(mockCreate).toHaveBeenCalledWith({ @@ -136,7 +136,7 @@ describe('inference.ts', () => { const result = await simpleInference(mockRequest) expect(result).toBeNull() - expect(core.info).toHaveBeenCalledWith('Model response: No response content') + expect(core.debug).toHaveBeenCalledWith('Model response: No response content') }) it('includes response format when specified', async () => { diff --git a/__tests__/mcp.test.ts b/__tests__/mcp.test.ts index f8a37bf..fea06cb 100644 --- a/__tests__/mcp.test.ts +++ b/__tests__/mcp.test.ts @@ -177,8 +177,8 @@ describe('mcp.ts', () => { name: 'test-tool', content: JSON.stringify(toolResult.content), }) - expect(core.info).toHaveBeenCalledWith('Executing GitHub MCP tool: test-tool with args: {"param": "value"}') - expect(core.info).toHaveBeenCalledWith('GitHub MCP tool test-tool executed successfully') + expect(core.debug).toHaveBeenCalledWith('Executing GitHub MCP tool: test-tool with args: {"param": "value"}') + expect(core.debug).toHaveBeenCalledWith('GitHub MCP tool test-tool executed successfully') }) it('handles tool execution errors gracefully', async () => { diff --git a/src/helpers.ts b/src/helpers.ts index ff79c0e..3482270 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -143,9 +143,9 @@ function validateAndMaskHeaders(headers: Record): Record lowerName.includes(pattern)) if (isSensitive) { - core.info(`Custom header added: ${name}: ***MASKED***`) + core.debug(`Custom header added: ${name}: ***MASKED***`) } else { - core.info(`Custom header added: ${name}: ${stringValue}`) + core.debug(`Custom header added: ${name}: ${stringValue}`) } } diff --git a/src/inference.ts b/src/inference.ts index c7880d7..a77dbe9 100644 --- a/src/inference.ts +++ b/src/inference.ts @@ -61,7 +61,7 @@ export async function simpleInference(request: InferenceRequest): Promise { - core.info(`Executing GitHub MCP tool: ${toolCall.function.name} with args: ${toolCall.function.arguments}`) + core.debug(`Executing GitHub MCP tool: ${toolCall.function.name} with args: ${toolCall.function.arguments}`) try { const args = JSON.parse(toolCall.function.arguments) @@ -106,7 +106,7 @@ export async function executeToolCall(githubMcpClient: Client, toolCall: ToolCal arguments: args, }) - core.info(`GitHub MCP tool ${toolCall.function.name} executed successfully`) + core.debug(`GitHub MCP tool ${toolCall.function.name} executed successfully`) return { tool_call_id: toolCall.id, From 326b9a12f48dd7bd841a3feecb1626c1909fedd5 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 24 Feb 2026 17:44:57 +0000 Subject: [PATCH 2/4] chore: relax HTTP header name validation to match RFC 7230 Updated the regex in `src/helpers.ts` to allow all valid characters in an HTTP token (RFC 7230, section 3.2.6), including symbols like `_`, `.`, `!`, and `*`. Previously, the validation was overly restrictive, only allowing alphanumeric characters and hyphens. Also updated the corresponding unit test in `__tests__/helpers.test.ts` to reflect the change. --- __tests__/helpers.test.ts | 4 +--- src/helpers.ts | 7 ++++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/__tests__/helpers.test.ts b/__tests__/helpers.test.ts index fe22b76..e8f4629 100644 --- a/__tests__/helpers.test.ts +++ b/__tests__/helpers.test.ts @@ -214,13 +214,11 @@ valid123: value5` expect(result).toEqual({ 'valid-header': 'value1', + invalid_underscore: 'value3', valid123: 'value5', }) expect(core.warning).toHaveBeenCalledWith(expect.stringContaining('Skipping invalid header name: invalid header')) - expect(core.warning).toHaveBeenCalledWith( - expect.stringContaining('Skipping invalid header name: invalid_underscore'), - ) expect(core.warning).toHaveBeenCalledWith(expect.stringContaining('Skipping invalid header name: invalid@header')) }) diff --git a/src/helpers.ts b/src/helpers.ts index ff79c0e..7ff3ce8 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -121,9 +121,10 @@ function validateAndMaskHeaders(headers: Record): Record Date: Wed, 25 Feb 2026 04:12:17 +0000 Subject: [PATCH 3/4] test: validate non-string file paths in parseFileTemplateVariables Add test cases to verify that `parseFileTemplateVariables` correctly throws an error when a non-string value (e.g. number, boolean, object) is provided as a file path in the input YAML. This ensures the existing validation is properly tested. Co-authored-by: Pet3cy <169947521+Pet3cy@users.noreply.github.com> --- __tests__/prompt.test.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/__tests__/prompt.test.ts b/__tests__/prompt.test.ts index 2eba81d..686eacd 100644 --- a/__tests__/prompt.test.ts +++ b/__tests__/prompt.test.ts @@ -135,5 +135,17 @@ describe('prompt.ts', () => { it('errors on missing files', () => { expect(() => parseFileTemplateVariables('x: ./does-not-exist.txt')).toThrow('was not found') }) + + it('errors on non-string file paths', () => { + expect(() => parseFileTemplateVariables('x: 123')).toThrow( + "File template variable 'x' must be a string file path", + ) + expect(() => parseFileTemplateVariables('x: true')).toThrow( + "File template variable 'x' must be a string file path", + ) + expect(() => parseFileTemplateVariables('x: { nested: "object" }')).toThrow( + "File template variable 'x' must be a string file path", + ) + }) }) }) From 9d962e5274fa65d8ef5c4887e7a2fbeeda7b8a59 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 22:44:58 +0000 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=94=92=20[security=20fix]=20Mask=20se?= =?UTF-8?q?nsitive=20tokens=20in=20GitHub=20Actions=20logs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added `core.setSecret(token)` to mask the primary GitHub token. - Added `core.setSecret(githubMcpToken)` to mask the GitHub MCP token. - Updated `__fixtures__/core.ts` to include the `setSecret` mock. - Updated `__tests__/main.test.ts` to verify `setSecret` is called for the tokens. --- __fixtures__/core.ts | 1 + __tests__/main.test.ts | 2 ++ src/main.ts | 3 +++ 3 files changed, 6 insertions(+) diff --git a/__fixtures__/core.ts b/__fixtures__/core.ts index efe7ebe..becbebd 100644 --- a/__fixtures__/core.ts +++ b/__fixtures__/core.ts @@ -9,3 +9,4 @@ export const getBooleanInput = vi.fn() export const setOutput = vi.fn() export const setFailed = vi.fn() export const warning = vi.fn() +export const setSecret = vi.fn() diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index 578bf98..387e064 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -136,6 +136,7 @@ describe('main.ts', () => { await run() expect(core.setOutput).toHaveBeenCalled() + expect(core.setSecret).toHaveBeenCalledWith('fake-token') verifyStandardResponse() expect(mockProcessExit).toHaveBeenCalledWith(0) }) @@ -199,6 +200,7 @@ describe('main.ts', () => { await run() + expect(core.setSecret).toHaveBeenCalledWith('fake-token') expect(mockConnectToGitHubMCP).toHaveBeenCalledWith('fake-token', '') expect(mockMcpInference).toHaveBeenCalledWith( expect.objectContaining({ diff --git a/src/main.ts b/src/main.ts index 18febc1..73c768a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -61,9 +61,12 @@ export async function run(): Promise { if (token === undefined) { throw new Error('GITHUB_TOKEN is not set') } + core.setSecret(token) // Get GitHub MCP token (use dedicated token if provided, otherwise fall back to main token) const githubMcpToken = core.getInput('github-mcp-token') || token + core.setSecret(githubMcpToken) + const githubMcpToolsets = core.getInput('github-mcp-toolsets') const endpoint = core.getInput('endpoint')