CVE-2021-3602 (published 2022-03-03T19:15Z)

An information disclosure flaw was found in Buildah, when building containers using chroot isolation. Running processes in container builds (e.g. Dockerfile RUN commands) can access environment variables from parent and grandparent processes. When run in a container in a CI/CD environment, environment variables may include sensitive information that was shared with the container in order to be used only by Buildah itself (e.g. container registry credentials).

Severity: LOW
CVSS v2 base score: 1.9 (AV:L/AC:M/Au:N/C:P/I:N/A:N)
CVSS v3 base score: 5.5, MEDIUM (CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N)

Weakness information:
cwe_id: CWE-212
cwe_name: Improper Removal of Sensitive Information Before Storage or Transfer
description: The product stores, transfers, or shares a resource that contains sensitive information, but it does not properly remove that information before the product makes the resource available to unauthorized actors.
extended_description: 
            Resources that may contain sensitive data include documents, packets, messages, databases, etc. While this data may be useful to an individual user or small set of users who share the resource, it may need to be removed before the resource can be shared outside of the trusted group. The process of removal is sometimes called cleansing or scrubbing.
            For example, a product for editing documents might not remove sensitive data such as reviewer comments or the local pathname where the document is stored. Or, a proxy might not remove an internal IP address from headers before making an outgoing request to an Internet site.
         
         

Fix information:
repo_url: https://github.com/containers/buildah
commit_details: repo_url: https://github.com/containers/buildah
author: Nalin Dahyabhai
author_date: 2021-06-02 16:22:28-04:00
msg: chroot: fix environment value leakage to intermediate processes

Blake Burkhart reports that when running processes using "chroot"
isolation, the process being run can examine the environment of its
immediate parent and grandparent processes (CVE-2021-3602).

When run in a container in a CI/CD environment, the environment may
include sensitive information which was shared with the container in
order to be used only by buildah itself.  The command being executed is
able to read such information.

