KEDA 2.21 vs 2.20: CVE Fix & Breaking Scaler Changes

KEDA 2.21 vs 2.20: CVE Fix & Breaking Scaler Changes

KEDA 2.21 vs 2.20: CVE Fix and Breaking Changes

KEDA 2.21 vs 2.20 is not a routine point-release comparison you can skim and forget — it lands on the same day, September 23, 2026, that KEDA 2.19 reaches end of life, and it ships a fix for CVE-2026-77524, a privilege-escalation bug in how TriggerAuthentication handles service account tokens. If your cluster runs Vault Kubernetes auth or bound-service-account-token integrations for any KEDA-managed scaler, this is not a “get to it next sprint” upgrade. It also removes deprecated settings from the Temporal scaler and flips a default in the Azure Pipelines scaler that will silently change how aggressively your agents scale. What this covers: the CVE and who is exposed, the Kubernetes compatibility matrix shift, every breaking change with real specifics, the new scalers and reliability fixes, and a staged migration plan that won’t take down your event-driven workloads.

Context and Background

Before diving into the KEDA 2.21 vs 2.20 differences themselves, a quick refresher on what the project does. KEDA — Kubernetes Event-Driven Autoscaling — is the CNCF project that scales workloads based on external signals: queue depth, Kafka consumer lag, Prometheus query results, cloud provider metrics, and dozens of other event sources, rather than relying solely on CPU or memory utilization. If you’re new to how KEDA’s ScaledObject and ScaledJob resources translate external metrics into HPA-compatible scaling decisions, our architecture deep dive on KEDA event-driven autoscaling covers the mechanics in detail; this piece assumes that background and focuses narrowly on what changed between 2.20 and 2.21.

It’s worth being precise about what KEDA does and doesn’t do, because the two get conflated constantly. KEDA answers the question “how many pods should this Deployment or Job have right now, given what’s happening outside the cluster?” It doesn’t provision nodes. Cluster-level autoscalers like Karpenter or the Cluster Autoscaler answer a different question: “given the pods that exist and need scheduling, what nodes do we need?” These are complementary layers, not competing ones — KEDA drives pod count from event metrics, and the node autoscaler reacts to the resulting scheduling pressure. We’ve covered that node-level layer separately in our Karpenter vs Cluster Autoscaler GPU node scaling comparison, and understanding both halves matters here because a KEDA misconfiguration — like the Azure Pipelines default flip discussed below — doesn’t just change pod counts, it changes downstream node scaling behavior too.

The timing of KEDA 2.21 is what makes this release worth an urgent read rather than a changelog skim. KEDA’s support policy generally keeps two minor versions active, and KEDA 2.19 exits support on the exact same date 2.21 ships — September 23, 2026 — per endoflife.date’s structured release tracking for the project. That means teams still running 2.19 have zero overlap between “still supported” and “new release available.” If you’re on 2.20, you have one release of runway before you’re in the same position, and given how the breaking changes below stack up, that runway is shorter than it looks on paper.

It’s also worth naming why the KEDA 2.21 vs 2.20 gap matters more than a typical KEDA minor bump. Most KEDA releases are additive — new scaler types, new authentication methods, incremental reliability fixes — and teams can reasonably defer them for a quarter without consequence. This one bundles a security fix with a mandatory schema removal and a default-value change that alters production scaling math without throwing an error. That combination is unusual enough that treating 2.21 like “just another point release” is the mistake this guide is trying to help you avoid.

KEDA 2.21 vs 2.20: The Compatibility Shift and the CVE That Forces the Upgrade

Direct answer: KEDA 2.21 supports Kubernetes 1.34 through 1.36, up from 2.20’s 1.33-through-1.35 window, and it patches CVE-2026-77524, a TriggerAuthentication flaw that lets a workload escalate privileges through improperly scoped service account token audiences — serious enough that clusters using Vault or bound-token auth should treat this as a security patch, not a feature upgrade.

Figure 1 lays out the decision tree most platform teams will actually walk through this week: check your Kubernetes version against the new matrix, check your TriggerAuthentication configuration against the CVE’s blast radius, and route to either an urgent patch or a scheduled upgrade.

KEDA 2.21 upgrade decision flow covering Kubernetes compatibility and the CVE patch path

