rss-bridge: pin the unprivileged-port sysctl, quote env values

Follow-up to the template-chart hardening fixes in #133, which landed
while this branch was open.

The env block now quotes names, values and keyRef fields. Without it a
value like "5" renders as a YAML number and the API server rejects the
whole manifest. RSS-Bridge takes numeric settings that way
(RSSBRIDGE_http_timeout), so this was reachable with the first env entry
anyone adds.

The port-80 question is settled by measurement rather than by the
"it works in k3d" reasoning #133 warns about. Same pod spec in k3d
(k3s v1.35.5), only ip_unprivileged_port_start changed:

  1024, capabilities.drop [ALL]      nginx: bind() to 0.0.0.0:80 failed
                                     (13: Permission denied)
  1024, plus NET_BIND_SERVICE        identical failure - for a non-root
                                     process the capability lands in the
                                     permitted but not the effective
                                     set, so it buys nothing
  0                                  binds, HTTP 200

So the chart cannot buy safety with a capability the way samba does, and
port 80 is not negotiable either: nginx is configured for it inside the
image and the entrypoint's only lever is a sed against a read-only
/etc/nginx. What it can do is stop depending on the node default - the
pod securityContext now pins the sysctl to 0, so the bind no longer
relies on cluster configuration. Verified: the chart-installed pod
reports 0 and answers 200 through the Service.

Worth recording how that failure looks without probes: the entrypoint
backgrounds nginx and then execs php-fpm, so a failed bind leaves a
container reporting Running with no web server at all. Both test pods
above were Running. The probes on /?action=health are what turn it into
a pod that never becomes Ready.

trivy config still reports 0 to act on; the KSV-0117 statement is
updated to the measured reasoning.
This commit is contained in:
jklein committed 2026-08-23 23:39:49 +02:00
1 parent e016650f91
commit 7e6b3beed5
4 files changed
+53 -10

No files matched your search

@@ -36,21 +36,27 @@ spec:
env:
{{- range $value := .Values.rssBridge.env }}
{{- if $value.value }}
- name: {{ $value.name }}
value: {{ tpl $value.value $ }}
- name: {{ $value.name | quote }}
# quote is required, not cosmetic: a value like "5" or "true"
# renders unquoted as a YAML number/bool, and the API server then
# rejects the whole manifest with "cannot unmarshal number into
# Go struct field EnvVar.value of type string". RSS-Bridge takes
# numeric settings this way (RSSBRIDGE_http_timeout), so this is
# reachable with the very first env entry someone adds.
value: {{ tpl $value.value $ | quote }}
{{- else if $value.valueFrom }}
{{- if $value.valueFrom.secretKeyRef }}
- name: {{ $value.name }}
- name: {{ $value.name | quote }}
valueFrom:
secretKeyRef:
name: {{ tpl $value.valueFrom.secretKeyRef.name $ }}
key: {{ tpl $value.valueFrom.secretKeyRef.key $ }}
name: {{ tpl $value.valueFrom.secretKeyRef.name $ | quote }}
key: {{ tpl $value.valueFrom.secretKeyRef.key $ | quote }}
{{- else if $value.valueFrom.configMapKeyRef }}
- name: {{ $value.name }}
- name: {{ $value.name | quote }}
valueFrom:
configMapKeyRef:
name: {{ tpl $value.valueFrom.configMapKeyRef.name $ }}
key: {{ tpl $value.valueFrom.configMapKeyRef.key $ }}
name: {{ tpl $value.valueFrom.configMapKeyRef.name $ | quote }}
key: {{ tpl $value.valueFrom.configMapKeyRef.key $ | quote }}
{{- end }}
{{- end }}
{{- end }}