[
https://issues.apache.org/jira/browse/FLINK-40414?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
ASF GitHub Bot updated FLINK-40414:
-----------------------------------
Labels: pull-request-available (was: )
> Autoscaler state ConfigMap is treated as trusted input
> ------------------------------------------------------
>
> Key: FLINK-40414
> URL: https://issues.apache.org/jira/browse/FLINK-40414
> Project: Flink
> Issue Type: Bug
> Components: Autoscaler, Kubernetes Operator
> Reporter: Dennis-Mircea Ciupitu
> Priority: Major
> Labels: pull-request-available
>
> h1. Summary
> The autoscaler persists its state in a per-resource ConfigMap
> ({{autoscaler-<name>}}): scaling history, collected metrics, scaling
> tracking, delayed scale-down, parallelism overrides and config overrides. The
> operator reads that ConfigMap back on every cycle and acts on its contents,
> but treats it as trusted input. The ConfigMap is writable by any workload in
> the namespace, so a poisoned or corrupt entry can break a reconcile or
> influence a managed deployment.
> h1. Trust boundary
> The autoscaler state ConfigMap is created and owned by the operator, but the
> default Flink job Role grants the job service account
> {{create/update/patch/delete}} on {{configmaps}} in its namespace (required
> for Kubernetes HA). Tenant code running in a TaskManager or JobManager pod
> can therefore write any ConfigMap in the namespace, including the autoscaler
> state of another job.
> Among the ConfigMaps the operator handles, only the autoscaler state
> ConfigMap has its content deserialized and acted upon. The generated cluster
> config and pod-template ConfigMaps are write-only from the operator, and the
> Kubernetes HA ConfigMaps are read only by name and key presence, never by
> value. The autoscaler state ConfigMap is the operator's untrusted-input
> surface.
> h1. Problems
> h2. Reads are not uniformly fail-closed
> The six read paths handle a bad stored value inconsistently:
> * {{getParallelismOverrides}} has no error handling. A malformed value throws
> out of the read and into the reconcile loop.
> * {{getConfigChanges}} falls back to empty on a bad value but does not
> discard the poisoned entry, so it is re-read and re-parsed every cycle.
> * The remaining four discard the bad entry and fall back to empty.
> So the same class of input is variously ignored, re-read, or allowed to
> propagate an exception.
> h2. Config overrides are applied to the deployment spec unfiltered
> When memory tuning is enabled, the config overrides read from the ConfigMap
> are merged into {{spec.flinkConfiguration}} with no key filtering. A poisoned
> entry can therefore inject arbitrary Flink configuration, for example
> {{env.java.opts}} or a pod template, into a managed deployment. This is an
> escalation from "write one ConfigMap" to influencing how and what the managed
> cluster runs, potentially across jobs within a namespace.
> h2. No value sanity
> Values read from the ConfigMap, such as the per-vertex parallelism overrides,
> are applied without basic validity checks.
> h1. Impact
> * Integrity and availability: a crafted entry can break a reconcile through
> an unhandled exception, or feed the autoscaler bogus history and metrics that
> steer scaling for that job or a co-tenant.
> * Config injection: with memory tuning enabled, arbitrary Flink configuration
> reaches the managed deployment spec.
> * Current exposure is bounded by {{job.autoscaler.memory.tuning.enabled}}
> (default off) for the injection path, but the design flaw is independent of
> that flag.
> This is not a deserialization remote-code-execution issue. The mapper uses no
> default typing and binds to concrete types, so malformed input fails to bind
> rather than instantiating arbitrary classes. The risk is integrity,
> availability and config injection.
> h1. Scope
> This completes the autoscaler-adjacent security review alongside FLINK-40400
> (artifact fetch SSRF) and FLINK-40401 (decompression bomb on the compressed
> state fields). Those two harden individual fields or paths as issues
> surfaced. This item addresses the general untrusted-read boundary of the
> state ConfigMap so the class of problem is closed rather than one instance.
> h1. Proposed approach
> At a high level:
> * Treat every read from the autoscaler state ConfigMap as untrusted:
> deserialize uniformly and fail closed, discarding the offending entry and
> falling back to empty on any failure, plus light value sanity on the values
> that are applied.
> * Filter config overrides on apply against the set of keys memory tuning is
> actually allowed to set, so that only memory-tuning keys can reach the
> deployment spec.
> Out of scope: deeper hardening of scaling decisions against plausible but
> wrong metrics, and the decompression size bound owned by FLINK-40401.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)