Figure 1: Decision flow for prioritizing the KEDA 2.21 upgrade based on Kubernetes version and TriggerAuthentication exposure.

Long description: the diagram starts from a cluster currently running KEDA 2.20, checks whether the cluster’s Kubernetes version falls in the 1.33-to-1.35 range that 2.20 supports, and branches based on that answer. A supported cluster proceeds to the EOL trigger — 2.20 will lose its buffer version once 2.21 line successors advance — and then checks whether TriggerAuthentication resources reference Vault or bound service account tokens. If they do, the path leads to an immediate patch; if not, it leads to a scheduled upgrade on the team’s normal cadence. A cluster outside the supported Kubernetes range is routed to align its Kubernetes version first. Both branches converge on upgrading to KEDA 2.21 and verifying the cluster now sits in the 1.34-to-1.36 supported window.

Kubernetes Version Support Matrix Explained

KEDA’s compatibility matrix moves in lockstep with upstream Kubernetes releases, but it lags by design — the project waits for a Kubernetes minor version to stabilize before adding it to the supported list, rather than chasing GA day. That’s the detail worth flagging explicitly here: Kubernetes 1.37 reached general availability on August 26, 2026, nearly a month before KEDA 2.21 shipped, and 2.21 still does not list 1.37 as supported. If you upgraded your control plane to 1.37 expecting KEDA to already have first-class support, check the release notes again — the safe supported range for 2.21 tops out at 1.36. Running KEDA on an unlisted Kubernetes version isn’t guaranteed to fail outright, since KEDA mostly rides on stable HPA and CRD APIs that don’t change dramatically between minors, but it’s untested territory the maintainers haven’t validated, and any bug report against that combination gets deprioritized. Teams that already jumped to 1.37 should either hold KEDA at 2.21 and wait for the next release to add support, or budget extra validation time before trusting autoscaling behavior on that combination in production.

CVE-2026-77524: TriggerAuthentication Privilege Escalation

The security fix in 2.21 addresses a gap in how TriggerAuthentication validates service account token audiences. TriggerAuthentication is the resource that tells a ScaledObject how to authenticate against an external system — a Vault cluster for secret retrieval, a cloud provider’s metadata service, or any integration that accepts a Kubernetes-issued bound service account token as a credential. Before the fix, KEDA didn’t enforce that the token audience presented to an external system matched what that system expected, which opened a path for a workload to potentially present a token scoped for one purpose and have it accepted somewhere it shouldn’t be — a textbook privilege-escalation pattern in token-based auth systems. The fix enforces explicit audience checking, which is the standard mitigation for this class of bug and mirrors similar hardening that’s happened elsewhere in the bound-service-account-token ecosystem over the past few years.

The practical exposure here isn’t universal. If your ScaledObjects authenticate purely through Kubernetes Secrets or static API keys, this CVE doesn’t touch your configuration. If you’re using Vault Kubernetes auth as your TriggerAuthentication provider, or any scaler configuration that relies on bound service account tokens for cross-system trust, you’re in the affected population and should not wait for a routine maintenance window.

To understand why audience scoping matters at all, it helps to remember what a bound service account token actually is. Since Kubernetes introduced the TokenRequest API, service account tokens are no longer long-lived static secrets mounted into every pod — they’re short-lived, cryptographically signed tokens that can be scoped to a specific audience, meaning a specific intended recipient service. A token minted for audience “vault” is supposed to be meaningless if presented to a different system; the receiving service is expected to check the audience claim and reject anything not addressed to it. The vulnerability here was on KEDA’s side of that contract: when KEDA’s TriggerAuthentication controller requested or forwarded these tokens, it wasn’t consistently enforcing that the audience matched what the target system expected, which weakens the isolation the audience mechanism is supposed to provide. This is the same general class of issue that has driven audience-scoping hardening across the broader Kubernetes ecosystem over the past several years, so KEDA closing this gap in 2.21 brings TriggerAuthentication in line with how the rest of the bound-token ecosystem already treats this boundary.

Why 2.20’s EOL Timing Raises the Stakes

