Finding
GetPodSecurityContext() in internal/controller/humiocluster_defaults.go (lines 727–737) returns a default PodSecurityContext that runs the container as non-root UID 65534, which is great — but pairs it with RunAsGroup: 0 and FSGroup: 0:
return &corev1.PodSecurityContext{
RunAsUser: helpers.Int64Ptr(65534),
RunAsNonRoot: helpers.BoolPtr(true),
RunAsGroup: helpers.Int64Ptr(0), // TODO: We probably want to move away from this.
FSGroup: helpers.Int64Ptr(0), // TODO: We probably want to move away from this.
}
The two TODO comments next to each line indicate this is already on the team's radar — opening this issue mainly to give it a tracking surface and (hopefully) help prioritize.
Why it matters
-
RunAsGroup: 0 means the process's primary group ID is root (GID 0). Even though the user is non-root, anything in the container that checks "is this process in the root group" (and there are surprising consumers of that — e.g., default-group ownership of files written by the process, some capability-aware tools) treats this process as privileged for group-based decisions. Combined with bind-mounted host paths or shared persistent volumes, files written by the Humio pod end up 0:root group-owned.
-
FSGroup: 0 is the bigger one. The kubelet applies FSGroup as a recursive chgrp (and bit-or of 02770 on the mode) on all writable volumes mounted into the pod. FSGroup: 0 makes every volume mount group-owned by root and group-writable, which:
- Breaks the principle of least privilege for the pod itself
- Opens a lateral path when volumes are shared across pods (HostPath, ReadWriteMany PVs): another pod in the cluster whose process happens to run as GID 0 (very common — many images default to root group) can read or modify Humio's on-disk state without any RBAC permission, because the access decision happens at the kernel level on the volume, not the API server.
For an operator that manages a log-store cluster (Kafka logs, cluster state, potentially crashdumps), an unauthenticated lateral read of those files is a real exposure if a sibling workload is ever compromised.
Suggested fix
The cleanest path, in increasing order of disruption:
-
Pick a non-zero GID for both fields. UID 65534's matching group on Debian/Alpine is nogroup = GID 65534. Setting RunAsGroup: 65534 and FSGroup: 65534 keeps the same identity, just on a non-privileged group:
RunAsGroup: helpers.Int64Ptr(65534),
FSGroup: helpers.Int64Ptr(65534),
The Humio container image needs to be confirmed to be group-65534-writable on its data directories — if it isn't today, the image's existing Dockerfile lines would need a chgrp -R 65534 /data (or equivalent).
-
If 65534 is wrong for the image, pick whatever GID the image's data directories are actually owned by, and document it as a hard constraint of the operator's contract with the Humio image.
-
Open up a CR-level override. The existing humioNodeSpec.PodSecurityContext is honored on the next line, so cluster operators can already specify their own — but the default is what most deployments will live with. Defaults should be safe.
Scope
- Only affects the default branch (
hnp.humioNodeSpec.PodSecurityContext == nil). Anyone who already specifies a podSecurityContext in their HumioCluster CR is unaffected.
- Should pair with a clear upgrade note in the release that lands this — existing clusters will get a fresh
chgrp recursive walk on their data volumes on the first rolling restart after the change, which can take a while on large clusters.
Happy to send a PR if useful — would want to confirm the image's expected GID with someone from the Humio side first.
Proudly Made in Nebraska. Go Big Red! 🌽 https://xkcd.com/2347/
Finding
GetPodSecurityContext()ininternal/controller/humiocluster_defaults.go(lines 727–737) returns a defaultPodSecurityContextthat runs the container as non-root UID 65534, which is great — but pairs it withRunAsGroup: 0andFSGroup: 0:The two
TODOcomments next to each line indicate this is already on the team's radar — opening this issue mainly to give it a tracking surface and (hopefully) help prioritize.Why it matters
RunAsGroup: 0means the process's primary group ID isroot(GID 0). Even though the user is non-root, anything in the container that checks "is this process in the root group" (and there are surprising consumers of that — e.g., default-group ownership of files written by the process, some capability-aware tools) treats this process as privileged for group-based decisions. Combined with bind-mounted host paths or shared persistent volumes, files written by the Humio pod end up0:rootgroup-owned.FSGroup: 0is the bigger one. The kubelet appliesFSGroupas a recursivechgrp(and bit-or of02770on the mode) on all writable volumes mounted into the pod.FSGroup: 0makes every volume mount group-owned byrootand group-writable, which:For an operator that manages a log-store cluster (Kafka logs, cluster state, potentially crashdumps), an unauthenticated lateral read of those files is a real exposure if a sibling workload is ever compromised.
Suggested fix
The cleanest path, in increasing order of disruption:
Pick a non-zero GID for both fields. UID 65534's matching group on Debian/Alpine is
nogroup= GID 65534. SettingRunAsGroup: 65534andFSGroup: 65534keeps the same identity, just on a non-privileged group:The Humio container image needs to be confirmed to be group-65534-writable on its data directories — if it isn't today, the image's existing
Dockerfilelines would need achgrp -R 65534 /data(or equivalent).If 65534 is wrong for the image, pick whatever GID the image's data directories are actually owned by, and document it as a hard constraint of the operator's contract with the Humio image.
Open up a CR-level override. The existing
humioNodeSpec.PodSecurityContextis honored on the next line, so cluster operators can already specify their own — but the default is what most deployments will live with. Defaults should be safe.Scope
hnp.humioNodeSpec.PodSecurityContext == nil). Anyone who already specifies apodSecurityContextin theirHumioClusterCR is unaffected.chgrprecursive walk on their data volumes on the first rolling restart after the change, which can take a while on large clusters.Happy to send a PR if useful — would want to confirm the image's expected GID with someone from the Humio side first.
Proudly Made in Nebraska. Go Big Red! 🌽 https://xkcd.com/2347/