Repository navigation
fix: quote/int-cast user values to prevent YAML injection - #188
Merged
Merged
Conversation
Onyxia fills chart values from user input and installs the chart as cluster-admin. Values interpolated unquoted (or wrapped only in literal quotes) could break out of their YAML scalar and inject arbitrary manifests. - Own templates, YAML scalars: `| quote`, `| int` for ports/replicas/probes, and `printf ... | quote` where literal text surrounds the value (images `repo:tag`, connection strings, test `args`). - Own templates, non-YAML payloads: `| toJson` for JSON/Python string contexts (cloudbeaver.conf, opensearch test script). - Values that land where escaping is impossible (XML in hive-metastore and trino core-site, trino .properties, pgadmin shell script, the S3 secret of the old library-chart used by spark-history / spark-thrift-server) or in third-party subcharts (Bitnami postgresql, chromadb, dask, elasticsearch, milvus, qdrant): a single-line `pattern` in values.schema.json, enforced by helm's schema validation before rendering. - postgresql-cnpg: `imageCatalog.major` default is now the string the schema declares (the chart did not render with its own defaults), and it is rendered with `| int` as the CNPG Cluster CRD expects an integer. Default renders are unchanged (compared object by object; only randomly generated secrets/certificates differ between renders), except the intended quoting in cloudbeaver.conf and the opensearch test script. Co-Authored-By: Claude Opus 5.5 <[email protected]>
utils/test_yaml_injection.py renders each chart with a `\n---` payload in every free-text schema field (feature flags of the field's parents switched on) and fails if a value breaks the rendered YAML or injects a document. Same script as helm-charts-interactive-services. The workflow tests the charts changed by a pull request or a push to main, and all charts on workflow_dispatch. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This was referenced Oct 23, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Onyxia fills chart values from user input and installs the chart as cluster-admin. Values interpolated without quoting (or wrapped only in literal quotes) can break out of their YAML scalar: a value with newlines and
---injects arbitrary manifests (e.g. aClusterRoleBindingtocluster-admin). Same class of bug as InseeFrLab/helm-charts-interactive-services#332.An audit rendering every free-text schema field with such a payload found 39 injectable fields in this repo's own templates and 22 more through third-party subcharts (plus fields behind disabled feature flags, e.g.
s3.*).Fix
| quote,| int(ports, replicas, probes),printf … | quotewhen text surrounds the value (repo:tag, connection strings, testargs)| toJson.properties(trino), shell (pgadmin), the S3 secret of the old library-chart (spark-history, spark-thrift-server), third-party subcharts (Bitnami postgresql, chromadb, dask, elasticsearch, milvus, qdrant)pattern(^[^\n\r]*$) invalues.schema.json— quoting is impossible there, helm rejects the value before renderingpatternis used rather thanformat: helm enforcespatternbut does not assertformat(anemail/urifield accepts any string).Also:
postgresql-cnpgdid not render with its own defaults (imageCatalog.major: 18vs the schema's string); the default is now"18"and it renders with| int, as the CNPGClusterCRD expects an integer.Regression test
utils/test_yaml_injection.py+.github/workflows/yaml-injection-test.yaml(same script as helm-charts-interactive-services): tests the charts changed by a PR / push to main, all charts onworkflow_dispatch. Feature flags of each field's parents are switched on so gated values are covered.Verification
| quoteis caught.cloudbeaver.confand the opensearch test script.helm lintpasses on every chart; versions bumped.Pre-existing bugs found (not fixed here)
route.enabledbreaks the chart (app.kubernetes.io/component: -label).opensearch.StrongPassworduses the user's password as aprintfformat string, so a password containing%is altered.Limits
patternprotection relies on helm's schema validation at install time (i.e. Onyxia not passing--skip-schema-validation).extraDeploy) are not covered by any chart-level fix; least privilege for the installing identity is the real boundary there.🤖 Generated with Claude Code