Normally a CVE fix arriving in a new minor gives you some flexibility — you can often backport the specific fix or wait a few weeks while you plan a full upgrade. That flexibility is thinner here because of the EOL collision described above: KEDA doesn’t maintain long-lived security-only branches the way some larger projects do, so there’s no expectation of a 2.20.x patch release carrying just the CVE fix. The realistic path to being patched is the 2.21 upgrade itself, which means the security fix and the breaking changes below arrive as one bundle whether you want them separated or not.

Breaking Changes Walkthrough: Temporal, Azure Pipelines, and Liiklus

The compatibility and CVE story explains why you need to move. This section is about what actually breaks in the KEDA 2.21 vs 2.20 diff when you do, because two of the three changes here won’t show up as an obvious error message until something in production stops scaling the way it used to.

KEDA 2.21 Temporal scaler breaking change flow from deprecated fields to controller rejection

Figure 2: How a ScaledObject using deprecated Temporal scaler fields fails reconciliation after the KEDA 2.21 upgrade.

Long description: the diagram traces a ScaledObject that sets the deprecated buildId, selectAllActive, or selectUnversioned fields through a cluster upgrade to KEDA 2.21. The upgraded controller attempts to parse the Temporal trigger metadata, and because those fields no longer exist in the schema, the ScaledObject is rejected at reconcile time rather than silently ignored. The remediation path removes the deprecated fields and adopts the new composite backlog-and-workflow-count metric, after which the ScaledObject reconciles normally and Temporal-backed workloads resume scaling on 2.21.

Change KEDA 2.20 behavior KEDA 2.21 behavior Action required
TriggerAuthentication token audience No explicit audience enforcement (CVE-2026-77524) Explicit service account token audience required Upgrade; re-verify Vault/bound-token auth still authenticates
Temporal scaler fields buildId, selectAllActive, selectUnversioned accepted (deprecated) Fields removed entirely from schema Edit every affected ScaledObject/ScaledJob before or immediately after upgrade
Azure Pipelines scaleOnInFlight Defaults to false (queued jobs only) Defaults to true (queued + in-flight jobs) Set explicitly to false if you need the old counting behavior
Liiklus scaler Fully supported Deprecated, removal planned in a future release Plan migration off Liiklus; upstream project is unmaintained

Temporal Scaler: Deprecated Settings Are Gone, Not Just Discouraged

The Temporal scaler change is the sharpest edge in this release because it’s a hard schema removal, not a soft deprecation warning. If any of your ScaledObject or ScaledJob manifests still set buildId, selectAllActive, or selectUnversioned under the Temporal trigger metadata, those manifests will fail to parse once the 2.21 controller reconciles them — meaning the scaler stops functioning for that workload, not that it falls back to old behavior. A minimal before-and-after looks like this:

# KEDA 2.20 — will fail to parse on 2.21
triggers:
  - type: temporal
    metadata:
      namespace: production
      taskQueue: order-processing
      buildId: "v42"
      selectAllActive: "true"
# KEDA 2.21 — buildId/selectAllActive/selectUnversioned removed
triggers:
  - type: temporal
    metadata:
      namespace: production
      taskQueue: order-processing

The good news is that 2.21 doesn’t leave Temporal users with less capability — it adds a composite metric that combines backlog size with running workflow count, which is a more accurate signal for scaling decisions than the removed settings provided anyway. The practical step is to grep your GitOps repo for buildId, selectAllActive, and selectUnversioned under Temporal triggers before you upgrade the controller, not after. A pre-upgrade audit takes minutes; discovering the break in production because a Temporal worker pool silently stopped scaling takes considerably longer to diagnose.

Azure Pipelines: A Default Flip That Changes Real Scaling Math

The Azure Pipelines scaler change is more subtle because it’s not a removal — it’s a default value flip that produces no error at all, just different pod counts. scaleOnInFlight controls whether jobs that have already been picked up by an agent, but haven’t finished, count toward the queue length KEDA scales against. In 2.20, the default is false: only genuinely queued (unassigned) jobs drive scaling. In 2.21, the default is true: assigned-but-unfinished jobs now count too.

Sequence diagram comparing Azure Pipelines job counting before and after the scaleOnInFlight default flip

Figure 3: Under KEDA 2.20 defaults, only queued jobs count toward scaling; under 2.21 defaults, in-flight jobs count as well, producing extra replicas for the same queue.

