Skip to content

Conversation

fernandezcuesta
Copy link

@fernandezcuesta fernandezcuesta commented Jun 25, 2025

  • Add extraInitContainers to celery+django deployments.
  • Add extraEnv to all deployments
  • Remove existing volume logic in favor of agnostic extraVolumes and extraVolumeMounts
  • Add the ability to deploy secrets as regular (non-hooked) resources due to issues found with ArgoCD
  • Make some secret references optional (secret might not be created)
  • Fix optional secret mounts + reference
  • Update bitnami chart reference (OCI)
  • Bump up redis chart

Reasoning behind the logic change for volumes, with the existing behaviour we cannot mount projected volumes (e.g. a secret mount where we want the key names being renamed) or per-container volumeMounts (e.g. nginx emptyDir when readOnlyRootFs is enforced).

- Add extraInitContainers to celery+django deployments.
- Add extraEnv to all deployments
- Remove existing volume logic in favor of agnostic extraVolumes and extraVolumeMounts
- Fix optional secret mounts + reference
- Update bitnami chart reference (OCI)
- Bump up redis chart
@github-actions github-actions bot added the helm label Jun 25, 2025
@fernandezcuesta fernandezcuesta changed the title **Summary:** feat: improve Helm chart Jun 25, 2025
Copy link

dryrunsecurity bot commented Jun 25, 2025

DryRun Security

This pull request introduces multiple security regressions: it weakens Redis TLS by defaulting Celery broker params to ssl_cert_reqs=optional (allowing MitM), makes DD_SECRET_KEY and DD_CREDENTIAL_AES_256_KEY optional, and adds CI log output that could expose those secrets. It also permits arbitrary YAML/env injection via extraEnv/extra* Helm values so an attacker who controls chart values can override critical environment variables or inject malicious pod configuration.

Weak SSL/TLS Configuration for Celery Broker in helm/defectdojo/templates/configmap.yaml
Vulnerability Weak SSL/TLS Configuration for Celery Broker
Description The Helm chart sets DD_CELERY_BROKER_PARAMS to ssl_cert_reqs=optional by default when Redis TLS is enabled but no specific parameters are provided. This configuration allows the Celery client to connect to the Redis server over TLS without validating the server's certificate. This is a form of Improper Certificate Validation (CWE-295), which makes the connection vulnerable to Man-in-the-Middle (MitM) attacks.

{{- $fullName := include "defectdojo.fullname" . -}}
{{- $defaultBrokerParams := ternary "ssl_cert_reqs=optional" "" .Values.redis.tls.enabled -}}
apiVersion: v1
kind: ConfigMap
metadata:

Arbitrary Environment Variable Override in helm/defectdojo/templates/initializer-job.yaml
Vulnerability Arbitrary Environment Variable Override
Description The Helm chart templates for various components (initializer, Celery worker, Celery beat, Django) allow arbitrary environment variables to be injected via extraEnv fields. These extraEnv blocks are rendered after critical, explicitly-defined environment variables (such as DD_SECRET_KEY, DD_CREDENTIAL_AES_256_KEY, and DD_DATABASE_PASSWORD). Due to Kubernetes' environment variable precedence rules (last definition wins), an attacker with control over the Helm values can override these sensitive variables.

name: {{ $fullName }}
- secretRef:
name: {{ $fullName }}
optional: true
- secretRef:
name: {{ $fullName }}-extrasecrets
optional: true
env:
- name: DD_DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.postgresql.auth.existingSecret }}
key: {{ .Values.postgresql.auth.secretKeys.userPasswordKey }}
{{- with .Values.initializer.extraEnv }}
{{- toYaml . | nindent 8 }}
{{- end }}
resources:

Missing Critical Secrets in helm/defectdojo/templates/django-deployment.yaml
Vulnerability Missing Critical Secrets
Description The Helm chart for DefectDojo now allows the DD_SECRET_KEY and DD_CREDENTIAL_AES_256_KEY environment variables to be optional in the django-deployment.yaml file. The DD_SECRET_KEY is analogous to Django's SECRET_KEY, which is fundamental for cryptographic signing, session integrity, and CSRF protection. If this key is missing, Django's security mechanisms are severely compromised. The DD_CREDENTIAL_AES_256_KEY is likely used for encrypting sensitive credentials. Making this optional could lead to credentials being stored or transmitted in an unencrypted or weakly encrypted manner.

