From 52122d075364aebbb0cc4926b844a89241200385 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 16 Jun 2026 05:46:16 +0000 Subject: [PATCH 1/6] chore: narrow POC scope to PR outcomes and safe output outcomes only (#39484) From 0c964b43eabb41837a069ce13fbf31805408cf52 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 16 Jun 2026 05:46:18 +0000 Subject: [PATCH 2/6] jsweep: clean validate_lockdown_requirements.cjs - Remove unused ERR_VALIDATION import - Extract failWithError helper to eliminate repeated setOutput+setFailed+throw pattern (DRY) - Use template literals with \n for multi-line error messages instead of string concatenation - Add 6 new tests: setOutput side-effects, multiple tokens, error message newline formatting Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../js/validate_lockdown_requirements.cjs | 90 +++++++++---------- .../validate_lockdown_requirements.test.cjs | 82 +++++++++++++++++ 2 files changed, 127 insertions(+), 45 deletions(-) diff --git a/actions/setup/js/validate_lockdown_requirements.cjs b/actions/setup/js/validate_lockdown_requirements.cjs index 14f74a99b30..53386579f6f 100644 --- a/actions/setup/js/validate_lockdown_requirements.cjs +++ b/actions/setup/js/validate_lockdown_requirements.cjs @@ -22,8 +22,17 @@ * @param {any} core - GitHub Actions core library * @returns {void} */ -const { ERR_VALIDATION } = require("./error_codes.cjs"); function validateLockdownRequirements(core) { + /** + * @param {string} message + * @returns {never} + */ + function failWithError(message) { + core.setOutput("lockdown_check_failed", "true"); + core.setFailed(message); + throw new Error(message); + } + // Check if lockdown mode is explicitly enabled (set to "true" in frontmatter) const lockdownEnabled = process.env.GITHUB_MCP_LOCKDOWN_EXPLICIT === "true"; @@ -46,22 +55,19 @@ function validateLockdownRequirements(core) { core.info(`Custom github-token configured: ${hasCustomToken}`); if (!hasAnyCustomToken) { - const errorMessage = - "Lockdown mode is enabled (lockdown: true) but no custom GitHub token is configured.\\n" + - "\\n" + - "Please configure one of the following as a repository secret:\\n" + - " - GH_AW_GITHUB_TOKEN (recommended)\\n" + - " - GH_AW_GITHUB_MCP_SERVER_TOKEN (alternative)\\n" + - " - Custom github-token in your workflow frontmatter\\n" + - "\\n" + - "See: https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/auth.mdx\\n" + - "\\n" + - "To set a token:\\n" + - ' gh aw secrets set GH_AW_GITHUB_TOKEN --value "YOUR_FINE_GRAINED_PAT"'; - - core.setOutput("lockdown_check_failed", "true"); - core.setFailed(errorMessage); - throw new Error(errorMessage); + failWithError( + `Lockdown mode is enabled (lockdown: true) but no custom GitHub token is configured.\n` + + `\n` + + `Please configure one of the following as a repository secret:\n` + + ` - GH_AW_GITHUB_TOKEN (recommended)\n` + + ` - GH_AW_GITHUB_MCP_SERVER_TOKEN (alternative)\n` + + ` - Custom github-token in your workflow frontmatter\n` + + `\n` + + `See: https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/auth.mdx\n` + + `\n` + + `To set a token:\n` + + ` gh aw secrets set GH_AW_GITHUB_TOKEN --value "YOUR_FINE_GRAINED_PAT"` + ); } core.info("✓ Lockdown mode requirements validated: Custom GitHub token is configured"); @@ -77,20 +83,17 @@ function validateLockdownRequirements(core) { core.info(`Compiled with strict mode: ${isStrict}`); if (isPublic && !isStrict) { - const errorMessage = - "This workflow is running on a public repository but was not compiled with strict mode.\\n" + - "\\n" + - "Public repository workflows must be compiled with strict mode enabled to meet\\n" + - "the security requirements for public exposure.\\n" + - "\\n" + - "To fix this, recompile the workflow with strict mode:\\n" + - " gh aw compile --strict\\n" + - "\\n" + - "See: https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/security.mdx"; - - core.setOutput("lockdown_check_failed", "true"); - core.setFailed(errorMessage); - throw new Error(errorMessage); + failWithError( + `This workflow is running on a public repository but was not compiled with strict mode.\n` + + `\n` + + `Public repository workflows must be compiled with strict mode enabled to meet\n` + + `the security requirements for public exposure.\n` + + `\n` + + `To fix this, recompile the workflow with strict mode:\n` + + ` gh aw compile --strict\n` + + `\n` + + `See: https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/security.mdx` + ); } if (isPublic && isStrict) { @@ -104,20 +107,17 @@ function validateLockdownRequirements(core) { // and potentially exfiltrate secrets or cause unintended side effects. const eventName = process.env.GITHUB_EVENT_NAME; if (isPublic && eventName === "pull_request_target") { - const errorMessage = - "This workflow is triggered by the pull_request_target event on a public repository.\\n" + - "\\n" + - "The pull_request_target event is not allowed on public repositories because it runs\\n" + - "workflows with access to repository secrets even when triggered from a fork, which\\n" + - 'creates a significant security risk (known as a "pwn request").\\n' + - "\\n" + - "To fix this, use the pull_request event instead, or migrate to a private repository.\\n" + - "\\n" + - "See: https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/security.mdx"; - - core.setOutput("lockdown_check_failed", "true"); - core.setFailed(errorMessage); - throw new Error(errorMessage); + failWithError( + `This workflow is triggered by the pull_request_target event on a public repository.\n` + + `\n` + + `The pull_request_target event is not allowed on public repositories because it runs\n` + + `workflows with access to repository secrets even when triggered from a fork, which\n` + + `creates a significant security risk (known as a "pwn request").\n` + + `\n` + + `To fix this, use the pull_request event instead, or migrate to a private repository.\n` + + `\n` + + `See: https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/security.mdx` + ); } } diff --git a/actions/setup/js/validate_lockdown_requirements.test.cjs b/actions/setup/js/validate_lockdown_requirements.test.cjs index e6e2a323ad1..bb9f3cdf3c7 100644 --- a/actions/setup/js/validate_lockdown_requirements.test.cjs +++ b/actions/setup/js/validate_lockdown_requirements.test.cjs @@ -304,4 +304,86 @@ describe("validate_lockdown_requirements", () => { expect(mockCore.setFailed).toHaveBeenCalledWith(expect.stringContaining("not compiled with strict mode")); }); }); + + describe("setOutput side effects", () => { + it("should not set lockdown_check_failed output on a fully successful run", () => { + // All conditions pass: no lockdown, private repo, no special event + process.env.GITHUB_REPOSITORY_VISIBILITY = "private"; + process.env.GITHUB_EVENT_NAME = "push"; + + validateLockdownRequirements(mockCore); + + expect(mockCore.setOutput).not.toHaveBeenCalled(); + expect(mockCore.setFailed).not.toHaveBeenCalled(); + }); + + it("should not set lockdown_check_failed when lockdown is enabled with token and repo is private", () => { + process.env.GITHUB_MCP_LOCKDOWN_EXPLICIT = "true"; + process.env.GH_AW_GITHUB_TOKEN = "ghp_test"; + process.env.GITHUB_REPOSITORY_VISIBILITY = "private"; + + validateLockdownRequirements(mockCore); + + expect(mockCore.setOutput).not.toHaveBeenCalled(); + }); + }); + + describe("multiple tokens", () => { + it("should pass when all three tokens are configured simultaneously", () => { + process.env.GITHUB_MCP_LOCKDOWN_EXPLICIT = "true"; + process.env.GH_AW_GITHUB_TOKEN = "ghp_token1"; + process.env.GH_AW_GITHUB_MCP_SERVER_TOKEN = "ghp_token2"; + process.env.CUSTOM_GITHUB_TOKEN = "ghp_token3"; + + validateLockdownRequirements(mockCore); + + expect(mockCore.setFailed).not.toHaveBeenCalled(); + expect(mockCore.info).toHaveBeenCalledWith("GH_AW_GITHUB_TOKEN configured: true"); + expect(mockCore.info).toHaveBeenCalledWith("GH_AW_GITHUB_MCP_SERVER_TOKEN configured: true"); + expect(mockCore.info).toHaveBeenCalledWith("Custom github-token configured: true"); + expect(mockCore.info).toHaveBeenCalledWith("✓ Lockdown mode requirements validated: Custom GitHub token is configured"); + }); + }); + + describe("error message formatting", () => { + it("should include newlines in lockdown error message for readability", () => { + process.env.GITHUB_MCP_LOCKDOWN_EXPLICIT = "true"; + + expect(() => { + validateLockdownRequirements(mockCore); + }).toThrow(); + + const errorMsg = mockCore.setFailed.mock.calls[0][0]; + expect(errorMsg).toContain("\n"); + expect(errorMsg).toContain("GH_AW_GITHUB_TOKEN (recommended)"); + expect(errorMsg).toContain("GH_AW_GITHUB_MCP_SERVER_TOKEN (alternative)"); + }); + + it("should include newlines in strict mode error message for readability", () => { + process.env.GITHUB_REPOSITORY_VISIBILITY = "public"; + process.env.GH_AW_COMPILED_STRICT = "false"; + + expect(() => { + validateLockdownRequirements(mockCore); + }).toThrow(); + + const errorMsg = mockCore.setFailed.mock.calls[0][0]; + expect(errorMsg).toContain("\n"); + expect(errorMsg).toContain("gh aw compile --strict"); + }); + + it("should include newlines in pull_request_target error message for readability", () => { + process.env.GITHUB_REPOSITORY_VISIBILITY = "public"; + process.env.GH_AW_COMPILED_STRICT = "true"; + process.env.GITHUB_EVENT_NAME = "pull_request_target"; + + expect(() => { + validateLockdownRequirements(mockCore); + }).toThrow(); + + const errorMsg = mockCore.setFailed.mock.calls[0][0]; + expect(errorMsg).toContain("\n"); + expect(errorMsg).toContain("pwn request"); + }); + }); }); From 40525555b4a94d2008ee15ed439fc843ba3c226f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 16 Jun 2026 14:45:30 +0000 Subject: [PATCH 3/6] refactor lockdown validation messages into templates Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .../js/validate_lockdown_requirements.cjs | 40 ++----------- ...lidate_lockdown_requirements_templates.cjs | 59 +++++++++++++++++++ 2 files changed, 64 insertions(+), 35 deletions(-) create mode 100644 actions/setup/js/validate_lockdown_requirements_templates.cjs diff --git a/actions/setup/js/validate_lockdown_requirements.cjs b/actions/setup/js/validate_lockdown_requirements.cjs index 53386579f6f..d2b33afcfab 100644 --- a/actions/setup/js/validate_lockdown_requirements.cjs +++ b/actions/setup/js/validate_lockdown_requirements.cjs @@ -22,6 +22,8 @@ * @param {any} core - GitHub Actions core library * @returns {void} */ +const { renderLockdownTokenErrorMessage, renderPublicStrictModeErrorMessage, renderPullRequestTargetErrorMessage } = require("./validate_lockdown_requirements_templates.cjs"); + function validateLockdownRequirements(core) { /** * @param {string} message @@ -55,19 +57,7 @@ function validateLockdownRequirements(core) { core.info(`Custom github-token configured: ${hasCustomToken}`); if (!hasAnyCustomToken) { - failWithError( - `Lockdown mode is enabled (lockdown: true) but no custom GitHub token is configured.\n` + - `\n` + - `Please configure one of the following as a repository secret:\n` + - ` - GH_AW_GITHUB_TOKEN (recommended)\n` + - ` - GH_AW_GITHUB_MCP_SERVER_TOKEN (alternative)\n` + - ` - Custom github-token in your workflow frontmatter\n` + - `\n` + - `See: https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/auth.mdx\n` + - `\n` + - `To set a token:\n` + - ` gh aw secrets set GH_AW_GITHUB_TOKEN --value "YOUR_FINE_GRAINED_PAT"` - ); + failWithError(renderLockdownTokenErrorMessage()); } core.info("✓ Lockdown mode requirements validated: Custom GitHub token is configured"); @@ -83,17 +73,7 @@ function validateLockdownRequirements(core) { core.info(`Compiled with strict mode: ${isStrict}`); if (isPublic && !isStrict) { - failWithError( - `This workflow is running on a public repository but was not compiled with strict mode.\n` + - `\n` + - `Public repository workflows must be compiled with strict mode enabled to meet\n` + - `the security requirements for public exposure.\n` + - `\n` + - `To fix this, recompile the workflow with strict mode:\n` + - ` gh aw compile --strict\n` + - `\n` + - `See: https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/security.mdx` - ); + failWithError(renderPublicStrictModeErrorMessage()); } if (isPublic && isStrict) { @@ -107,17 +87,7 @@ function validateLockdownRequirements(core) { // and potentially exfiltrate secrets or cause unintended side effects. const eventName = process.env.GITHUB_EVENT_NAME; if (isPublic && eventName === "pull_request_target") { - failWithError( - `This workflow is triggered by the pull_request_target event on a public repository.\n` + - `\n` + - `The pull_request_target event is not allowed on public repositories because it runs\n` + - `workflows with access to repository secrets even when triggered from a fork, which\n` + - `creates a significant security risk (known as a "pwn request").\n` + - `\n` + - `To fix this, use the pull_request event instead, or migrate to a private repository.\n` + - `\n` + - `See: https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/security.mdx` - ); + failWithError(renderPullRequestTargetErrorMessage()); } } diff --git a/actions/setup/js/validate_lockdown_requirements_templates.cjs b/actions/setup/js/validate_lockdown_requirements_templates.cjs new file mode 100644 index 00000000000..ac564c22cec --- /dev/null +++ b/actions/setup/js/validate_lockdown_requirements_templates.cjs @@ -0,0 +1,59 @@ +// @ts-check + +const { renderTemplate } = require("./messages_core.cjs"); + +const LOCKDOWN_TOKEN_ERROR_TEMPLATE = `Lockdown mode is enabled (lockdown: true) but no custom GitHub token is configured. + +Please configure one of the following as a repository secret: + - GH_AW_GITHUB_TOKEN (recommended) + - GH_AW_GITHUB_MCP_SERVER_TOKEN (alternative) + - Custom github-token in your workflow frontmatter + +See: {auth_docs_url} + +To set a token: + gh aw secrets set GH_AW_GITHUB_TOKEN --value "YOUR_FINE_GRAINED_PAT"`; + +const PUBLIC_STRICT_MODE_ERROR_TEMPLATE = `This workflow is running on a public repository but was not compiled with strict mode. + +Public repository workflows must be compiled with strict mode enabled to meet +the security requirements for public exposure. + +To fix this, recompile the workflow with strict mode: + {strict_compile_command} + +See: {security_docs_url}`; + +const PULL_REQUEST_TARGET_ERROR_TEMPLATE = `This workflow is triggered by the pull_request_target event on a public repository. + +The pull_request_target event is not allowed on public repositories because it runs +workflows with access to repository secrets even when triggered from a fork, which +creates a significant security risk (known as a "pwn request"). + +To fix this, use the pull_request event instead, or migrate to a private repository. + +See: {security_docs_url}`; + +const TEMPLATE_CONTEXT = { + auth_docs_url: "https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/auth.mdx", + security_docs_url: "https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/security.mdx", + strict_compile_command: "gh aw compile --strict", +}; + +function renderLockdownTokenErrorMessage() { + return renderTemplate(LOCKDOWN_TOKEN_ERROR_TEMPLATE, TEMPLATE_CONTEXT); +} + +function renderPublicStrictModeErrorMessage() { + return renderTemplate(PUBLIC_STRICT_MODE_ERROR_TEMPLATE, TEMPLATE_CONTEXT); +} + +function renderPullRequestTargetErrorMessage() { + return renderTemplate(PULL_REQUEST_TARGET_ERROR_TEMPLATE, TEMPLATE_CONTEXT); +} + +module.exports = { + renderLockdownTokenErrorMessage, + renderPublicStrictModeErrorMessage, + renderPullRequestTargetErrorMessage, +}; From 22aa72f0b81b31f6c1b8c4cb44cf530e589380ed Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 16 Jun 2026 14:48:24 +0000 Subject: [PATCH 4/6] style: move lockdown template import to file top Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/validate_lockdown_requirements.cjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actions/setup/js/validate_lockdown_requirements.cjs b/actions/setup/js/validate_lockdown_requirements.cjs index d2b33afcfab..d69d45f0263 100644 --- a/actions/setup/js/validate_lockdown_requirements.cjs +++ b/actions/setup/js/validate_lockdown_requirements.cjs @@ -1,5 +1,7 @@ // @ts-check +const { renderLockdownTokenErrorMessage, renderPublicStrictModeErrorMessage, renderPullRequestTargetErrorMessage } = require("./validate_lockdown_requirements_templates.cjs"); + /** * Validates that lockdown mode requirements are met at runtime. * @@ -22,8 +24,6 @@ * @param {any} core - GitHub Actions core library * @returns {void} */ -const { renderLockdownTokenErrorMessage, renderPublicStrictModeErrorMessage, renderPullRequestTargetErrorMessage } = require("./validate_lockdown_requirements_templates.cjs"); - function validateLockdownRequirements(core) { /** * @param {string} message From 625bc907a4204eb8a85e0720ecced4fa15381e1d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 16 Jun 2026 17:00:21 +0000 Subject: [PATCH 5/6] test: focus lockdown error assertions on behavior Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .../js/validate_lockdown_requirements.test.cjs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/actions/setup/js/validate_lockdown_requirements.test.cjs b/actions/setup/js/validate_lockdown_requirements.test.cjs index bb9f3cdf3c7..7fb9313e8fb 100644 --- a/actions/setup/js/validate_lockdown_requirements.test.cjs +++ b/actions/setup/js/validate_lockdown_requirements.test.cjs @@ -345,44 +345,41 @@ describe("validate_lockdown_requirements", () => { }); }); - describe("error message formatting", () => { - it("should include newlines in lockdown error message for readability", () => { + describe("error messages", () => { + it("should include token guidance in lockdown error message", () => { process.env.GITHUB_MCP_LOCKDOWN_EXPLICIT = "true"; expect(() => { validateLockdownRequirements(mockCore); - }).toThrow(); + }).toThrow("no custom GitHub token is configured"); const errorMsg = mockCore.setFailed.mock.calls[0][0]; - expect(errorMsg).toContain("\n"); expect(errorMsg).toContain("GH_AW_GITHUB_TOKEN (recommended)"); expect(errorMsg).toContain("GH_AW_GITHUB_MCP_SERVER_TOKEN (alternative)"); }); - it("should include newlines in strict mode error message for readability", () => { + it("should include compile guidance in strict mode error message", () => { process.env.GITHUB_REPOSITORY_VISIBILITY = "public"; process.env.GH_AW_COMPILED_STRICT = "false"; expect(() => { validateLockdownRequirements(mockCore); - }).toThrow(); + }).toThrow("not compiled with strict mode"); const errorMsg = mockCore.setFailed.mock.calls[0][0]; - expect(errorMsg).toContain("\n"); expect(errorMsg).toContain("gh aw compile --strict"); }); - it("should include newlines in pull_request_target error message for readability", () => { + it("should include pwn request warning in pull_request_target error message", () => { process.env.GITHUB_REPOSITORY_VISIBILITY = "public"; process.env.GH_AW_COMPILED_STRICT = "true"; process.env.GITHUB_EVENT_NAME = "pull_request_target"; expect(() => { validateLockdownRequirements(mockCore); - }).toThrow(); + }).toThrow("pwn request"); const errorMsg = mockCore.setFailed.mock.calls[0][0]; - expect(errorMsg).toContain("\n"); expect(errorMsg).toContain("pwn request"); }); }); From c6cd0ba764ce0cf5d5e2f5c3d831500535c05f75 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 16 Jun 2026 17:04:43 +0000 Subject: [PATCH 6/6] test: remove redundant pull_request_target assertion Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/validate_lockdown_requirements.test.cjs | 3 --- 1 file changed, 3 deletions(-) diff --git a/actions/setup/js/validate_lockdown_requirements.test.cjs b/actions/setup/js/validate_lockdown_requirements.test.cjs index 7fb9313e8fb..73522e37cc0 100644 --- a/actions/setup/js/validate_lockdown_requirements.test.cjs +++ b/actions/setup/js/validate_lockdown_requirements.test.cjs @@ -378,9 +378,6 @@ describe("validate_lockdown_requirements", () => { expect(() => { validateLockdownRequirements(mockCore); }).toThrow("pwn request"); - - const errorMsg = mockCore.setFailed.mock.calls[0][0]; - expect(errorMsg).toContain("pwn request"); }); }); });