CVEReports
Reports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Reports
  • Sitemap
  • RSS Feed

Company

  • About
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Powered by Google Gemini & CVE Feed

|
•

CVE-2025-14987
CVSS 5.3|EPSS 0.05%

Temporal Paradox: The Cross-Namespace Authorization Bypass

Amit Schendel
Amit Schendel
Senior Security Researcher•January 2, 2026•5 min read
PoC Available

Executive Summary (TL;DR)

Temporal trusted the envelope but ignored the letter inside. A worker authorized for 'Namespace A' could embed commands targeting 'Namespace B' within a standard task completion response. Because the server only validated the worker's access to 'Namespace A', the cross-namespace commands were executed without a secondary permission check. Fixed by adding 'Deep Inspection' logic to the authorization layer.

A logic flaw in Temporal's gRPC authorization interceptor allows authenticated workers in one namespace to execute unauthorized commands (Signaling, Canceling, etc.) against workflows in a completely different namespace.

The Hook: Multi-Tenancy's Thin Veneer

Temporal is the engine that drives reliable, durable execution for code that simply cannot fail. It's the backbone for microservices orchestration at scale. One of its key selling points for SaaS providers is the concept of Namespaces. These are supposed to be hard isolation boundaries—Tenant A plays in their sandbox, and Tenant B plays in theirs.

But here's the thing about boundaries in complex distributed systems: they are often enforced at the front door, but forgotten once you're inside the hallway. CVE-2025-14987 is a classic example of 'Shallow Inspection'.

Imagine a secure mailroom. The guard checks your ID badge to make sure you are allowed to send mail from your department. But once you hand over the envelope, the guard doesn't bother to check if the letter inside is a bomb addressed to the CEO. You're authorized to send mail, so the system assumes your mail is safe. In Temporal's case, the 'bomb' was a cross-namespace command.

The Flaw: Trusting the Messenger

To understand this bug, you have to understand the Temporal Worker lifecycle. Workers don't just execute code; they drive the state of the workflow. They poll for tasks, do some work, and then call RespondWorkflowTaskCompleted to tell the server what happened.

Crucially, this response payload contains a list of Commands. These are instructions for the server: 'Start a timer', 'Run an activity', or—more dangerously—'Signal an external workflow'.

Before the fix, Temporal's authorization interceptor checked permissions based solely on the source namespace of the request. If I am a worker for namespace-attacker, and I send a RespondWorkflowTaskCompleted request, the server asks: "Does this user have write access to namespace-attacker?" The answer is yes.

However, if I enabled system.enableCrossNamespaceCommands (which is true by default), I could embed a command inside that response saying: "Hey, please also signal workflow ID 123 in namespace-victim." The server, having already cleared me at the gate, would take that command and pass it to the History service for execution. The History service assumed the Frontend service did its job. The Frontend service assumed checking the envelope was enough. The result? A confusingly authorized bypass.

The Code: Adding Deep Inspection

The fix required moving from shallow inspection to deep inspection. The developers had to crack open the RespondWorkflowTaskCompleted payload and iterate through every single command to see if it touched a namespace other than the caller's.

Here is the critical logic added to common/authorization/interceptor.go in commit b292a32bacdfa6472affd90f0a940408d5839cfa. It's a loop of scrutiny:

// The new sheriff in town: authorizeTargetNamespaces
func (a *Interceptor) authorizeTargetNamespaces(...) error {
    // ... setup code ...
 
    // Iterate through every command in the response
    for _, cmd := range wftRequest.GetCommands() {
        var targetNamespace string
        var apiName string
 
        // Switch on command type to find the 'target'
        switch cmd.GetCommandType() {
        case enumspb.COMMAND_TYPE_SIGNAL_EXTERNAL_WORKFLOW_EXECUTION:
            if attr := cmd.GetSignalExternalWorkflowExecutionCommandAttributes(); attr != nil {
                targetNamespace = attr.GetNamespace()
                apiName = "SignalWorkflowExecution"
            }
        // ... (checks for Cancel and StartChild as well)
        }
 
        // THE FIX: If we are crossing boundaries, RE-AUTHORIZE.
        if targetNamespace != "" && targetNamespace != sourceNamespace {
            if err := a.Authorize(ctx, claims, &CallTarget{
                APIName:   api.WorkflowServicePrefix + apiName,
                Namespace: targetNamespace, // Check permissions for the TARGET
                Request:   req,
            }); err != nil {
                return err
            }
        }
    }
    return nil
}

