diff --git a/0010-Escape-terminal-special-characters-in-kubectl-112553.patch b/0010-Escape-terminal-special-characters-in-kubectl-112553.patch new file mode 100644 index 0000000000000000000000000000000000000000..a1b95e669b7e11bfdf4e51408e1e6f7eb5765c35 --- /dev/null +++ b/0010-Escape-terminal-special-characters-in-kubectl-112553.patch @@ -0,0 +1,193 @@ +From a2f7a90f4a71d3eaef19521baa99f27981d7554e Mon Sep 17 00:00:00 2001 +From: zhangxiaoyu +Date: Mon, 28 Nov 2022 10:56:01 +0800 +Subject: [PATCH] Escape terminal special characters in kubectl (#112553) + +* Escape terminal special characters in kubectl + +* Add escaping for kubectl alpha events + +Signed-off-by: David Leadbeater +--- + .../cli-runtime/pkg/printers/tableprinter.go | 19 ++++++++- + .../cli-runtime/pkg/printers/terminal.go | 39 +++++++++++++++++++ + .../kubectl/pkg/cmd/get/customcolumn.go | 2 +- + .../kubectl/pkg/cmd/get/customcolumn_test.go | 16 ++++++++ + .../k8s.io/kubectl/pkg/describe/describe.go | 7 +++- + .../kubectl/pkg/describe/describe_test.go | 19 +++++++++ + 6 files changed, 98 insertions(+), 4 deletions(-) + create mode 100644 staging/src/k8s.io/cli-runtime/pkg/printers/terminal.go + +diff --git a/staging/src/k8s.io/cli-runtime/pkg/printers/tableprinter.go b/staging/src/k8s.io/cli-runtime/pkg/printers/tableprinter.go +index 56bd05aa..c6bab0ee 100644 +--- a/staging/src/k8s.io/cli-runtime/pkg/printers/tableprinter.go ++++ b/staging/src/k8s.io/cli-runtime/pkg/printers/tableprinter.go +@@ -209,7 +209,24 @@ func printTable(table *metav1.Table, output io.Writer, options PrintOptions) err + fmt.Fprint(output, "\t") + } + if cell != nil { +- fmt.Fprint(output, cell) ++ switch val := cell.(type) { ++ case string: ++ print := val ++ truncated := false ++ // Truncate at the first newline, carriage return or formfeed ++ // (treated as a newline by tabwriter). ++ breakchar := strings.IndexAny(print, "\f\n\r") ++ if breakchar >= 0 { ++ truncated = true ++ print = print[:breakchar] ++ } ++ WriteEscaped(output, print) ++ if truncated { ++ fmt.Fprint(output, "...") ++ } ++ default: ++ WriteEscaped(output, fmt.Sprint(val)) ++ } + } + } + fmt.Fprintln(output) +diff --git a/staging/src/k8s.io/cli-runtime/pkg/printers/terminal.go b/staging/src/k8s.io/cli-runtime/pkg/printers/terminal.go +new file mode 100644 +index 00000000..5a59491e +--- /dev/null ++++ b/staging/src/k8s.io/cli-runtime/pkg/printers/terminal.go +@@ -0,0 +1,39 @@ ++/* ++Copyright 2022 The Kubernetes Authors. ++ ++Licensed under the Apache License, Version 2.0 (the "License"); ++you may not use this file except in compliance with the License. ++You may obtain a copy of the License at ++ ++ http://www.apache.org/licenses/LICENSE-2.0 ++ ++Unless required by applicable law or agreed to in writing, software ++distributed under the License is distributed on an "AS IS" BASIS, ++WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++See the License for the specific language governing permissions and ++limitations under the License. ++*/ ++ ++package printers ++ ++import ( ++ "io" ++ "strings" ++) ++ ++// terminalEscaper replaces ANSI escape sequences and other terminal special ++// characters to avoid terminal escape character attacks (issue #101695). ++var terminalEscaper = strings.NewReplacer("\x1b", "^[", "\r", "\\r") ++ ++// WriteEscaped replaces unsafe terminal characters with replacement strings ++// and writes them to the given writer. ++func WriteEscaped(writer io.Writer, output string) error { ++ _, err := terminalEscaper.WriteString(writer, output) ++ return err ++} ++ ++// EscapeTerminal escapes terminal special characters in a human readable (but ++// non-reversible) format. ++func EscapeTerminal(in string) string { ++ return terminalEscaper.Replace(in) ++} +diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/get/customcolumn.go b/staging/src/k8s.io/kubectl/pkg/cmd/get/customcolumn.go +index f9f48176..64d6d6f1 100644 +--- a/staging/src/k8s.io/kubectl/pkg/cmd/get/customcolumn.go ++++ b/staging/src/k8s.io/kubectl/pkg/cmd/get/customcolumn.go +@@ -250,7 +250,7 @@ func (s *CustomColumnsPrinter) printOneObject(obj runtime.Object, parsers []*jso + } + for arrIx := range values { + for valIx := range values[arrIx] { +- valueStrings = append(valueStrings, fmt.Sprintf("%v", values[arrIx][valIx].Interface())) ++ valueStrings = append(valueStrings, printers.EscapeTerminal(fmt.Sprint(values[arrIx][valIx].Interface()))) + } + } + columns[ix] = strings.Join(valueStrings, ",") +diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/get/customcolumn_test.go b/staging/src/k8s.io/kubectl/pkg/cmd/get/customcolumn_test.go +index e4fb17a8..de403142 100644 +--- a/staging/src/k8s.io/kubectl/pkg/cmd/get/customcolumn_test.go ++++ b/staging/src/k8s.io/kubectl/pkg/cmd/get/customcolumn_test.go +@@ -311,6 +311,22 @@ foo baz + obj: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}, TypeMeta: metav1.TypeMeta{APIVersion: "baz"}}, + expectedOutput: `NAME API_VERSION NOT_FOUND + foo baz ++`, ++ }, ++ { ++ columns: []Column{ ++ { ++ Header: "NAME", ++ FieldSpec: "{.metadata.name}", ++ }, ++ }, ++ obj: &corev1.PodList{ ++ Items: []corev1.Pod{ ++ {ObjectMeta: metav1.ObjectMeta{Name: "\x1b \r"}}, ++ }, ++ }, ++ expectedOutput: `NAME ++^[ \r + `, + }, + } +diff --git a/staging/src/k8s.io/kubectl/pkg/describe/describe.go b/staging/src/k8s.io/kubectl/pkg/describe/describe.go +index ba59c191..35253c87 100644 +--- a/staging/src/k8s.io/kubectl/pkg/describe/describe.go ++++ b/staging/src/k8s.io/kubectl/pkg/describe/describe.go +@@ -62,6 +62,7 @@ import ( + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/cli-runtime/pkg/genericclioptions" ++ "k8s.io/cli-runtime/pkg/printers" + "k8s.io/client-go/dynamic" + clientset "k8s.io/client-go/kubernetes" + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" +@@ -143,11 +144,13 @@ func (pw *prefixWriter) Write(level int, format string, a ...interface{}) { + for i := 0; i < level; i++ { + prefix += levelSpace + } +- fmt.Fprintf(pw.out, prefix+format, a...) ++ output := fmt.Sprintf(prefix+format, a...) ++ printers.WriteEscaped(pw.out, output) + } + + func (pw *prefixWriter) WriteLine(a ...interface{}) { +- fmt.Fprintln(pw.out, a...) ++ output := fmt.Sprintln(a...) ++ printers.WriteEscaped(pw.out, output) + } + + func (pw *prefixWriter) Flush() { +diff --git a/staging/src/k8s.io/kubectl/pkg/describe/describe_test.go b/staging/src/k8s.io/kubectl/pkg/describe/describe_test.go +index 3ef9afdc..b3f31579 100644 +--- a/staging/src/k8s.io/kubectl/pkg/describe/describe_test.go ++++ b/staging/src/k8s.io/kubectl/pkg/describe/describe_test.go +@@ -4459,3 +4459,22 @@ func TestControllerRef(t *testing.T) { + t.Errorf("unexpected out: %s", out) + } + } ++ ++func TestDescribeTerminalEscape(t *testing.T) { ++ fake := fake.NewSimpleClientset(&corev1.ConfigMap{ ++ ObjectMeta: metav1.ObjectMeta{ ++ Name: "mycm", ++ Namespace: "foo", ++ Annotations: map[string]string{"annotation1": "terminal escape: \x1b"}, ++ }, ++ }) ++ c := &describeClient{T: t, Namespace: "foo", Interface: fake} ++ d := ConfigMapDescriber{c} ++ out, err := d.Describe("foo", "mycm", DescriberSettings{ShowEvents: true}) ++ if err != nil { ++ t.Errorf("unexpected error: %v", err) ++ } ++ if strings.Contains(out, "\x1b") || !strings.Contains(out, "^[") { ++ t.Errorf("unexpected out: %s", out) ++ } ++} +-- +2.25.1 + diff --git a/kubernetes.spec b/kubernetes.spec index b94c39410298fd4a649a75aa45ffddb5adac1ccd..8a4f0443de2d3a53a6ac5c10af1b5727a4c0fdeb 100644 --- a/kubernetes.spec +++ b/kubernetes.spec @@ -3,7 +3,7 @@ Name: kubernetes Version: 1.20.2 -Release: 14 +Release: 15 Summary: Container cluster management License: ASL 2.0 URL: https://k8s.io/kubernetes @@ -264,6 +264,12 @@ getent passwd kube >/dev/null || useradd -r -g kube -d / -s /sbin/nologin \ %systemd_postun kubelet kube-proxy %changelog +* Mon Nov 28 2022 zhangxiaoyu - 1.20.2-15 +- Type:bugfix +- CVE:NA +- SUG:NA +- DESC:fix CVE-2021-25743 + * Thu Nov 17 2022 zhangxiaoyu - 1.20.2-14 - Type:bugfix - CVE:NA