nebari-dev / nebari-dev/data-science-pack
Security(H-05): RBAC bootstrap Job runs a mutable image with the Keycloak master-realm admin password
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 5
- Forks
- 7
- Avg merge
- 1d 20h
- Merged PRs (30d)
- 13
Description
Summary
The Keycloak RBAC bootstrap runs by default on NebariApp deployments as a post-install/post-upgrade Job. It pulls the mutable python:3.12-slim tag, receives the Keycloak master-realm admin password in its environment, and authenticates as admin to the master realm to reconfigure clients, mappers, roles, and redirects. The Job has no security context, no token opt-out, no resource limits, and no egress policy.
Severity: High · CWE-494 (Download of Code Without Integrity Check)
Validation: Confirmed against HEAD f932d80 on 2026-07-14 (assessed at 69c84f7; unchanged since).
Evidence
- Default-enabled:
templates/keycloak-rbac-bootstrap-job.yaml:27gates onnebariapp.enabled(values.yaml:47true) ANDrbac.bootstrap.enabled(values.yaml:279true) AND a non-empty credential secret (values.yaml:288keycloak-admin-credentials). - Mutable image:
values.yaml:326python:3.12-slim, referenced atkeycloak-rbac-bootstrap-job.yaml:91, no digest. - Master admin password in env:
keycloak-rbac-bootstrap-job.yaml:98-102injectsKC_ADMIN_PASSWORDfrom the credential secret. - Master-realm password grant as
admin:files/keycloak_rbac_bootstrap.py:105(/realms/master/protocol/openid-connect/token) and:124-129(grant_type=password&client_id=admin-cli&username=admin&password=...). - Mutations performed (
files/keycloak_rbac_bootstrap.py:474-502): group-membership mapper, hub OIDC client + service-account settings, redirect/rootUrl config, realm-management role binding, shared-directory client role, group-to-role assignment. - Missing hardening: no pod/container
securityContextin the Job spec (keycloak-rbac-bootstrap-job.yaml:87-126), so it runs as root; noautomountServiceAccountToken: false; no resource requests/limits; no egress NetworkPolicy.
Partial mitigations already present: the password is delivered via secretKeyRef (not hardcoded), the script ConfigMap is mounted read-only mode 0555, and ttlSecondsAfterFinished: 600 bounds the pod lifetime. These reduce but do not remove the exposure, since the password is readable in the running pod's environment and the container runs as root.
Impact
A compromised or moved image tag can read the master admin password and take control of Keycloak: alter clients, redirects, group assignments, roles, and identities across every service that trusts the realm. Pinning the Helm chart tag does not pin these runtime bytes.
Remediation
- Use a purpose-built image pinned by digest, signed, attested, and admission-verified.
- Replace the persistent master password with a narrowly scoped, short-lived provisioning identity, or move provisioning to a separately controlled infrastructure workflow.
- Disable the Job after one-time provisioning.
- Add token opt-out, strict egress, read-only filesystem, seccomp, capability, and resource controls.
- Rotate the admin password after migration.
Acceptance criteria
- No application-chart Job receives the master admin password.
- The provisioning identity cannot administer unrelated realms or clients.
- A mutable or unsigned bootstrap image is rejected.
- The Job can reach only the intended Keycloak endpoint.
Related
- #129 asks to set
runAsNonRoot: true/ non-zerorunAsUseron this Job (or document why not). This issue also covers the mutable image tag, the master-password model, token opt-out, resource limits, and egress policy.
Source: data-science-pack 0.1.0 security assessment (pinned commit 69c84f72df259ec755ed40bfc83f20158c550d55), finding H-05.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with templates/keycloak-rbac-bootstrap-job.yaml and values.yaml to trace when the Job is enabled, its image, credentials, and pod settings. Read files/keycloak_rbac_bootstrap.py around the token request and mutation calls, then review the related #129 work. Done means all listed acceptance criteria are met and the bootstrap path no longer exposes or over-privileges the master password.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- helm, kubernetes, python
- Domain
- authentication, authorization, devops, security
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100