Summary
The chart's default podSecurityContext sets runAsUser: 1000 and runAsNonRoot: true, but the nousresearch/hermes-agent image is designed to start as root (uid 0) and drop privileges internally via s6-overlay.
Root Cause
The s6-overlay init system inside the image runs /etc/cont-init.d/01-hermes-setup and /etc/cont-init.d/02-reconcile-profiles as root, then drops to the hermes user (uid 10000 by default, remappable via HERMES_UID/HERMES_GID) using s6-setuidgid. This call internally invokes setgroups(), which requires the process to be running as root — it cannot be called from a non-root context even with CAP_SETGID/CAP_SETUID in the bounding set when allowPrivilegeEscalation: false is also set (which applies no_new_privs).
When the pod starts as uid 1000 (chart default), the following fatal errors occur:
s6-applyuidgid: fatal: unable to set supplementary group list: Operation not permitted
cont-init: info: /etc/cont-init.d/01-hermes-setup exited 111
s6-applyuidgid: fatal: unable to set supplementary group list: Operation not permitted
cont-init: info: /etc/cont-init.d/02-reconcile-profiles exited 111
And with readOnlyRootFilesystem: true (also a chart default), /run is immutable and owned by root, causing s6-overlay's preinit to fail before any init scripts even run:
/package/admin/s6-overlay/libexec/preinit: fatal: /run belongs to uid 0 instead of 1000, has insecure and/or unworkable permissions, and we're lacking the privileges to fix it.
s6-overlay-suexec: fatal: child failed with exit code 100
Fix Applied (workaround)
Override the security contexts in Helm values to allow root startup:
podSecurityContext:
runAsUser: 0
runAsNonRoot: false
securityContext:
allowPrivilegeEscalation: true
readOnlyRootFilesystem: false
runAsNonRoot: false
capabilities:
drop: []
env:
HERMES_UID: "1000"
HERMES_GID: "1000"
HERMES_UID/HERMES_GID tell the image's stage2 hook to remap the hermes user to uid/gid 1000 before dropping privileges, which integrates cleanly with Kubernetes fsGroup on the persistent volume.
Suggestion
The chart's default podSecurityContext and securityContext should either:
- Default to
runAsUser: 0 / runAsNonRoot: false to match the image's actual requirements, or
- Include documentation/warnings that the defaults are incompatible with the official image and must be overridden as shown above.
The HERMES_UID/HERMES_GID env vars are a clean mechanism — it may be worth exposing them as first-class chart values.
Summary
The chart's default
podSecurityContextsetsrunAsUser: 1000andrunAsNonRoot: true, but thenousresearch/hermes-agentimage is designed to start as root (uid 0) and drop privileges internally via s6-overlay.Root Cause
The s6-overlay init system inside the image runs
/etc/cont-init.d/01-hermes-setupand/etc/cont-init.d/02-reconcile-profilesas root, then drops to thehermesuser (uid 10000 by default, remappable viaHERMES_UID/HERMES_GID) usings6-setuidgid. This call internally invokessetgroups(), which requires the process to be running as root — it cannot be called from a non-root context even withCAP_SETGID/CAP_SETUIDin the bounding set whenallowPrivilegeEscalation: falseis also set (which appliesno_new_privs).When the pod starts as uid 1000 (chart default), the following fatal errors occur:
And with
readOnlyRootFilesystem: true(also a chart default),/runis immutable and owned by root, causing s6-overlay's preinit to fail before any init scripts even run:Fix Applied (workaround)
Override the security contexts in Helm values to allow root startup:
HERMES_UID/HERMES_GIDtell the image's stage2 hook to remap thehermesuser to uid/gid 1000 before dropping privileges, which integrates cleanly with KubernetesfsGroupon the persistent volume.Suggestion
The chart's default
podSecurityContextandsecurityContextshould either:runAsUser: 0/runAsNonRoot: falseto match the image's actual requirements, orThe
HERMES_UID/HERMES_GIDenv vars are a clean mechanism — it may be worth exposing them as first-class chart values.