This patch reduces the set of environment variables passed to these
intermediate processes, from all variables to the one which is used to
control the level of debug logging.  It also corrects a misleading debug
message and expands the description of chroot isolation in man pages.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
repository: repo_url: https://github.com/containers/buildah
repo_name: containers/buildah
description: A tool that facilitates building OCI images.
repo_language: Go
owner: containers
file_changes: filename: run.go
change_type: ModificationType.MODIFY
diff: @@ -161,7 +161,7 @@ func RunUsingChroot(spec *specs.Spec, bundlePath, homeDir string, stdin io.Reade
 	cmd := unshare.Command(runUsingChrootCommand)
 	cmd.Stdin, cmd.Stdout, cmd.Stderr = stdin, stdout, stderr
 	cmd.Dir = "/"
-	cmd.Env = append([]string{fmt.Sprintf("LOGLEVEL=%d", logrus.GetLevel())}, os.Environ()...)
+	cmd.Env = []string{fmt.Sprintf("LOGLEVEL=%d", logrus.GetLevel())}
 
 	logrus.Debugf("Running %#v in %#v", cmd.Cmd, cmd)
 	confwg.Add(1)
@@ -207,7 +207,7 @@ func runUsingChrootMain() {
 		os.Exit(1)
 	}
 
-	if options.Spec == nil {
+	if options.Spec == nil || options.Spec.Process == nil {
 		fmt.Fprintf(os.Stderr, "invalid options spec in runUsingChrootMain\n")
 		os.Exit(1)
 	}
@@ -573,7 +573,7 @@ func runUsingChroot(spec *specs.Spec, bundlePath string, ctty *os.File, stdin io
 	cmd := unshare.Command(append([]string{runUsingChrootExecCommand}, spec.Process.Args...)...)
 	cmd.Stdin, cmd.Stdout, cmd.Stderr = stdin, stdout, stderr
 	cmd.Dir = "/"
-	cmd.Env = append([]string{fmt.Sprintf("LOGLEVEL=%d", logrus.GetLevel())}, os.Environ()...)
+	cmd.Env = []string{fmt.Sprintf("LOGLEVEL=%d", logrus.GetLevel())}
 	cmd.UnshareFlags = syscall.CLONE_NEWUTS | syscall.CLONE_NEWNS
 	requestedUserNS := false
 	for _, ns := range spec.Linux.Namespaces {
@@ -663,7 +663,7 @@ func runUsingChrootExecMain() {
 	// Set the hostname.  We're already in a distinct UTS namespace and are admins in the user
 	// namespace which created it, so we shouldn't get a permissions error, but seccomp policy
 	// might deny our attempt to call sethostname() anyway, so log a debug message for that.
-	if options.Spec == nil {
+	if options.Spec == nil || options.Spec.Process == nil {
 		fmt.Fprintf(os.Stderr, "invalid options spec passed in\n")
 		os.Exit(1)
 	}
@@ -819,7 +819,6 @@ func runUsingChrootExecMain() {
 // Output debug messages when that differs from what we're being asked to do.
 func logNamespaceDiagnostics(spec *specs.Spec) {
 	sawMountNS := false
-	sawUserNS := false
 	sawUTSNS := false
 	for _, ns := range spec.Linux.Namespaces {
 		switch ns.Type {
@@ -854,9 +853,8 @@ func logNamespaceDiagnostics(spec *specs.Spec) {
 			}
 		case specs.UserNamespace:
 			if ns.Path != "" {
-				logrus.Debugf("unable to join user namespace %q, creating a new one", ns.Path)
+				logrus.Debugf("unable to join user namespace, sorry about that")
 			}
-			sawUserNS = true
 		case specs.UTSNamespace:
 			if ns.Path != "" {
 				logrus.Debugf("unable to join UTS namespace %q, creating a new one", ns.Path)
@@ -867,9 +865,6 @@ func logNamespaceDiagnostics(spec *specs.Spec) {
 	if !sawMountNS {
 		logrus.Debugf("mount namespace not requested, but creating a new one anyway")
 	}
-	if !sawUserNS {
-		logrus.Debugf("user namespace not requested, but creating a new one anyway")
-	}
 	if !sawUTSNS {
 		logrus.Debugf("UTS namespace not requested, but creating a new one anyway")
 	}

programming_language: Go
filename: buildah-bud.md
change_type: ModificationType.MODIFY
diff: @@ -307,11 +307,13 @@ another process.
 Controls what type of isolation is used for running processes as part of `RUN`
 instructions.  Recognized types include *oci* (OCI-compatible runtime, the
 default), *rootless* (OCI-compatible runtime invoked using a modified
-configuration, with *--no-new-keyring* added to its *create*
-invocation, with network and UTS namespaces disabled, and IPC, PID,
-and user namespaces enabled; the default for unprivileged users), and
-*chroot* (an internal wrapper that leans more toward chroot(1) than
-container technology).
+configuration, with *--no-new-keyring* added to its *create* invocation,
+reusing the host's network and UTS namespaces, and creating private IPC, PID,
+mount, and user namespaces; the default for unprivileged users), and *chroot*
+(an internal wrapper that leans more toward chroot(1) than container
+technology, reusing the host's control group, network, IPC, and PID namespaces,
+and creating private mount and UTS namespaces, and creating user namespaces
+only when they're required for ID mapping).
 
 Note: You can also override the default isolation type by setting the
 BUILDAH\_ISOLATION environment variable.  `export BUILDAH_ISOLATION=oci`

programming_language: Markdown
filename: buildah-from.md
change_type: ModificationType.MODIFY
diff: @@ -234,11 +234,13 @@ another process.
 Controls what type of isolation is used for running processes under `buildah
 run`.  Recognized types include *oci* (OCI-compatible runtime, the default),
 *rootless* (OCI-compatible runtime invoked using a modified
-configuration, with *--no-new-keyring* added to its *create*
-invocation, with network and UTS namespaces disabled, and IPC, PID,
-and user namespaces enabled; the default for unprivileged users), and
-*chroot* (an internal wrapper that leans more toward chroot(1) than
-container technology).
+configuration, with *--no-new-keyring* added to its *create* invocation,
+reusing the host's network and UTS namespaces, and creating private IPC, PID,
+mount, and user namespaces; the default for unprivileged users), and *chroot*
+(an internal wrapper that leans more toward chroot(1) than container
+technology, reusing the host's control group, network, IPC, and PID namespaces,
+and creating private mount and UTS namespaces, and creating user namespaces
+only when they're required for ID mapping).
 
 Note: You can also override the default isolation type by setting the
 BUILDAH\_ISOLATION environment variable.  `export BUILDAH_ISOLATION=oci`

programming_language: Markdown
filename: buildah-run.md
change_type: ModificationType.MODIFY
diff: @@ -82,10 +82,13 @@ process.
 Controls what type of isolation is used for running the process.  Recognized
 types include *oci* (OCI-compatible runtime, the default), *rootless*
 (OCI-compatible runtime invoked using a modified configuration, with
-*--no-new-keyring* added to its *create* invocation, with network and
-UTS namespaces disabled, and IPC, PID, and user namespaces enabled;
-the default for unprivileged users), and *chroot* (an internal wrapper
-that leans more toward chroot(1) than container technology).
+*--no-new-keyring* added to its *create* invocation, reusing the host's network
+and UTS namespaces, and creating private IPC, PID, mount, and user namespaces;
+the default for unprivileged users), and *chroot* (an internal wrapper that
+leans more toward chroot(1) than container technology, reusing the host's
+control group, network, IPC, and PID namespaces, and creating private mount and
+UTS namespaces, and creating user namespaces only when they're required for ID
+mapping).
 
 Note: You can also override the default isolation type by setting the
 BUILDAH\_ISOLATION environment variable.  `export BUILDAH_ISOLATION=oci`

programming_language: Markdown