From 1c50cd717aa404d8c2d785d5025ac002c59dc6dc Mon Sep 17 00:00:00 2001 From: i-OmSharma Date: Wed, 17 Jun 2026 16:01:32 +0530 Subject: [PATCH] fix(parser): extract host namespaces from nested security contexts with validation precedence --- pkg/parser/helm.go | 24 ++++++++++++++++++ pkg/parser/helm_test.go | 54 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/pkg/parser/helm.go b/pkg/parser/helm.go index 3f0451b..27161aa 100644 --- a/pkg/parser/helm.go +++ b/pkg/parser/helm.go @@ -348,6 +348,30 @@ func readSecurity(n *yaml.Node) SecurityContext { } func applySecFields(ctx *yaml.Node, out *SecurityContext) { + for _, key := range [][2]string{ + {"hostNetwork", "HostNetwork"}, + {"hostPID", "HostPID"}, + {"hostIPC", "HostIPC"}, + } { + if v := findChild(ctx, key[0]); v != nil && v.Kind == yaml.ScalarNode { + b := boolValue(v.Value) + switch key[1] { + case "HostNetwork": + if out.HostNetwork == nil { + out.HostNetwork = &b + } + case "HostPID": + if out.HostPID == nil { + out.HostPID = &b + } + case "HostIPC": + if out.HostIPC == nil { + out.HostIPC = &b + } + } + } + } + if v := findChild(ctx, "runAsNonRoot"); v != nil && v.Kind == yaml.ScalarNode { b := boolValue(v.Value) out.RunAsNonRoot = &b diff --git a/pkg/parser/helm_test.go b/pkg/parser/helm_test.go index 221fe40..9a74a56 100644 --- a/pkg/parser/helm_test.go +++ b/pkg/parser/helm_test.go @@ -101,6 +101,60 @@ features: in: "- a\n- b\n", wantErr: true, }, + { + // hostNetwork/PID/IPC nested under podSecurityContext were silently + // ignored before the applySecFields fix (issue #39). + name: "host-namespace-flags-nested-under-podSecurityContext", + in: ` +agent: + resources: + requests: + cpu: "100m" + podSecurityContext: + hostNetwork: true + hostPID: true + hostIPC: true +`, + check: func(t *testing.T, wls []Workload) { + t.Helper() + if len(wls) != 1 { + t.Fatalf("expected 1 workload, got %d", len(wls)) + } + sec := wls[0].Security + if sec.HostNetwork == nil || !*sec.HostNetwork { + t.Errorf("HostNetwork = %v, want *true", sec.HostNetwork) + } + if sec.HostPID == nil || !*sec.HostPID { + t.Errorf("HostPID = %v, want *true", sec.HostPID) + } + if sec.HostIPC == nil || !*sec.HostIPC { + t.Errorf("HostIPC = %v, want *true", sec.HostIPC) + } + }, + }, + { + // Workload-level values must not be overwritten by podSecurityContext. + name: "workload-level-host-flags-take-precedence", + in: ` +agent: + resources: + requests: + cpu: "100m" + hostNetwork: false + podSecurityContext: + hostNetwork: true +`, + check: func(t *testing.T, wls []Workload) { + t.Helper() + if len(wls) != 1 { + t.Fatalf("expected 1 workload, got %d", len(wls)) + } + sec := wls[0].Security + if sec.HostNetwork == nil || *sec.HostNetwork { + t.Errorf("HostNetwork = %v, want *false (workload level wins)", sec.HostNetwork) + } + }, + }, { name: "deterministic-alpha-order", in: `