From 4150b913d6e1643e2af4e3281a8de827cb458a47 Mon Sep 17 00:00:00 2001 From: Azure Linux Security Servicing Account Date: Wed, 3 Jun 2026 07:09:21 +0000 Subject: [PATCH] Patch gh for CVE-2026-45803 --- SPECS/gh/CVE-2026-45803.patch | 160 ++++++++++++++++++++++++++++++++++ SPECS/gh/gh.spec | 6 +- 2 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 SPECS/gh/CVE-2026-45803.patch diff --git a/SPECS/gh/CVE-2026-45803.patch b/SPECS/gh/CVE-2026-45803.patch new file mode 100644 index 00000000000..1da0a20ff97 --- /dev/null +++ b/SPECS/gh/CVE-2026-45803.patch @@ -0,0 +1,160 @@ +From 12bdd95f36cef29851d73e97faeca539366b121a Mon Sep 17 00:00:00 2001 +From: AllSpark +Date: Wed, 3 Jun 2026 07:02:07 +0000 +Subject: [PATCH] Fix log terminal injection + +Signed-off-by: Azure Linux Security Servicing Account +Upstream-reference: AI Backport of https://github.com/cli/cli/commit/a9d36fb9ef38ecc4c143da6bacd91b3e959cd76a.patch +--- + .../run-view-log-escape-sequences.txtar | 70 +++++++++++++++++++ + pkg/cmd/run/view/view.go | 2 + + pkg/cmd/run/view/view_test.go | 42 +++++++++++ + 3 files changed, 114 insertions(+) + create mode 100644 acceptance/testdata/workflow/run-view-log-escape-sequences.txtar + +diff --git a/acceptance/testdata/workflow/run-view-log-escape-sequences.txtar b/acceptance/testdata/workflow/run-view-log-escape-sequences.txtar +new file mode 100644 +index 0000000..47978cf +--- /dev/null ++++ b/acceptance/testdata/workflow/run-view-log-escape-sequences.txtar +@@ -0,0 +1,70 @@ ++# This test ensures that a malicious workflow which emit terminal control sequences (ESC, OSC, CSI) in ++# its log output does not result in terminal injection when logs are displayed using `gh run view --log` ++ ++# Use gh as a credential helper ++exec gh auth setup-git ++ ++# Create a repository with a file so it has a default branch ++exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private ++ ++# Defer repo cleanup ++defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING ++ ++# Clone the repo ++exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING ++ ++# Commit the workflow file ++cd $SCRIPT_NAME-$RANDOM_STRING ++mkdir .github/workflows ++mv ../workflow.yml .github/workflows/workflow.yml ++exec git add .github/workflows/workflow.yml ++exec git commit -m 'Create workflow with escape sequences' ++exec git push -u origin main ++ ++# Sleep because it takes a second for the workflow to register ++sleep 1 ++ ++# Run the workflow ++exec gh workflow run 'Escape Sequence PoC' ++ ++# It takes some time for a workflow run to register ++sleep 10 ++ ++# Get the run ID we want to view ++exec gh run list --json databaseId --jq '.[0].databaseId' ++stdout2env RUN_ID ++ ++# Wait for workflow to complete ++exec gh run watch $RUN_ID --exit-status ++ ++# View the logs and check that raw ESC bytes (0x1b) are NOT present in output. ++# If this assertion fails, it means terminal escape sequences from the workflow ++# log are being passed through to the user's terminal unsanitised. ++exec gh run view $RUN_ID --log ++ ++# The output should contain the safe/visible text but not raw ESC bytes. ++# \x1b is the ESC byte - it must not appear in the output. ++! stdout '\x1b' ++ ++# The log output should still contain the non-escape parts of the log lines. ++stdout 'ESCAPE_MARKER_START' ++stdout 'ESCAPE_MARKER_END' ++ ++-- workflow.yml -- ++name: Escape Sequence PoC ++ ++on: ++ workflow_dispatch: ++ ++jobs: ++ emit-escape-sequences: ++ runs-on: ubuntu-latest ++ steps: ++ - name: Emit terminal escape sequences ++ run: | ++ # OSC title set: \x1b]0;TITLE\x07 ++ printf 'ESCAPE_MARKER_START \033]0;HIJACKED_TITLE\007 ESCAPE_MARKER_END\n' ++ # CSI color: \x1b[31m ... \x1b[0m ++ printf 'ESCAPE_MARKER_START \033[31mRED_TEXT\033[0m ESCAPE_MARKER_END\n' ++ # Screen title set (from original PoC): \x1bk ... \x1b\\ ++ printf 'ESCAPE_MARKER_START \033k;malicious command;\033\\ ESCAPE_MARKER_END\n' +diff --git a/pkg/cmd/run/view/view.go b/pkg/cmd/run/view/view.go +index c794cff..9103ac8 100644 +--- a/pkg/cmd/run/view/view.go ++++ b/pkg/cmd/run/view/view.go +@@ -26,7 +26,9 @@ import ( + "github.com/cli/cli/v2/pkg/cmd/run/shared" + "github.com/cli/cli/v2/pkg/cmdutil" + "github.com/cli/cli/v2/pkg/iostreams" ++ "github.com/cli/go-gh/v2/pkg/asciisanitizer" + "github.com/spf13/cobra" ++ "golang.org/x/text/transform" + ) + + type RunLogCache struct { +diff --git a/pkg/cmd/run/view/view_test.go b/pkg/cmd/run/view/view_test.go +index 05eb257..e56e826 100644 +--- a/pkg/cmd/run/view/view_test.go ++++ b/pkg/cmd/run/view/view_test.go +@@ -1611,6 +1611,48 @@ var coolJobRunLogOutput = fmt.Sprintf("%s%s", fobTheBarzLogOutput, barfTheFobLog + var sadJobRunLogOutput = fmt.Sprintf("%s%s", barfTheQuuxLogOutput, quuxTheBarfLogOutput) + var expectedRunLogOutput = fmt.Sprintf("%s%s", coolJobRunLogOutput, sadJobRunLogOutput) + ++ ++func TestCopyLogWithLinePrefix_TerminalEscapeSequences(t *testing.T) { ++ tests := []struct { ++ name string ++ input string ++ }{ ++ { ++ name: "OSC title set sequence", ++ input: "normal prefix\x1b]0;HIJACKED TITLE\x07trailing text\n", ++ }, ++ { ++ name: "CSI color sequence", ++ input: "\x1b[31mRED TEXT\x1b[0m normal text\n", ++ }, ++ { ++ name: "screen title set sequence used in original report", ++ input: "\x1bk;echo this is an arbitrary command;\x1b\\\n", ++ }, ++ { ++ name: "CSI window title query", ++ input: "before\x1b[21tafter\n", ++ }, ++ { ++ name: "multiple escape sequences", ++ input: "\x1b]0;title\x07\x1b[31mred\x1b[0m\x1b[21t\n", ++ }, ++ } ++ ++ for _, tt := range tests { ++ t.Run(tt.name, func(t *testing.T) { ++ var buf bytes.Buffer ++ err := copyLogWithLinePrefix(&buf, strings.NewReader(tt.input), "jobname\tstep\t") ++ require.NoError(t, err) ++ ++ output := buf.String() ++ assert.NotContains(t, output, "\x1b", ++ "output should not contain raw ESC (0x1b) bytes, got: %q", output) ++ }) ++ } ++} ++ ++ + func TestRunLog(t *testing.T) { + t.Run("when the cache dir doesn't exist, exists return false", func(t *testing.T) { + cacheDir := t.TempDir() + "/non-existent-dir" +-- +2.45.4 + diff --git a/SPECS/gh/gh.spec b/SPECS/gh/gh.spec index 253ac1b35bd..d135248bd1b 100644 --- a/SPECS/gh/gh.spec +++ b/SPECS/gh/gh.spec @@ -1,7 +1,7 @@ Summary: GitHub official command line tool Name: gh Version: 2.62.0 -Release: 17%{?dist} +Release: 18%{?dist} License: MIT Vendor: Microsoft Corporation Distribution: Azure Linux @@ -45,6 +45,7 @@ Patch29: CVE-2026-39827.patch Patch30: CVE-2026-39828.patch Patch31: CVE-2026-39835.patch Patch32: CVE-2026-42502.patch +Patch33: CVE-2026-45803.patch BuildRequires: golang < 1.24 BuildRequires: git @@ -89,6 +90,9 @@ make test %{_datadir}/zsh/site-functions/_gh %changelog +* Wed Jun 03 2026 Azure Linux Security Servicing Account - 2.62.0-18 +- Patch for CVE-2026-45803 + * Mon Jun 01 2026 Azure Linux Security Servicing Account - 2.62.0-17 - Patch for CVE-2026-42502, CVE-2026-39835, CVE-2026-39828, CVE-2026-39827, CVE-2026-25681, CVE-2026-25680