Skip to main content
Vulnerability Database/CVE-2026-65651

CVE-2026-65651: temporalio/sqlparser Stack Overflow DoS

CVE-2026-65651 is a denial of service flaw in temporalio/sqlparser that allows attackers to trigger stack overflow through deeply nested SQL expressions. This post explains its impact, affected systems, and mitigation steps.

Published:

CVE-2026-65651 Overview

CVE-2026-65651 is a denial-of-service vulnerability in the temporalio/sqlparser library. The parser accepts SQL containing deeply nested unary expressions and returns a correspondingly deep abstract syntax tree (AST) without enforcing a nesting limit. Recursive String and Walk operations on the tree can trigger a fatal Go stack overflow that terminates the host process. Go panic recovery cannot contain this condition. Temporal Server routes caller-controlled query input through the affected parser in archival, visibility, and worker-query paths. An authenticated caller holding namespace read permission can crash Frontend or Matching processes and sustain denial of service through repeated requests. The weakness is classified under [CWE-674: Uncontrolled Recursion].

Critical Impact

An authenticated attacker with namespace read permission can crash Temporal Server Frontend or Matching processes and maintain a persistent denial-of-service condition through repeated crafted queries.

Affected Products

  • temporalio/sqlparser prior to v0.1.0
  • Temporal Server versions prior to v1.30.7
  • Temporal Server versions prior to v1.31.3

Discovery Timeline

  • 2026-09-21 - CVE-2026-65651 published to NVD
  • 2026-09-22 - Last updated in NVD database

Technical Details for CVE-2026-65651

Vulnerability Analysis

The defect resides in the SQL grammar and AST consumers within temporalio/sqlparser. Left-recursive grammar rules such as NOT expression allow attackers to construct inputs whose parsed AST grows linearly with the input length. The parser itself does not exhaust stack during parsing because the grammar avoids parser-stack growth for left-recursive rules. However, the resulting left-heavy AST forces recursive consumers like Walk and Format to recurse to a depth equal to input nesting.

When Temporal Server encounters an invalid expression during validation, it recursively formats the expression to build an error message. That format call recurses through the deep AST, exhausts the goroutine stack, and triggers a runtime-fatal stack overflow. Because Go stack overflows bypass recover(), the entire process terminates. The impact is limited to availability; no read or write of protected data occurs.

Root Cause

The root cause is missing depth enforcement in temporalio/sqlparser. Grammar productions for unary operators such as NOT produced arbitrarily deep AST nodes, and no counter tracked nesting during parsing. Downstream traversal functions relied on native recursion, so tree depth translated directly into stack frames.

Attack Vector

An authenticated caller with namespace read permission submits a query containing thousands of chained unary operators through archival, visibility, or worker-query endpoints. The ListWorkers route additionally requires at least one retained worker heartbeat. When the Server validates the expression and constructs an error, the recursive Format call overflows the stack and terminates the receiving Frontend or Matching process.

go
// Security patch in ast.go - Limit depth of nested expressions (#6)
// maxExprDepth bounds the depth of the parsed Expr tree. Left-recursive
// rules (a AND b AND c ...) don't grow the parser stack, but produce a
// left-heavy AST whose depth scales with input length; deep trees can
// stack-overflow recursive AST consumers (Walk, Format, ...).
const maxExprDepth = 1000

Source: temporalio/sqlparser commit 0466b6b

The grammar was updated to increment and decrement a nesting counter around recursive productions:

text
| NOT
  {
    if incNesting(yylex) {
      yylex.Error("max nesting level reached")
      return 1
    }
  }
  expression
  {
    $$ = &NotExpr{Expr: $3}
    decNesting(yylex)
  }

Source: temporalio/sqlparser commit 0466b6b

Detection Methods for CVE-2026-65651

Indicators of Compromise

  • Unexpected termination of Temporal Frontend or Matching processes with Go runtime fatal error: stack overflow messages in logs.
  • Repeated crashes of the same service correlated with authenticated calls to archival, visibility, or ListWorkers endpoints.
  • Query payloads containing long chains of repeated unary tokens such as NOT NOT NOT ... in request bodies.

Detection Strategies

  • Inspect Temporal Server logs for panics referencing runtime.morestack or stack overflow signatures tied to sqlparser frames.
  • Monitor request bodies to visibility and worker-query APIs for anomalously long query strings or high operator repetition counts.
  • Correlate authenticated namespace read events with subsequent Frontend or Matching process restarts.

Monitoring Recommendations

  • Track process uptime and restart counts for Temporal Frontend, History, and Matching services and alert on sudden decreases.
  • Enable request-size ceilings and log queries exceeding operator-count thresholds at ingress proxies.
  • Forward Temporal Server telemetry into a centralized data lake for correlation of caller identity, endpoint, and crash events.

How to Mitigate CVE-2026-65651

Immediate Actions Required

  • Upgrade Temporal Server to v1.30.7, v1.31.3, or later, which incorporate the patched temporalio/sqlparser.
  • Update direct consumers of temporalio/sqlparser to v0.1.0 or later.
  • Audit namespace read permissions and revoke access for callers that do not require query capabilities.

Patch Information

The fix is delivered in temporalio/sqlparser v0.1.0 via Pull Request #6 and Pull Request #7. It introduces a maxExprDepth constant of 1000 and instruments the grammar with incNesting/decNesting counters that reject inputs exceeding the limit. Temporal Server integrations landed via Pull Request #11202 and shipped in Temporal Server v1.30.7 and v1.31.3.

Workarounds

  • Place an ingress filter in front of Temporal Frontend that rejects query strings above a defined length or operator count.
  • Restrict namespace read permissions to trusted identities until patched builds are deployed.
  • Disable or gate the ListWorkers route where operationally feasible to reduce the attack surface.
bash
# Configuration example: pin patched versions in go.mod
go get github.com/temporalio/sqlparser@v0.1.0
go get go.temporal.io/server@v1.31.3
go mod tidy

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.