From 6ab67d12ec6e0a80732dcde3fb9b108cf65b7677 Mon Sep 17 00:00:00 2001 From: Nikolai Emil Damm Date: Tue, 21 Jul 2026 20:50:59 +0200 Subject: [PATCH 1/2] fix(installer): prevent AWS controller values injection --- .../installer/awslbcontroller/installer.go | 36 ++++++++++++------- .../awslbcontroller/installer_test.go | 24 +++++++++++-- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/pkg/svc/installer/awslbcontroller/installer.go b/pkg/svc/installer/awslbcontroller/installer.go index 21c8971182..24c82325cd 100644 --- a/pkg/svc/installer/awslbcontroller/installer.go +++ b/pkg/svc/installer/awslbcontroller/installer.go @@ -7,6 +7,7 @@ import ( "github.com/devantler-tech/ksail/v7/pkg/client/helm" "github.com/devantler-tech/ksail/v7/pkg/svc/installer/internal/helmutil" + "sigs.k8s.io/yaml" ) const ( @@ -52,6 +53,11 @@ func NewInstaller( return nil, ErrClusterNameRequired } + valuesYaml, err := buildValuesYaml(clusterName, region, haEnabled) + if err != nil { + return nil, err + } + return &Installer{ Base: helmutil.NewBase( "aws-load-balancer-controller", @@ -76,7 +82,7 @@ func NewInstaller( // (helm v4 maps !UpgradeCRDs to SkipCRDs). UpgradeCRDs: true, Timeout: timeout, - ValuesYaml: buildValuesYaml(clusterName, region, haEnabled), + ValuesYaml: valuesYaml, }, ), }, nil @@ -91,21 +97,25 @@ func NewInstaller( // disabled: it makes this controller the default for every new LoadBalancer // Service, and during install its admitted-but-not-ready window rejects // Services created by concurrently-installing components. -func buildValuesYaml(clusterName, region string, haEnabled bool) string { - parts := []string{ - "clusterName: " + clusterName, - "enableServiceMutatorWebhook: false", +func buildValuesYaml(clusterName, region string, haEnabled bool) (string, error) { + values := struct { + ClusterName string `json:"clusterName"` + EnableServiceMutatorWebhook bool `json:"enableServiceMutatorWebhook"` + Region string `json:"region,omitempty"` + ReplicaCount int `json:"replicaCount"` + }{ + ClusterName: clusterName, + Region: region, + ReplicaCount: 1, } - - if region != "" { - parts = append(parts, "region: "+region) + if haEnabled { + values.ReplicaCount = 2 } - if haEnabled { - parts = append(parts, "replicaCount: 2") - } else { - parts = append(parts, "replicaCount: 1") + encoded, err := yaml.Marshal(values) + if err != nil { + return "", err } - return strings.Join(parts, "\n") + return string(encoded), nil } diff --git a/pkg/svc/installer/awslbcontroller/installer_test.go b/pkg/svc/installer/awslbcontroller/installer_test.go index 6e374e3006..52debdec35 100644 --- a/pkg/svc/installer/awslbcontroller/installer_test.go +++ b/pkg/svc/installer/awslbcontroller/installer_test.go @@ -9,6 +9,7 @@ import ( awslbcontrollerinstaller "github.com/devantler-tech/ksail/v7/pkg/svc/installer/awslbcontroller" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "sigs.k8s.io/yaml" ) func TestNewInstaller(t *testing.T) { @@ -111,15 +112,34 @@ func TestBuildValuesYaml(t *testing.T) { t.Run(testCase.name, func(t *testing.T) { t.Parallel() - got := awslbcontrollerinstaller.BuildValuesYamlForTest( + got, err := awslbcontrollerinstaller.BuildValuesYamlForTest( testCase.clusterName, testCase.region, testCase.haEnabled, ) - assert.Equal(t, testCase.want, got) + require.NoError(t, err) + assert.YAMLEq(t, testCase.want, got) }) } } +func TestBuildValuesYaml_EscapesUntrustedScalars(t *testing.T) { + t.Parallel() + + clusterName := "prod-eks\nimage:\n repository: attacker/controller" + region := "eu-north-1\nserviceAccount:\n name: attacker" + values, err := awslbcontrollerinstaller.BuildValuesYamlForTest(clusterName, region, false) + require.NoError(t, err) + + var parsed map[string]any + require.NoError(t, yaml.Unmarshal([]byte(values), &parsed)) + assert.Equal(t, map[string]any{ + "clusterName": clusterName, + "enableServiceMutatorWebhook": false, + "region": region, + "replicaCount": float64(1), + }, parsed) +} + func TestChartVersion(t *testing.T) { t.Parallel() From abfcf12695eb474ef2d7ade3fce73ff40b924f2d Mon Sep 17 00:00:00 2001 From: Nikolai Emil Damm Date: Tue, 28 Jul 2026 15:46:47 +0200 Subject: [PATCH 2/2] fix(deps): patch gRPC vulnerability --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bcdbafcfa6..f71136047a 100644 --- a/go.mod +++ b/go.mod @@ -104,7 +104,7 @@ require ( golang.org/x/oauth2 v0.36.0 golang.org/x/text v0.40.0 google.golang.org/genproto/googleapis/rpc v0.0.0-20260630182238-925bb5da69e7 - google.golang.org/grpc v1.82.0 + google.golang.org/grpc v1.82.1 google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af gopkg.in/yaml.v3 v3.0.1 k8s.io/klog/v2 v2.140.0 diff --git a/go.sum b/go.sum index d60d4f6480..5a4be0569f 100644 --- a/go.sum +++ b/go.sum @@ -3324,8 +3324,8 @@ google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.82.0 h1:vguDnZUPjE26w09A63VoxZPnvPjB5Riyc0mkXPFmAIU= -google.golang.org/grpc v1.82.0/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA= +google.golang.org/grpc v1.82.1 h1:NnAxzGRA0677vCa4BUkOAnO5+FfQqVl9iUXeD0IqcGE= +google.golang.org/grpc v1.82.1/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=