Long description: the sequence shows a pipelines agent picking up a job and marking it assigned, then the DevOps queue reporting both queued and assigned jobs to the Azure Pipelines scaler. Under the KEDA 2.20 default, the scaler counts only queued jobs when instructing the HPA to scale. Under the KEDA 2.21 default, the scaler counts queued plus in-flight (assigned but unfinished) jobs, which produces additional replicas for what is otherwise an identical workload state.

If you didn’t set scaleOnInFlight explicitly because you were happy with 2.20’s default behavior, the upgrade changes that behavior underneath you without touching your manifest at all. For most teams this means somewhat more aggressive scale-out — more agents spin up for the same backlog, since in-progress jobs now add to the count — which can be a reasonable improvement if your build agents were under-provisioned for burst load, or an unwanted cost increase if they weren’t. If you want to preserve the old counting behavior, add scaleOnInFlight: "false" explicitly to the trigger metadata rather than relying on the default.

Liiklus Deprecation and the Quieter Additions

The Liiklus scaler is now formally deprecated because its upstream project is unmaintained, with removal planned for a future KEDA release — not this one, but the writing is on the wall if you’re still routing event sources through it. On the positive side of the ledger, 2.21 adds native scalers for GCP Cloud Spanner, ClickHouse, and Azure Cosmos DB Change Feed, along with new authentication options: Prometheus OAuth2 client-credentials flow, Kafka Kerberos credential-cache support, and Azure Pipelines service-principal authentication. External scalers also gain dynamic HPA target updates through a new StreamMetricSpec RPC, and controller sharding via label selectors was added for teams running KEDA at a scale where a single controller instance becomes a bottleneck.

Several reliability fixes are worth knowing about even if they don’t require action: a concurrent map write panic in the shared root CA CertPool is fixed, a nil-pointer dereference in customScalingStrategy.GetEffectiveMaxScale is fixed, gRPC reconnect backoff is restored after a regression where an unset backoff value caused zero-delay reconnect storms that flooded logs, and HTTP transports are now shared across scalers to prevent connection-pool exhaustion on clusters running large numbers of ScaledObjects. If you’ve seen mysterious log floods or occasional controller panics on 2.20 at scale, these fixes are likely the explanation, and they’re a reason to upgrade even setting the CVE aside.

Two of those fixes deserve a slightly longer explanation because they map directly to symptoms operators actually report. The gRPC reconnect storm happens when an external scaler connection drops and the client’s backoff configuration is effectively unset, so instead of retrying with increasing delay, the controller hammers the reconnect attempt as fast as the event loop allows — this shows up as a sudden, sustained spike in controller CPU and a log stream that becomes unreadable within seconds. If you’ve ever had to silence KEDA controller logs during an external scaler outage just to keep your log aggregation bill sane, that’s very likely this bug, and 2.21 restores sane exponential backoff so a single flaky connection degrades gracefully instead of drowning everything else. The HTTP transport sharing fix matters most on clusters with large ScaledObject counts — each scaler instance previously could open its own transport and connection pool, and at high enough object counts that adds up to file-descriptor pressure and connection churn against target systems that didn’t expect that many concurrent clients. Sharing transports across scalers is a straightforward fix, but it’s the kind of change that only becomes visible as a problem once you’re running KEDA at real scale, which is exactly the audience most likely to be reading a migration guide like this one.

One process note: starting with 2.21.0, release notes are generated from PR metadata and published only to the GitHub Releases page rather than being archived into CHANGELOG.md. If your team has a habit of grepping the changelog file for historical context, that workflow breaks going forward — bookmark the releases page instead.

Trade-offs, Gotchas, and What Goes Wrong

Across the full KEDA 2.21 vs 2.20 comparison, the single biggest risk in this upgrade isn’t the CVE fix itself — that’s a well-scoped, additive security check. It’s the combination of a hard schema break (Temporal) and a silent behavior change (Azure Pipelines) landing in the same release as a mandatory security patch. That combination pressures teams to move fast on the CVE while the two other changes need careful, unhurried auditing, and rushing the audit is exactly how a Temporal ScaledObject ends up rejected in production during what was supposed to be a security-driven maintenance window.

