Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions pkg/utils/datasource_event.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ func (e *DatasourceEvent) GetExePath() string {
switch e.EventType {
case DnsEventType, ExecveEventType, ForkEventType, PtraceEventType, RandomXEventType, KmodEventType, UnshareEventType, BpfEventType:
exepath, _ := e.getFieldAccessor("exepath").String(e.Data)
return exepath
return NormalizePath(exepath)
default:
logger.L().Warning("GetExePath not implemented for event type", helpers.String("eventType", string(e.EventType)))
return ""
Expand Down Expand Up @@ -432,7 +432,7 @@ func (e *DatasourceEvent) GetFullPath() string {
if path == "" {
path, _ = e.getFieldAccessor("fname").String(e.Data)
}
return path
return NormalizePath(path)
default:
logger.L().Warning("GetFullPath not implemented for event type", helpers.String("eventType", string(e.EventType)))
return ""
Expand Down Expand Up @@ -499,7 +499,7 @@ func (e *DatasourceEvent) GetNewPath() string {
switch e.EventType {
case HardlinkEventType, SymlinkEventType:
newPath, _ := e.getFieldAccessor("newpath").String(e.Data)
return newPath
return NormalizePath(newPath)
default:
logger.L().Warning("GetNewPath not implemented for event type", helpers.String("eventType", string(e.EventType)))
return ""
Expand All @@ -521,7 +521,7 @@ func (e *DatasourceEvent) GetOldPath() string {
switch e.EventType {
case HardlinkEventType, SymlinkEventType:
oldPath, _ := e.getFieldAccessor("oldpath").String(e.Data)
return oldPath
return NormalizePath(oldPath)
default:
logger.L().Warning("GetOldPath not implemented for event type", helpers.String("eventType", string(e.EventType)))
return ""
Expand Down Expand Up @@ -559,7 +559,7 @@ func (e *DatasourceEvent) GetPath() string {
switch e.EventType {
case OpenEventType:
path, _ := e.getFieldAccessor("fname").String(e.Data)
return path
return NormalizePath(path)
default:
logger.L().Warning("GetPath not implemented for event type", helpers.String("eventType", string(e.EventType)))
return ""
Expand Down
72 changes: 72 additions & 0 deletions pkg/utils/normalize_path_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package utils

import (
"github.com/stretchr/testify/assert"
"testing"
)

func TestNormalizePath(t *testing.T) {
tests := []struct {
name string
input string
expected string
}{
{
name: "empty path",
input: "",
expected: "",
},
{
name: "dot path",
input: ".",
expected: "/",
},
{
name: "absolute path",
input: "/etc/passwd",
expected: "/etc/passwd",
},
{
name: "headless proc path (task)",
input: "/46/task/46/fd",
expected: "/proc/46/task/46/fd",
},
{
name: "headless proc path (fd)",
input: "/46/fd/3",
expected: "/proc/46/fd/3",
},
{
name: "already absolute proc path",
input: "/proc/46/fd/3",
expected: "/proc/46/fd/3",
},
{
name: "relative path (not dot)",
input: "usr/bin/ls",
expected: "/usr/bin/ls",
},
{
name: "relative path with ./",
input: "./config",
expected: "/config",
},
{
name: "path with redundant slashes",
input: "/etc//passwd",
expected: "/etc/passwd",
},
{
name: "path with dot components",
input: "/usr/./bin/../lib",
expected: "/usr/lib",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := NormalizePath(tt.input)
assert.Equal(t, tt.expected, got)
})
}
}
34 changes: 34 additions & 0 deletions pkg/utils/path.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package utils

import (
"path"
"regexp"
"strings"
)

var headlessProcRegex = regexp.MustCompile(`^/\d+/(task|fd)/`)

// NormalizePath normalizes a path by:
// 1. Prepending "/proc" to "headless" proc paths (e.g. /46/task/46/fd -> /proc/46/task/46/fd)
// 2. Ensuring it starts with "/" if it's not empty
// 3. Converting "." to "/"
// 4. Cleaning the path (removing redundant slashes, dot-dots, etc.)
func NormalizePath(p string) string {
if p == "" {
return ""
}

if p == "." {
return "/"
}

if headlessProcRegex.MatchString(p) {
p = "/proc" + p
}

if !strings.HasPrefix(p, "/") {
p = "/" + p
}

return path.Clean(p)
}
10 changes: 5 additions & 5 deletions pkg/utils/struct_event.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ func (e *StructEvent) GetEventType() EventType {
func (e *StructEvent) GetExePath() string {
switch e.EventType {
case DnsEventType, ExecveEventType, ForkEventType, PtraceEventType, RandomXEventType, KmodEventType, UnshareEventType, BpfEventType:
return e.ExePath
return NormalizePath(e.ExePath)
default:
logger.L().Warning("GetExePath not implemented for event type", helpers.String("eventType", string(e.EventType)))
return ""
Expand Down Expand Up @@ -296,7 +296,7 @@ func (e *StructEvent) GetFlagsRaw() uint32 {
func (e *StructEvent) GetFullPath() string {
switch e.EventType {
case OpenEventType:
return e.FullPath
return NormalizePath(e.FullPath)
default:
logger.L().Warning("GetFullPath not implemented for event type", helpers.String("eventType", string(e.EventType)))
return ""
Expand Down Expand Up @@ -352,7 +352,7 @@ func (e *StructEvent) GetNamespace() string {
func (e *StructEvent) GetNewPath() string {
switch e.EventType {
case HardlinkEventType, SymlinkEventType:
return e.NewPath
return NormalizePath(e.NewPath)
default:
logger.L().Warning("GetNewPath not implemented for event type", helpers.String("eventType", string(e.EventType)))
return ""
Expand All @@ -372,7 +372,7 @@ func (e *StructEvent) GetNumAnswers() int {
func (e *StructEvent) GetOldPath() string {
switch e.EventType {
case HardlinkEventType, SymlinkEventType:
return e.OldPath
return NormalizePath(e.OldPath)
default:
logger.L().Warning("GetOldPath not implemented for event type", helpers.String("eventType", string(e.EventType)))
return ""
Expand Down Expand Up @@ -408,7 +408,7 @@ func (e *StructEvent) GetPath() string {
}
switch e.EventType {
case OpenEventType:
return e.Path
return NormalizePath(e.Path)
default:
logger.L().Warning("GetPath not implemented for event type", helpers.String("eventType", string(e.EventType)))
return ""
Expand Down
4 changes: 4 additions & 0 deletions tests/chart/templates/node-agent/daemonset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ spec:
{{- if .value }}
value: "{{ .value }}"
{{- end }}
{{- if .valueFrom }}
valueFrom:
{{ toYaml .valueFrom | indent 16 }}
{{- end }}
Comment on lines 119 to +125
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Missing mutual exclusion guard between value and valueFrom.

If a nodeAgent.env entry sets both .value and .valueFrom, both blocks will be rendered, producing invalid Kubernetes YAML (the pod spec requires exactly one of value or valueFrom, not both). Kubernetes will reject the resulting pod spec.

🛡️ Proposed guard
-            {{- if .value }}
-              value: "{{ .value }}"
-            {{- end }}
-            {{- if .valueFrom }}
-              valueFrom:
-{{ toYaml .valueFrom | indent 16 }}
-            {{- end }}
+            {{- if and .value (not .valueFrom) }}
+              value: "{{ .value }}"
+            {{- else if .valueFrom }}
+              valueFrom:
+{{ toYaml .valueFrom | indent 16 }}
+            {{- end }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/chart/templates/node-agent/daemonset.yaml` around lines 119 - 125,
Render only one of `.value` or `.valueFrom` for each `nodeAgent.env` entry by
making the template mutually exclusive: change the current independent `if
.value` / `if .valueFrom` checks so that `.value` is rendered only when `.value`
is set and `.valueFrom` is not, and `.valueFrom` is rendered only when
`.valueFrom` is set and `.value` is not (or use an if/else-if structure) to
ensure exactly one of the two blocks appears for any env entry.

{{- end }}
securityContext:
runAsUser: 0
Expand Down
Loading