This code explicitly checks if targetNamespace != sourceNamespace. If they differ, it forces a secondary Authorize call against the target. No more free rides.

The Exploit: Trojan Horse Workflow

Exploiting this requires a valid worker credential for any namespace on the cluster. It is an authenticated attack, which explains the CVSS score of 5.3, but in a multi-tenant environment, tenant isolation is everything.

The Setup:

  1. Attacker: Has full control over namespace-red.
  2. Victim: Runs critical payments in namespace-blue.
  3. Config: system.enableCrossNamespaceCommands is true (default).

The Attack Chain:

  1. The attacker writes a malicious Workflow Definition. Instead of doing actual work, this workflow generates a SignalExternalWorkflowExecution command.
  2. The attacker configures this command to target namespace-blue and a known Workflow ID (often predictable or discoverable via enumeration).
  3. The attacker's worker runs this workflow in namespace-red.
  4. When the worker completes the task, it sends RespondWorkflowTaskCompleted to the server.

The Payload:

{
  "namespace": "namespace-red",
  "commands": [
    {
      "commandType": "COMMAND_TYPE_SIGNAL_EXTERNAL_WORKFLOW_EXECUTION",
      "attributes": {
        "namespace": "namespace-blue",
        "workflowExecution": { "workflowId": "payment-process-101" },
        "signalName": "CancelPayment",
        "input": "..."
      }
    }
  ]
}

The Result: The server authorizes the request for namespace-red. It then processes the command list. It sees the signal for namespace-blue and executes it. The payment workflow in the victim namespace receives the signal and cancels the transaction. Chaos ensues.

The Fix: Trust, but Verify Everything

Mitigation comes in two flavors: the patch and the configuration hammer.

1. The Patch (Preferred) Upgrade your Temporal cluster to version 1.29.2, 1.28.2, or 1.27.4. These versions include the deep inspection logic shown above. This allows legitimate cross-namespace communication (if you have the right permissions) while blocking unauthorized attempts.

2. The Configuration Hammer If you can't patch immediately, you can simply turn off the feature that allows this behavior. Set the dynamic configuration system.enableCrossNamespaceCommands to false.

[!NOTE] Disabling this setting is a breaking change for workflows that legitimately rely on cross-namespace signaling. However, if you are running a strictly isolated multi-tenant environment, you probably wanted this disabled anyway.

Official Patches

TemporalRelease notes for version 1.29.2

Fix Analysis (1)

Technical Appendix

CVSS Score
5.3/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:L/VA:L/SC:L/SI:L/SA:L
EPSS Probability
0.05%
Top 100% most exploited

Affected Systems

Temporal Server

Affected Versions Detail

ProductAffected VersionsFixed Version
Temporal Server
Temporal
<= 1.27.31.27.4
Temporal Server
Temporal
1.28.0 - 1.28.11.28.2
Temporal Server
Temporal
1.29.0 - 1.29.11.29.2
AttributeDetail
CVE IDCVE-2025-14987
CVSS 4.05.3 (Medium)
CWECWE-863 (Incorrect Authorization)
VectorCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:L/VA:L/SC:L/SI:L/SA:L
ImpactCross-Namespace Command Execution
Patch Commitb292a32bacdfa6472affd90f0a940408d5839cfa

MITRE ATT&CK Mapping

MITRE ATT&CK Mapping

T1068Exploitation for Privilege Escalation
Privilege Escalation
T1565.001Data Manipulation: Stored Data Manipulation
Impact
CWE-863
Incorrect Authorization

The product provides an authorization method that does not properly verify that the user has the necessary permissions to access the requested resource.

Exploit Resources

Known Exploits & Detection

GitHubUnit tests demonstrating the authorized vs unauthorized cross-namespace behavior

Vulnerability Timeline

Vulnerability Timeline

Patch authored and committed
2025-02-04
Advisory Published
2025-02-12

References & Sources

  • [1]GitHub Security Advisory
  • [2]Patch Commit
Related Vulnerabilities
CVE-2025-14986

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.