A second gotcha is the Kubernetes 1.37 gap. Teams that raced to adopt 1.37 for its scheduling and device-plugin improvements — see our coverage of DRA-based GPU device plugins on Kubernetes 1.37 and gang scheduling approaches on 1.37 — may assume KEDA has caught up by now. It hasn’t, as of 2.21. Running KEDA 2.21 on 1.37 isn’t reckless, but it is unvalidated, and any weirdness you hit won’t have prior art to search for.

Third, the Azure Pipelines default flip is easy to miss entirely because nothing fails. Your ScaledObject still reconciles, your agents still scale, and the only symptom is a shift in replica counts and, downstream, cloud spend on compute for those extra agents. If you have cost alerting on your CI/CD node pools, expect a step change after this upgrade unless you pin scaleOnInFlight explicitly. The direction of that change also isn’t uniformly bad — teams whose build agents were chronically under-provisioned during burst periods may find the new default actually fixes a latent problem, since in-flight jobs now contribute to scale-out decisions instead of being invisible to the scaler until they finish. The point isn’t that the new default is wrong; it’s that inheriting a behavior-changing default silently, without a deliberate choice, is the wrong way to arrive at either outcome.

A related, less obvious risk sits in the new controller sharding feature. Sharding by label selector is a genuine scalability improvement for large multi-tenant clusters running thousands of ScaledObjects, but it changes the operational model: instead of one controller reconciling everything, you now have multiple controller instances each responsible for a subset of objects, selected by label. Get the label selectors wrong during setup — overlapping ranges, or a gap that leaves some ScaledObjects unclaimed by any shard — and you can end up with objects that are either double-reconciled or silently orphaned and never reconciled at all. This isn’t a breaking change in the sense of something that stops working on upgrade, since sharding is opt-in, but it’s a new failure mode to understand before you adopt it, not after.

Fourth, the “release notes only on GitHub” process change quietly increases the operational burden of tracking future KEDA changes — if your team has any tooling that scrapes CHANGELOG.md for automated changelog aggregation, that tooling needs to point at the GitHub Releases API instead, or it will silently stop finding anything for versions after 2.20.

Finally, don’t treat this as a one-shot flag-day upgrade across your whole fleet. Figure 4 shows the staged rollout most teams should follow: audit for deprecated fields first, patch what needs patching, canary the new controller version in one namespace, watch specifically for Temporal reconciliation errors and Azure Pipelines scaling anomalies, and only then roll out cluster-wide.

KEDA 2.21 migration decision tree covering manifest audit, canary deployment, and rollback

Figure 4: Recommended staged rollout for KEDA 2.21, from manifest audit through canary validation to cluster-wide rollout, with an explicit rollback branch.

Long description: the flow begins with planning the upgrade and auditing all ScaledObjects and ScaledJobs for deprecated Temporal fields. If deprecated fields are found, manifests are patched before proceeding; if not, the flow moves directly to staging a canary namespace. The canary deployment runs KEDA 2.21 in isolation, and the team watches for errors or scaling regressions. If problems appear, the rollback branch reverts to 2.20, fixes the root cause, and loops back to the audit step. If the canary is clean, the team rolls out cluster-wide and moves into ongoing monitoring of the CVE patch’s effect on TriggerAuthentication flows and the Azure Pipelines scaling behavior change.

Practical Recommendations