secretKeyRef:
name: {{ $fullName }}
key: DD_SECRET_KEY
optional: true
- name: DD_CREDENTIAL_AES_256_KEY
valueFrom:
secretKeyRef:
name: {{ $fullName }}
key: DD_CREDENTIAL_AES_256_KEY
optional: true
- name: DD_SESSION_COOKIE_SECURE
value: {{- if or .Values.django.ingress.activateTLS .Values.django.nginx.tls.enabled }} "True" {{- else }} "False" {{- end }}
- name: DD_CSRF_COOKIE_SECURE
value: {{- if or .Values.django.ingress.activateTLS .Values.django.nginx.tls.enabled }} "True" {{- else }} "False" {{- end }}
{{- with .Values.extraEnv }}
{{- . | toYaml | nindent 8 }}
{{- end }}
{{- with .Values.django.uwsgi.extraEnv }}
{{- . | toYaml | nindent 8 }}
{{- end }}
{{- if .Values.django.uwsgi.livenessProbe.enabled }}
livenessProbe:

Increased Attack Surface via Flexible Configuration in helm/defectdojo/values.yaml
Vulnerability Increased Attack Surface via Flexible Configuration
Description The Helm chart introduces new configuration options (extraEnv, extraInitContainers, extraVolumes, livenessProbe, readinessProbe, startupProbe) for Celery Beat and Worker components. These options are rendered directly into the Kubernetes pod specification using toYaml, allowing for arbitrary YAML injection. This enables an attacker who can control the Helm values to inject malicious configurations, potentially leading to privilege escalation, command injection, or information disclosure.

# Components
celery:
broker: redis
logLevel: INFO
# Common annotations to worker and beat deployments and pods.
annotations: {}
beat:
# Annotations for the Celery beat deployment.
annotations: {}
affinity: {}
# Additional environment variables injected to Celery beat containers.
extraEnv: []
# A list of additional initContainers to run before celery beat containers.
extraInitContainers: []
# Array of additional volume mount points for the celery beat containers.
extraVolumeMounts: []
# A list of extra volumes to mount
# @type: array<map>
extraVolumes: []
# Enable liveness probe for Celery beat container.
livenessProbe: {}
# exec:
# command:
# - bash
# - -c
# - celery -A dojo inspect ping -t 5
# initialDelaySeconds: 30
# periodSeconds: 60
# timeoutSeconds: 10
nodeSelector: {}
# Annotations for the Celery beat pods.
podAnnotations: {}
# Enable readiness probe for Celery beat container.
readinessProbe: {}
replicas: 1
resources:
requests:

Information Disclosure (Sensitive Logs) in .github/workflows/k8s-tests.yml
Vulnerability Information Disclosure (Sensitive Logs)
Description The CI/CD workflow in .github/workflows/k8s-tests.yml now logs the last 30 lines of the uwsgi container's output on test failure. The uwsgi container is configured with sensitive environment variables, specifically DD_SECRET_KEY and DD_CREDENTIAL_AES_256_KEY. In the event of an unhandled exception or error within the Django application, a detailed stack trace or error message containing these sensitive environment variables could be logged to standard output/error. Since the repository is public, these logs would be publicly accessible via GitHub Actions, leading to the disclosure of critical secrets.

--max-time 20 \
--head \
--header "Host: $DD_HOSTNAME" \
"http://${DJANGO_IP}/login?next=/")
echo $OUT
CR=$(echo $OUT | egrep "^HTTP" | cut -d' ' -f2)
echo $CR
if [[ $CR -ne 200 ]]; then
echo $RETRY
if [[ $RETRY -gt 2 ]]; then
kubectl get pods
echo $(kubectl logs --tail=30 -l defectdojo.org/component=django -c uwsgi)
echo "ERROR: cannot display login screen; got HTTP code $CR"
exit 1
else


All finding details can be found in the DryRun Security Dashboard.

@Maffooch Maffooch changed the base branch from master to bugfix June 25, 2025 17:47
Copy link
Contributor

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@valentijnscholten
Copy link
Member

@fernandezcuesta Thanks for the PR, we'll ask some helm/k8s experienced devs to look at it. In the mean time could you look at the conflicts? Also this seems to be a bigger change, could you look at basing it against the dev branch

@fernandezcuesta fernandezcuesta changed the base branch from bugfix to dev June 26, 2025 06:28
Copy link
Contributor

Conflicts have been resolved. A maintainer will review the pull request shortly.

@fernandezcuesta
Copy link
Author

@valentijnscholten done, thanks for having a look at it! I also changed the base to dev branch.

@Maffooch Maffooch requested a review from rossops June 26, 2025 16:07
Copy link
Contributor

@kiblik kiblik left a comment

Choose a reason for hiding this comment

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

I will need more time for the rest (this is not my final review).

@valentijnscholten valentijnscholten added this to the 2.49.0 milestone Jun 29, 2025
@fernandezcuesta fernandezcuesta requested a review from kiblik July 23, 2025 11:49
Copy link
Contributor

Conflicts have been resolved. A maintainer will review the pull request shortly.

@fernandezcuesta
Copy link
Author

fernandezcuesta commented Aug 21, 2025

@kiblik Thanks for your detailed review and suggestions. I tried to go through all, but have some doubts about one of them (see inline comments).

