From d4ebe697f3e7c770864fc3472f72fbe087e8dfad Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 18 Mar 2026 23:40:20 +0000
Subject: [PATCH 1/4] feat: update github mcp guard policy step summary to use
details element
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
.../setup/js/determine_automatic_lockdown.cjs | 17 ++----
.../js/determine_automatic_lockdown.test.cjs | 54 +++++++++----------
2 files changed, 29 insertions(+), 42 deletions(-)
diff --git a/actions/setup/js/determine_automatic_lockdown.cjs b/actions/setup/js/determine_automatic_lockdown.cjs
index 0af3452b3de..aa38b2c1b56 100644
--- a/actions/setup/js/determine_automatic_lockdown.cjs
+++ b/actions/setup/js/determine_automatic_lockdown.cjs
@@ -87,18 +87,11 @@ async function determineAutomaticLockdown(github, context, core) {
// Write resolved guard policy values to the step summary
const autoLabel = isPrivate ? "automatic (private repo)" : "automatic (public repo)";
- await core.summary
- .addHeading("GitHub MCP Guard Policy", 3)
- .addTable([
- [
- { data: "Field", header: true },
- { data: "Value", header: true },
- { data: "Source", header: true },
- ],
- ["min-integrity", resolvedMinIntegrity, configuredMinIntegrity ? "workflow config" : autoLabel],
- ["repos", resolvedRepos, configuredRepos ? "workflow config" : autoLabel],
- ])
- .write();
+ const minIntegritySource = configuredMinIntegrity ? "workflow config" : autoLabel;
+ const reposSource = configuredRepos ? "workflow config" : autoLabel;
+ const tableRows = ["| Field | Value | Source |", "|-------|-------|--------|", `| min-integrity | ${resolvedMinIntegrity} | ${minIntegritySource} |`, `| repos | ${resolvedRepos} | ${reposSource} |`].join("\n");
+ const details = `\nGitHub MCP Guard Policy
\n\n${tableRows}\n\n \n`;
+ await core.summary.addRaw(details).write();
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
core.error(`Failed to determine automatic guard policy: ${errorMessage}`);
diff --git a/actions/setup/js/determine_automatic_lockdown.test.cjs b/actions/setup/js/determine_automatic_lockdown.test.cjs
index e34e0f17cee..3e87066a28d 100644
--- a/actions/setup/js/determine_automatic_lockdown.test.cjs
+++ b/actions/setup/js/determine_automatic_lockdown.test.cjs
@@ -33,8 +33,7 @@ describe("determine_automatic_lockdown", () => {
error: vi.fn(),
setOutput: vi.fn(),
summary: {
- addHeading: vi.fn().mockReturnThis(),
- addTable: vi.fn().mockReturnThis(),
+ addRaw: vi.fn().mockReturnThis(),
write: vi.fn().mockResolvedValue(undefined),
},
};
@@ -218,16 +217,15 @@ describe("determine_automatic_lockdown", () => {
await determineAutomaticLockdown(mockGithub, mockContext, mockCore);
- expect(mockCore.summary.addHeading).toHaveBeenCalledWith("GitHub MCP Guard Policy", 3);
- expect(mockCore.summary.addTable).toHaveBeenCalledWith([
- [
- { data: "Field", header: true },
- { data: "Value", header: true },
- { data: "Source", header: true },
- ],
- ["min-integrity", "approved", "automatic (public repo)"],
- ["repos", "all", "automatic (public repo)"],
- ]);
+ expect(mockCore.summary.addRaw).toHaveBeenCalledTimes(1);
+ const publicSummaryArg = mockCore.summary.addRaw.mock.calls[0][0];
+ expect(publicSummaryArg).toContain("");
+ expect(publicSummaryArg).toContain("GitHub MCP Guard Policy");
+ expect(publicSummaryArg).toContain("min-integrity");
+ expect(publicSummaryArg).toContain("approved");
+ expect(publicSummaryArg).toContain("automatic (public repo)");
+ expect(publicSummaryArg).toContain("repos");
+ expect(publicSummaryArg).toContain("all");
expect(mockCore.summary.write).toHaveBeenCalled();
});
@@ -244,15 +242,13 @@ describe("determine_automatic_lockdown", () => {
await determineAutomaticLockdown(mockGithub, mockContext, mockCore);
- expect(mockCore.summary.addTable).toHaveBeenCalledWith([
- [
- { data: "Field", header: true },
- { data: "Value", header: true },
- { data: "Source", header: true },
- ],
- ["min-integrity", "merged", "workflow config"],
- ["repos", "public", "workflow config"],
- ]);
+ expect(mockCore.summary.addRaw).toHaveBeenCalledTimes(1);
+ const configuredSummaryArg = mockCore.summary.addRaw.mock.calls[0][0];
+ expect(configuredSummaryArg).toContain("min-integrity");
+ expect(configuredSummaryArg).toContain("merged");
+ expect(configuredSummaryArg).toContain("workflow config");
+ expect(configuredSummaryArg).toContain("repos");
+ expect(configuredSummaryArg).toContain("public");
expect(mockCore.summary.write).toHaveBeenCalled();
});
@@ -266,15 +262,13 @@ describe("determine_automatic_lockdown", () => {
await determineAutomaticLockdown(mockGithub, mockContext, mockCore);
- expect(mockCore.summary.addTable).toHaveBeenCalledWith([
- [
- { data: "Field", header: true },
- { data: "Value", header: true },
- { data: "Source", header: true },
- ],
- ["min-integrity", "none", "automatic (private repo)"],
- ["repos", "all", "automatic (private repo)"],
- ]);
+ expect(mockCore.summary.addRaw).toHaveBeenCalledTimes(1);
+ const privateSummaryArg = mockCore.summary.addRaw.mock.calls[0][0];
+ expect(privateSummaryArg).toContain("min-integrity");
+ expect(privateSummaryArg).toContain("none");
+ expect(privateSummaryArg).toContain("automatic (private repo)");
+ expect(privateSummaryArg).toContain("repos");
+ expect(privateSummaryArg).toContain("all");
expect(mockCore.summary.write).toHaveBeenCalled();
});
});
From f9f005f20dcfea0fa23aa08b9f297c7ebe09d512 Mon Sep 17 00:00:00 2001
From: Peli de Halleux
Date: Wed, 18 Mar 2026 16:59:07 -0700
Subject: [PATCH 2/4] Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---
.../setup/js/determine_automatic_lockdown.cjs | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/actions/setup/js/determine_automatic_lockdown.cjs b/actions/setup/js/determine_automatic_lockdown.cjs
index aa38b2c1b56..96225eaae3d 100644
--- a/actions/setup/js/determine_automatic_lockdown.cjs
+++ b/actions/setup/js/determine_automatic_lockdown.cjs
@@ -89,9 +89,20 @@ async function determineAutomaticLockdown(github, context, core) {
const autoLabel = isPrivate ? "automatic (private repo)" : "automatic (public repo)";
const minIntegritySource = configuredMinIntegrity ? "workflow config" : autoLabel;
const reposSource = configuredRepos ? "workflow config" : autoLabel;
- const tableRows = ["| Field | Value | Source |", "|-------|-------|--------|", `| min-integrity | ${resolvedMinIntegrity} | ${minIntegritySource} |`, `| repos | ${resolvedRepos} | ${reposSource} |`].join("\n");
- const details = `\nGitHub MCP Guard Policy
\n\n${tableRows}\n\n \n`;
- await core.summary.addRaw(details).write();
+
+ await core.summary
+ .addRaw("\nGitHub MCP Guard Policy
\n\n")
+ .addTable([
+ [
+ { data: "Field", header: true },
+ { data: "Value", header: true },
+ { data: "Source", header: true },
+ ],
+ ["min-integrity", resolvedMinIntegrity, minIntegritySource],
+ ["repos", resolvedRepos, reposSource],
+ ])
+ .addRaw("\n \n")
+ .write();
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
core.error(`Failed to determine automatic guard policy: ${errorMessage}`);
From 30cecd1ffbc83b54de3ff67d40b3f84f577ecf54 Mon Sep 17 00:00:00 2001
From: Peli de Halleux
Date: Wed, 18 Mar 2026 16:59:15 -0700
Subject: [PATCH 3/4] Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---
.../js/determine_automatic_lockdown.test.cjs | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/actions/setup/js/determine_automatic_lockdown.test.cjs b/actions/setup/js/determine_automatic_lockdown.test.cjs
index 3e87066a28d..8136a712eb9 100644
--- a/actions/setup/js/determine_automatic_lockdown.test.cjs
+++ b/actions/setup/js/determine_automatic_lockdown.test.cjs
@@ -221,6 +221,12 @@ describe("determine_automatic_lockdown", () => {
const publicSummaryArg = mockCore.summary.addRaw.mock.calls[0][0];
expect(publicSummaryArg).toContain("");
expect(publicSummaryArg).toContain("GitHub MCP Guard Policy");
+ // Ensure we have a well-formed block with a and closing
+ expect(publicSummaryArg).toMatch(/[\\s\\S]*<\\/details>/);
+ expect(publicSummaryArg).toMatch(/[\\s\\S]*GitHub MCP Guard Policy[\\s\\S]*<\\/summary>/);
+ // Ensure the markdown table header and separator are present
+ expect(publicSummaryArg).toMatch(/\\| *Field *\\| *Value *\\| *Source *\\|/);
+ expect(publicSummaryArg).toMatch(/\\|[- ]+\\|[- ]+\\|[- ]+\\|/);
expect(publicSummaryArg).toContain("min-integrity");
expect(publicSummaryArg).toContain("approved");
expect(publicSummaryArg).toContain("automatic (public repo)");
@@ -244,6 +250,11 @@ describe("determine_automatic_lockdown", () => {
expect(mockCore.summary.addRaw).toHaveBeenCalledTimes(1);
const configuredSummaryArg = mockCore.summary.addRaw.mock.calls[0][0];
+ // Ensure we have a well-formed block with closing
+ expect(configuredSummaryArg).toMatch(/[\\s\\S]*<\\/details>/);
+ // Ensure the markdown table header and separator are present
+ expect(configuredSummaryArg).toMatch(/\\| *Field *\\| *Value *\\| *Source *\\|/);
+ expect(configuredSummaryArg).toMatch(/\\|[- ]+\\|[- ]+\\|[- ]+\\|/);
expect(configuredSummaryArg).toContain("min-integrity");
expect(configuredSummaryArg).toContain("merged");
expect(configuredSummaryArg).toContain("workflow config");
@@ -264,6 +275,11 @@ describe("determine_automatic_lockdown", () => {
expect(mockCore.summary.addRaw).toHaveBeenCalledTimes(1);
const privateSummaryArg = mockCore.summary.addRaw.mock.calls[0][0];
+ // Ensure we have a well-formed block with closing
+ expect(privateSummaryArg).toMatch(/[\\s\\S]*<\\/details>/);
+ // Ensure the markdown table header and separator are present
+ expect(privateSummaryArg).toMatch(/\\| *Field *\\| *Value *\\| *Source *\\|/);
+ expect(privateSummaryArg).toMatch(/\\|[- ]+\\|[- ]+\\|[- ]+\\|/);
expect(privateSummaryArg).toContain("min-integrity");
expect(privateSummaryArg).toContain("none");
expect(privateSummaryArg).toContain("automatic (private repo)");
From 56025bfc80f30faa1f7b7b8f3d7609ba2204dd37 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 19 Mar 2026 00:08:10 +0000
Subject: [PATCH 4/4] fix: restore pure addRaw approach, add cell sanitization,
fix regex patterns in tests
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
.../setup/js/determine_automatic_lockdown.cjs | 29 ++++++++++---------
.../js/determine_automatic_lockdown.test.cjs | 20 ++++++-------
2 files changed, 26 insertions(+), 23 deletions(-)
diff --git a/actions/setup/js/determine_automatic_lockdown.cjs b/actions/setup/js/determine_automatic_lockdown.cjs
index 96225eaae3d..be17474d777 100644
--- a/actions/setup/js/determine_automatic_lockdown.cjs
+++ b/actions/setup/js/determine_automatic_lockdown.cjs
@@ -90,19 +90,22 @@ async function determineAutomaticLockdown(github, context, core) {
const minIntegritySource = configuredMinIntegrity ? "workflow config" : autoLabel;
const reposSource = configuredRepos ? "workflow config" : autoLabel;
- await core.summary
- .addRaw("\nGitHub MCP Guard Policy
\n\n")
- .addTable([
- [
- { data: "Field", header: true },
- { data: "Value", header: true },
- { data: "Source", header: true },
- ],
- ["min-integrity", resolvedMinIntegrity, minIntegritySource],
- ["repos", resolvedRepos, reposSource],
- ])
- .addRaw("\n \n")
- .write();
+ /**
+ * Escapes a value for safe embedding in a markdown table cell.
+ * Replaces HTML-special characters and pipe characters that would break the table.
+ * @param {string} value
+ * @returns {string}
+ */
+ const escapeCell = value => value.replace(/&/g, "&").replace(//g, ">").replace(/\|/g, "\\|").replace(/\n/g, " ");
+
+ const tableRows = [
+ "| Field | Value | Source |",
+ "|-------|-------|--------|",
+ `| min-integrity | ${escapeCell(resolvedMinIntegrity)} | ${escapeCell(minIntegritySource)} |`,
+ `| repos | ${escapeCell(resolvedRepos)} | ${escapeCell(reposSource)} |`,
+ ].join("\n");
+ const details = `\nGitHub MCP Guard Policy
\n\n${tableRows}\n\n \n`;
+ await core.summary.addRaw(details).write();
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
core.error(`Failed to determine automatic guard policy: ${errorMessage}`);
diff --git a/actions/setup/js/determine_automatic_lockdown.test.cjs b/actions/setup/js/determine_automatic_lockdown.test.cjs
index 8136a712eb9..54c4caba788 100644
--- a/actions/setup/js/determine_automatic_lockdown.test.cjs
+++ b/actions/setup/js/determine_automatic_lockdown.test.cjs
@@ -222,11 +222,11 @@ describe("determine_automatic_lockdown", () => {
expect(publicSummaryArg).toContain("");
expect(publicSummaryArg).toContain("GitHub MCP Guard Policy");
// Ensure we have a well-formed block with a and closing
- expect(publicSummaryArg).toMatch(/[\\s\\S]*<\\/details>/);
- expect(publicSummaryArg).toMatch(/[\\s\\S]*GitHub MCP Guard Policy[\\s\\S]*<\\/summary>/);
+ expect(publicSummaryArg).toMatch(/[\s\S]*<\/details>/);
+ expect(publicSummaryArg).toMatch(/[\s\S]*GitHub MCP Guard Policy[\s\S]*<\/summary>/);
// Ensure the markdown table header and separator are present
- expect(publicSummaryArg).toMatch(/\\| *Field *\\| *Value *\\| *Source *\\|/);
- expect(publicSummaryArg).toMatch(/\\|[- ]+\\|[- ]+\\|[- ]+\\|/);
+ expect(publicSummaryArg).toMatch(/\| *Field *\| *Value *\| *Source *\|/);
+ expect(publicSummaryArg).toMatch(/\|[- ]+\|[- ]+\|[- ]+\|/);
expect(publicSummaryArg).toContain("min-integrity");
expect(publicSummaryArg).toContain("approved");
expect(publicSummaryArg).toContain("automatic (public repo)");
@@ -251,10 +251,10 @@ describe("determine_automatic_lockdown", () => {
expect(mockCore.summary.addRaw).toHaveBeenCalledTimes(1);
const configuredSummaryArg = mockCore.summary.addRaw.mock.calls[0][0];
// Ensure we have a well-formed block with closing
- expect(configuredSummaryArg).toMatch(/[\\s\\S]*<\\/details>/);
+ expect(configuredSummaryArg).toMatch(/[\s\S]*<\/details>/);
// Ensure the markdown table header and separator are present
- expect(configuredSummaryArg).toMatch(/\\| *Field *\\| *Value *\\| *Source *\\|/);
- expect(configuredSummaryArg).toMatch(/\\|[- ]+\\|[- ]+\\|[- ]+\\|/);
+ expect(configuredSummaryArg).toMatch(/\| *Field *\| *Value *\| *Source *\|/);
+ expect(configuredSummaryArg).toMatch(/\|[- ]+\|[- ]+\|[- ]+\|/);
expect(configuredSummaryArg).toContain("min-integrity");
expect(configuredSummaryArg).toContain("merged");
expect(configuredSummaryArg).toContain("workflow config");
@@ -276,10 +276,10 @@ describe("determine_automatic_lockdown", () => {
expect(mockCore.summary.addRaw).toHaveBeenCalledTimes(1);
const privateSummaryArg = mockCore.summary.addRaw.mock.calls[0][0];
// Ensure we have a well-formed block with closing
- expect(privateSummaryArg).toMatch(/[\\s\\S]*<\\/details>/);
+ expect(privateSummaryArg).toMatch(/[\s\S]*<\/details>/);
// Ensure the markdown table header and separator are present
- expect(privateSummaryArg).toMatch(/\\| *Field *\\| *Value *\\| *Source *\\|/);
- expect(privateSummaryArg).toMatch(/\\|[- ]+\\|[- ]+\\|[- ]+\\|/);
+ expect(privateSummaryArg).toMatch(/\| *Field *\| *Value *\| *Source *\|/);
+ expect(privateSummaryArg).toMatch(/\|[- ]+\|[- ]+\|[- ]+\|/);
expect(privateSummaryArg).toContain("min-integrity");
expect(privateSummaryArg).toContain("none");
expect(privateSummaryArg).toContain("automatic (private repo)");