Treat the KEDA 2.21 vs 2.20 upgrade as a security upgrade with migration homework attached, not a routine version bump you can automate blindly. Before you touch the controller version, run through this checklist:

  • Audit TriggerAuthentication usage. Identify every ScaledObject using Vault Kubernetes auth or bound service account tokens. These are your CVE-2026-77524 exposure surface and should drive your upgrade timeline, not your general maintenance calendar.
  • Grep for deprecated Temporal fields. Search your entire GitOps repository for buildId, selectAllActive, and selectUnversioned under type: temporal triggers, and remove or migrate them before the controller upgrade lands, not after.
  • Decide on scaleOnInFlight explicitly. Don’t inherit the new default silently. Set it to true if you want the improved in-flight accounting, or false if you need to preserve exact 2.20 scaling math, and document the choice.
  • Check your Kubernetes version against 1.34-1.36. If you’re already on 1.37, treat KEDA 2.21 as unvalidated on that combination and budget extra testing time, or hold at your current KEDA version until the next release adds support.
  • Plan a Liiklus exit if you’re still using it. It’s deprecated now; don’t wait for the removal release to start the migration.
  • Update your changelog tooling. Point any automated release-note scraping at the GitHub Releases page — CHANGELOG.md stops getting new entries starting with 2.21.0.
  • Canary before cluster-wide rollout. Use a single namespace or a non-critical workload class to validate Temporal and Azure Pipelines behavior before touching production-critical ScaledObjects.
  • Re-verify TriggerAuthentication post-upgrade. The audience-enforcement fix is correct behavior, but any TriggerAuthentication configuration that was implicitly relying on the old permissive check should be tested, not assumed to still work identically.
  • Approach controller sharding cautiously. If you’re adopting the new label-selector sharding for a large multi-tenant cluster, validate your label selectors cover every ScaledObject with no overlaps and no gaps before relying on it in production — an unclaimed object silently stops reconciling.
  • Watch controller resource usage after upgrade. The gRPC backoff and HTTP transport-sharing fixes should reduce CPU spikes and connection churn under load; if you were previously over-provisioning controller resources to compensate for those issues, this is a reasonable point to right-size them, but confirm with a few weeks of metrics before cutting limits.
  • Document the Kubernetes-version gap for your team. If you’re running or planning to run Kubernetes 1.37, make sure whoever owns the KEDA upgrade knows it’s outside the officially validated range for 2.21, so any scaling oddity gets investigated with that context rather than assumed to be unrelated.

Frequently Asked Questions

Is the KEDA 2.21 vs 2.20 upgrade mandatory because of the CVE?

It’s mandatory in practice for anyone using Vault Kubernetes auth or bound-service-account-token TriggerAuthentication, since KEDA doesn’t maintain a separate security-only patch branch for 2.20. If your TriggerAuthentication resources use static Secrets or API keys instead, you’re not directly exposed to CVE-2026-77524, but you should still plan the upgrade before 2.20 itself approaches end of life, since KEDA’s support window only covers two minor versions at a time.

Will my Temporal ScaledObjects break automatically on upgrade?

Only if they still reference the removed buildId, selectAllActive, or selectUnversioned fields. Manifests that don’t use those settings reconcile normally under 2.21. The failure mode is a parsing rejection at reconcile time, not a silent behavior change, so you’ll see it in controller logs or ScaledObject status conditions immediately rather than discovering it through a scaling incident — provided you’re watching those signals during the upgrade window.

What happens if I don’t set scaleOnInFlight explicitly?

You inherit the new default of true, meaning in-flight (assigned but unfinished) Azure Pipelines jobs now count toward the scaling metric alongside queued jobs. This typically produces more replicas for the same nominal backlog than 2.20 did. It’s not an error, so nothing will alert you unless you have scaling or cost monitoring in place — which is exactly why it’s worth setting the value explicitly rather than inheriting whichever default happens to ship.

Does KEDA 2.21 support Kubernetes 1.37?

Not officially, as of this release. KEDA 2.21’s supported range is 1.34 through 1.36, even though Kubernetes 1.37 reached general availability about a month before 2.21 shipped. Clusters on 1.37 can likely run KEDA 2.21 without immediate issues since HPA and CRD APIs are generally stable across minors, but the combination hasn’t been validated by the maintainers, so treat it as experimental until a future KEDA release adds explicit 1.37 support.

How does KEDA 2.21 relate to cluster autoscalers like Karpenter?

They operate at different layers and this release doesn’t change that relationship. KEDA decides how many pods a workload needs based on external event metrics; Karpenter or the Cluster Autoscaler then decides what nodes are needed to schedule those pods. The Azure Pipelines scaleOnInFlight default flip is a good example of why this matters here: more KEDA-driven replicas can trigger more node provisioning downstream, so a behavior change that looks purely pod-level can still move your node-autoscaling costs.

Should I migrate off the Liiklus scaler now or wait for removal?

Start planning now. KEDA has marked Liiklus deprecated because the upstream project is unmaintained, and while removal isn’t scheduled for 2.21 itself, deprecated scalers in KEDA’s history have generally been removed within a few subsequent minor releases. Waiting until the removal release forces an emergency migration; starting now gives you a normal-priority project instead.

Further Reading

For more background beyond this KEDA 2.21 vs 2.20 migration guide, the following cover the surrounding architecture and ecosystem:

By Riju — about

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *