CVE-2026-89140 Overview
CVE-2026-89140 is a cross-namespace authorization flaw in Temporal Server that lets an authenticated caller tamper with Scheduler V2 schedules in a namespace other than their own. The server does not bind internal completion callbacks to the namespace that attached them. The reserved callback address temporal://internal bypasses the component.callbacks.allowedAddresses allowlist, and the History service delivers forged completions to the component named in the token without re-authorizing the caller. The flaw maps to CWE-639: Authorization Bypass Through User-Controlled Key.
Critical Impact
An authenticated user with write permission in one namespace can mark actions complete, defeat SKIP overlap policies, inject caller-controlled data as the last completion result, and pause Scheduler V2 schedules in another namespace.
Affected Products
- Temporal Server releases prior to v1.30.8
- Temporal Server releases prior to v1.31.4
- Temporal Server releases prior to v1.32.1
Discovery Timeline
- 2026-10-12 - CVE-2026-89140 published to NVD
- 2026-10-16 - Last updated in NVD database
Technical Details for CVE-2026-89140
Vulnerability Analysis
Temporal Server uses the Component-based Hierarchical State Machine (CHASM) callbacks subsystem to signal completion of Workflows started by Scheduler V2. The reserved address temporal://internal was treated as a privileged channel. The callbackValidatorProvider in service/frontend/fx.go constructed its validator without a namespace registry, so the validator could not confirm that the caller attaching the callback belonged to the namespace the callback targeted.
When a forged completion matches an in-flight action on a target schedule, the schedule records the action as complete even though the underlying Workflow continues to run. This defeats overlap policies such as SKIP, forwards caller-controlled data as the lastCompletionResult to the next scheduled Workflow, and may pause schedules configured to pause on failure. Workflow payloads and history were not disclosed.
Root Cause
The root cause is missing namespace binding on internal CHASM callbacks. The address temporal://internal was exempt from the operator-defined callback.allowedAddresses allowlist. The History service routed callbacks solely by the component token embedded in the request, without re-checking that the caller held write permission in the target namespace.
Attack Vector
The attacker is any authenticated principal with write permission in any namespace on the cluster. The attacker needs three pieces of context about the target: the target namespace identifier, the schedule identifier, and the identity plus timing of a running action. The attacker starts a Workflow in their own namespace and attaches a callback with address temporal://internal and a component token referencing the victim schedule.
The fix adds the namespace registry to the validator so that internal callbacks are bound to the originating namespace:
// Patched callback validator provider in service/frontend/fx.go
// Source: https://github.com/temporalio/temporal/commit/d0bd72e85014f31ecfbada1b436b08806496dbef
func callbackValidatorProvider(
dc *dynamicconfig.Collection,
namespaceRegistry namespace.Registry,
) callback.Validator {
return callback.NewValidator(
callback.MaxPerExecution.Get(dc),
dynamicconfig.FrontendCallbackURLMaxLength.Get(dc),
dynamicconfig.FrontendCallbackHeaderMaxSize.Get(dc),
callback.AllowedAddresses.Get(dc),
namespaceRegistry,
)
}
See GitHub Commit a210eeb and GitHub Pull Request #11876 for the full change set.
Detection Methods for CVE-2026-89140
Indicators of Compromise
- Workflow start requests that include a completion callback with address temporal://internal originating from a namespace that does not own the referenced component token.
- Scheduler V2 schedules reporting an action as completed while the corresponding Workflow execution is still in a Running state.
- Unexpected pauses on Scheduler V2 schedules configured with pause-on-failure, with no matching failure in the actual Workflow history.
- lastCompletionResult payloads that do not match the output of the previously executed scheduled Workflow.
Detection Strategies
- Audit Frontend service logs for StartWorkflowExecution and callback attachment calls where the callback URL equals temporal://internal and correlate the caller namespace to the component token namespace.
- Compare schedule action state against Workflow execution state across namespaces to find divergences where actions complete before Workflows terminate.
- Review History service callback delivery metrics for cross-namespace delivery patterns on the internal address.
Monitoring Recommendations
- Enable verbose auditing on Scheduler V2 namespaces and alert on schedule state transitions that lack a corresponding Workflow completion event.
- Track per-namespace counts of callbacks that use reserved internal addresses, flagging any originating from unexpected tenants.
- Forward Temporal Server audit and callback logs to a central analytics platform for cross-namespace correlation and retention.
How to Mitigate CVE-2026-89140
Immediate Actions Required
- Upgrade Temporal Server to v1.30.8, v1.31.4, or v1.32.1 or later, depending on the deployed minor version.
- Inventory all namespaces that currently hold Scheduler V2 schedules, since these remain targets even if the dynamic configuration that enabled Scheduler V2 is subsequently disabled.
- Review authenticated principals that have write permission in any namespace and revoke access that is no longer required.
Patch Information
Temporal published patched releases v1.30.8, v1.31.4, and v1.32.1. The core fix is tracked in Pull Request #11876 with backports in #12318, #12319, #12320, and #12382. The patches bind internal CHASM callbacks to the namespace that attached them by threading the namespace registry through callbackValidatorProvider.
Workarounds
- Disable Scheduler V2 and delete all existing Scheduler V2 schedules in affected namespaces until the server is patched, since schedules created while the feature was enabled remain targets.
- Restrict write permissions on namespaces so that only trusted principals can start Workflows and attach callbacks on the cluster.
- Isolate tenants onto separate clusters where feasible to limit the blast radius of a cross-namespace forgery.
# Verify running Temporal Server version and confirm patched build
temporal operator cluster describe --address <temporal-frontend>:7233 \
--output json | jq '.serverVersion'
# Disable Scheduler V2 as a temporary workaround (dynamic config)
# system.enableScheduler2: false
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

