CVE-2023-34236: Exposure of Sensitive Information to an Unauthorized Actor (CWE-200)
value: Weave GitOps Terraform Controller (aka Weave TF-controller) is a controller for Flux to reconcile Terraform resources in a GitOps way. A vulnerability has been identified in Weave GitOps Terraform Controller which could allow an authenticated remote attacker to view sensitive information. This vulnerability stems from Weave GitOps Terraform Runners (`tf-runner`), where sensitive data is inadvertently printed - potentially revealing sensitive user data in their pod logs. In particular, functions `tfexec.ShowPlan`, `tfexec.ShowPlanRaw`, and `tfexec.Output` are implicated when the `tfexec` object set its `Stdout` and `Stderr` to be `os.Stdout` and `os.Stderr`. An unauthorized remote attacker could exploit this vulnerability by accessing these prints of sensitive information, which may contain configurations or tokens that could be used to gain unauthorized control or access to resources managed by the Terraform controller. A successful exploit could allow the attacker to utilize this sensitive data, potentially leading to unauthorized access or control of the system. This vulnerability has been addressed in Weave GitOps Terraform Controller versions `v0.14.4` and `v0.15.0-rc.5`. Users are urged to upgrade to one of these versions to mitigate the vulnerability. As a temporary measure until the patch can be applied, users can add the environment variable `DISABLE_TF_LOGS` to the tf-runners via the runner pod template of the Terraform Custom Resource. This will prevent the logging of sensitive information and mitigate the risk of this vulnerability.
CWE description: The product exposes sensitive information to an actor that is not explicitly authorized to have access to that information.
CVSS v3 base score: 6.5
Published: 2023-07-14T22:15Z
Repository: https://github.com/weaveworks/tf-controller
Language: Go
Files changed: runner/server_outputs.go
Commit date: 2023-06-06 21:58:18 +0700
Commit message: fix loggin in tf.output

Signed-off-by: Chanwit Kaewkasi <chanwit@gmail.com>

Diff: diff --git a/runner/server_outputs.go b/runner/server_outputs.go
index 921e545..b961a17 100644
--- a/runner/server_outputs.go
+++ b/runner/server_outputs.go
@@ -1,30 +1,44 @@
 package runner
 
 import (
 	"context"
 	"fmt"
+	"io"
 	"reflect"
 
+	"github.com/hashicorp/terraform-exec/tfexec"
 	infrav1 "github.com/weaveworks/tf-controller/api/v1alpha2"
 	corev1 "k8s.io/api/core/v1"
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
 	ctrl "sigs.k8s.io/controller-runtime"
 )
 
+func (r *TerraformRunnerServer) tfOutput(ctx context.Context, opts ...tfexec.OutputOption) (map[string]tfexec.OutputMeta, error) {
+	log := ctrl.LoggerFrom(ctx, "instance-id", r.InstanceID).WithName(loggerName)
+
+	// This is the only place where we disable the logger
+	r.tf.SetStdout(io.Discard)
+	r.tf.SetStderr(io.Discard)
+
+	defer r.initLogger(log)
+
+	return r.tf.Output(ctx, opts...)
+}
+
 func (r *TerraformRunnerServer) Output(ctx context.Context, req *OutputRequest) (*OutputReply, error) {
 	log := ctrl.LoggerFrom(ctx, "instance-id", r.InstanceID).WithName(loggerName)
 	log.Info("creating outputs")
 	if req.TfInstance != r.InstanceID {
 		err := fmt.Errorf("no TF instance found")
 		log.Error(err, "no terraform")
 		return nil, err
 	}
 
-	outputs, err := r.tf.Output(ctx)
+	outputs, err := r.tfOutput(ctx)
 	if err != nil {
 		log.Error(err, "unable to get outputs")
 		return nil, err
 	}
 

Vulnerable code: 	outputs, err := r.tf.Output(ctx)
Fixed code: 	"io"
	"github.com/hashicorp/terraform-exec/tfexec"
func (r *TerraformRunnerServer) tfOutput(ctx context.Context, opts ...tfexec.OutputOption) (map[string]tfexec.OutputMeta, error) {
	log := ctrl.LoggerFrom(ctx, "instance-id", r.InstanceID).WithName(loggerName)

	// This is the only place where we disable the logger
	r.tf.SetStdout(io.Discard)
	r.tf.SetStderr(io.Discard)

	defer r.initLogger(log)

	return r.tf.Output(ctx, opts...)
}

	outputs, err := r.tfOutput(ctx)