@fernandezcuesta fernandezcuesta requested a review from kiblik August 21, 2025 12:05
Copy link
Contributor

@kiblik kiblik left a comment

Choose a reason for hiding this comment

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

Many of the issues have been solved; some small ones are still open.
However, I'm still missing some info in the release notes
Mainly parts that have potential side-effects (rename annotations ot podAnnotations in celery)

Comment on lines -493 to -494
# To use an external Redis instance, set enabled to false and uncomment
# the line below:
# redisServer: myrediscluster
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmmm... I'm just checking _helpers.tpl and I'm thinking what is the right approach here 🤔.

{{/*
Determine the hostname to use for PostgreSQL/Redis.
*/}}
{{- define "postgresql.hostname" -}}
{{- if .Values.postgresql.enabled -}}
{{- if eq .Values.postgresql.architecture "replication" -}}
{{- printf "%s-%s-%s" .Release.Name "postgresql" .Values.postgresql.primary.name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name "postgresql" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- else -}}
{{- printf "%s" ( .Values.postgresql.postgresServer | default "127.0.0.1" ) -}}
{{- end -}}
{{- end -}}
{{- define "redis.hostname" -}}
{{- if eq .Values.celery.broker "redis" -}}
{{- if .Values.redis.enabled -}}
{{- printf "%s-%s" .Release.Name "redis-master" | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s" (.Values.celery.brokerHost | default .Values.redis.redisServer) -}}
{{- end -}}
{{- end -}}
{{- end -}}

  • Postgres and Redis are both essential parts for DD.
  • They might be used as part of the stack, or both can be used aaS or any combination between
  • Postgres is used by all Django components (uwsgi, celery, initializer), same for Redis (well, except initializer, but definitely not only celery)
  • The following two statements should use the same conventions (they do not follow right now)
{{- printf "%s" ( .Values.postgresql.postgresServer | default "127.0.0.1" ) -}}
{{- printf "%s" (.Values.celery.brokerHost | default .Values.redis.redisServer) -}}

@github-actions github-actions bot added the docs label Aug 27, 2025
Copy link
Contributor

This pull request has conflicts, please resolve those before we can evaluate the pull request.

Copy link
Contributor

Conflicts have been resolved. A maintainer will review the pull request shortly.

Copy link
Contributor

@kiblik kiblik left a comment

Choose a reason for hiding this comment

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

Just a small issue - I would drop the Bitnami reference from the release notes (see the context)

And TBH, I would probably change the chart version to 1.7.1 (it needs to be 1.7.1-dev, the suffix will be removed during releasing).
Because this is a radical change, and it should be noticeable in the version number as well. It not only adds value, but it might also affect existing deployments.

Huge thanks, this PR is a large cleanup and makes the chart more flexible and easier to read and use.

@@ -53,15 +53,16 @@ Create the name of the service account to use
{{- printf "%s-%s" .Release.Name "postgresql" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- else -}}
{{- printf "%s" ( .Values.postgresql.postgresServer | default "127.0.0.1" ) -}}
{{- .Values.postgresServer | default "127.0.0.1" | quote -}}
Copy link
Contributor

Choose a reason for hiding this comment

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

CC @lchastel
JFYI, your #12965 has not been released yet, but it will probably change the format before it is officially released. Please see #12691 (comment) for full context.

Comment on lines -493 to -494
# To use an external Redis instance, set enabled to false and uncomment
# the line below:
# redisServer: myrediscluster
Copy link
Contributor

Choose a reason for hiding this comment

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

I really like this separation. I was planning to add values.schema.json (see #12984) to avoid wrong values. And I wasn't sure what to do with the overlap with subchart values. As soon as we separate them, it is much easier to adopt them.

Copy link
Contributor

github-actions bot commented Sep 2, 2025

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@valentijnscholten valentijnscholten modified the milestones: 2.50.0, 2.51.0 Sep 2, 2025
Copy link
Contributor

github-actions bot commented Sep 2, 2025

Conflicts have been resolved. A maintainer will review the pull request shortly.

@kiblik
Copy link
Contributor

kiblik commented Sep 3, 2025

I really hoped this will be part of 2.50.0
As it wasn't merged before release, changelog has to be moved to 2.51.md file.

@fernandezcuesta
Copy link
Author

I really hoped this will be part of 2.50.0 As it wasn't merged before release, changelog has to be moved to 2.51.md file.

Done!

Copy link
Contributor

@Maffooch Maffooch left a comment

Choose a reason for hiding this comment

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

Apologies for missing this one folks 😅

@valentijnscholten valentijnscholten merged commit 43434d6 into DefectDojo:dev Sep 5, 2025
85 checks passed
@valentijnscholten
Copy link
Member

@kiblik I merged this as it looks it's still valid and doesn't conflict with the vendoring of the bitnami charts we did last week?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants