Every CVE Search/ Get API key

CVE-2026-59168

Dasel: Unbounded recursion in JSON and XML readers causes unrecoverable stack-overflow DoS

6.2 MediumFix available

Dasel is a command-line tool and library for querying, modifying, and transforming data structures. From 3.0.0 until 3.11.1, parsing/json/json_reader.go decodeValue, decodeObject, and decodeArray, and parsing/xml/reader.go parseElement, recurse once per input nesting level without a depth guard. Deeply nested attacker-controlled JSON or XML supplied through parsing.Format(...).NewReader(...).Read(data), the command-line interface, or the parse selector function can exhaust the Go goroutine stack and raise an unrecoverable fatal error that terminates the entire process. The XML input-size limit does not prevent depth exhaustion, and defer or recover cannot intercept the failure. This issue is fixed in version 3.11.1.

Attack profile

How easy it is to exploit

Attack vector
Local
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
None
Availability
High

Exploit likelihood

0.13%Unchanged since Sep 22, 2026
90%50%10%1%

What each source reports

CVE List Score used 6.2

Dasel: Unbounded recursion in JSON and XML readers causes unrecoverable stack-overflow DoS

Dasel is a command-line tool and library for querying, modifying, and transforming data structures. From 3.0.0 until 3.11.1, parsing/json/json_reader.go decodeValue, decodeObject, and decodeArray, and parsing/xml/reader.go parseElement, recurse once per input nesting level without a depth guard. Deeply nested attacker-controlled JSON or XML supplied through parsing.Format(...).NewReader(...).Read(data), the command-line interface, or the parse selector function can exhaust the Go goroutine stack and raise an unrecoverable fatal error that terminates the entire process. The XML input-size limit does not prevent depth exhaustion, and defer or recover cannot intercept the failure. This issue is fixed in version 3.11.1.

Record
CVE-2026-59168
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-674
Updated
2026-11-02
EUVDEUVD-2026-84017 6.2

Dasel is a command-line tool and library for querying, modifying, and transforming data structures. From 3.0.0 until 3.11.1, parsing/json/json_reader.go decodeValue, decodeObject, and decodeArray, and parsing/xml/reader.go parseElement, recurse once per input nesting level without a depth guard. Deeply nested attacker-controlled JSON or XML supplied through parsing.Format(...).NewReader(...).Read(data), the command-line interface, or the parse selector function can exhaust the Go goroutine stack and raise an unrecoverable fatal error that terminates the entire process. The XML input-size limit does not prevent depth exhaustion, and defer or recover cannot intercept the failure. This issue is fixed in version 3.11.1.

Record
EUVD-2026-84017
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Updated
2026-11-02
GitHub AdvisoriesGHSA-cqxr-jxr2-85pq 6.2

Dasel: Unbounded recursion in JSON and XML readers causes unrecoverable stack-overflow DoS

Summary

dasel's JSON and XML readers parse nested structures with unbounded recursion, one native stack frame per nesting level, with no depth guard. A small (sub-10 MB), deeply nested document drives the Go runtime past its goroutine stack limit and triggers a fatal error: stack overflow. This is unrecoverable: it is a runtime fatal error, not a panic, so a consumer's defer/recover cannot intercept it, the entire process dies.

Both readers are affected; neither has a depth limit, and the JSON reader additionally has no input-size cap (the XML reader caps size at 10 MB but not depth).

Affected Versions

github.com/tomwright/dasel/v3 and all v3.x releases through v3.11.0 (current main, commit abc1e1d). This vulnerability is fixed in 3.11.1. Pre-v3 is out of scope.

Description

JSON reader @ parsing/json/json_reader.go

decodeValue (line 54) dispatches to the mutually-recursive decodeObject (line 78) and decodeArray (line 140). Each calls back into both for nested values (decodeArray→decodeArray at line 151, decodeObject at 163; decodeObject→decodeArray at 95, decodeObject at 111). Every [ or { in the input adds one stack frame. There is no depth counter and no len(data) cap anywhere in the reader.

XML reader @parsing/xml/reader.go

parseElement (line 172) recurses at line 211 for every xml.StartElement. The file declares explicit DoS guards — maxXMLSize = 10_000_000, comment count/length — but these bound size and comment volume, not nesting depth. The open tag <a> is 3 bytes, so the 10 MB cap still permits ~3.3 M nesting levels, exhausting the stack long before the size limit fires.

Reachability (both)

Both are on the primary public read path: parsing.Format(<fmt>).NewReader(opts).Read(data), with data fully attacker-controlled and no depth validation before the recursion. The same path backs the dasel CLI (dasel -r json / -r xml). Default reader, no special options. Go stack overflow is a fatal error, so recover() at the call site does not help.

Precedent in this codebase

DoS hardening on the readers is already an accepted concern here, which is why this is a gap rather than a design choice: the XML reader has the maxXMLSize cap, and the YAML reader already implements exactly the fix needed, parsing/yaml/yaml_reader.go:31,90-93 returns ErrYamlExpansionDepthExceeded once expansionDepth > maxExpansionDepth. The JSON and XML readers simply lack the equivalent depth guard.

Proof of Concept

Single runnable program, public API only (poc/main.go, module wired to a local clone via replace):

package main

import (
	"fmt"; "os"; "strings"
	"github.com/tomwright/dasel/v3/parsing"
	_ "github.com/tomwright/dasel/v3/parsing/json"
	_ "github.com/tomwright/dasel/v3/parsing/xml"
)

func main() {
	mode := "json"; if len(os.Args) > 1 { mode = os.Args[1] }
	depth := 6_000_000; if mode == "xml" { depth = 3_200_000 }

	var data []byte
	if mode == "xml" {
		data = []byte(strings.Repeat("<a>", depth))          // ~9.6MB, under the 10MB cap
	} else {
		data = []byte(strings.Repeat("[", depth) + strings.Repeat("]", depth)) // ~12MB
	}

	defer func() { if r := recover(); r != nil { fmt.Println("recovered (NOT fatal):", r) } }()
	r, _ := parsing.Format(mode).NewReader(parsing.DefaultReaderOptions())
	v, err := r.Read(data)
	fmt.Printf("Read returned WITHOUT crash: v=%v err=%v\n", v != nil, err)
}
go run . json    # nested arrays -> fatal error: stack overflow ; ~85 decodeArray frames
go run . xml     # nested <a>    -> fatal error: stack overflow ; ~93 parseElement frames

Observed (Go 1.26, default 1 GB goroutine stack):

  • json depth 6 M (12 MB): runtime: goroutine stack exceeds 1000000000-byte limit → fatal error: stack overflow; backtrace dominated by json.(*jsonReader).decodeArray. depth 2 M completes (~0.83 s), confirming it is depth-driven, not a parse error.
  • xml…
Record
GHSA-cqxr-jxr2-85pq
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-674
Updated
2026-11-02
NVD 6.2

Dasel is a command-line tool and library for querying, modifying, and transforming data structures. From 3.0.0 until 3.11.1, parsing/json/json_reader.go decodeValue, decodeObject, and decodeArray, and parsing/xml/reader.go parseElement, recurse once per input nesting level without a depth guard. Deeply nested attacker-controlled JSON or XML supplied through parsing.Format(...).NewReader(...).Read(data), the command-line interface, or the parse selector function can exhaust the Go goroutine stack and raise an unrecoverable fatal error that terminates the entire process. The XML input-size limit does not prevent depth exhaustion, and defer or recover cannot intercept the failure. This issue is fixed in version 3.11.1.

Record
CVE-2026-59168
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-674
Updated
2026-11-02
OSV 6.2

Dasel: Unbounded recursion in JSON and XML readers causes unrecoverable stack-overflow DoS

Dasel is a command-line tool and library for querying, modifying, and transforming data structures. From 3.0.0 until 3.11.1, parsing/json/json_reader.go decodeValue, decodeObject, and decodeArray, and parsing/xml/reader.go parseElement, recurse once per input nesting level without a depth guard. Deeply nested attacker-controlled JSON or XML supplied through parsing.Format(...).NewReader(...).Read(data), the command-line interface, or the parse selector function can exhaust the Go goroutine stack and raise an unrecoverable fatal error that terminates the entire process. The XML input-size limit does not prevent depth exhaustion, and defer or recover cannot intercept the failure. This issue is fixed in version 3.11.1.

Record
CVE-2026-59168
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-674
Updated
2026-11-02
OSVDEBIAN-CVE-2026-59168 6.2

Dasel is a command-line tool and library for querying, modifying, and transforming data structures. From 3.0.0 until 3.11.1, parsing/json/json_reader.go decodeValue, decodeObject, and decodeArray, and parsing/xml/reader.go parseElement, recurse once per input nesting level without a depth guard. Deeply nested attacker-controlled JSON or XML supplied through parsing.Format(...).NewReader(...).Read(data), the command-line interface, or the parse selector function can exhaust the Go goroutine stack and raise an unrecoverable fatal error that terminates the entire process. The XML input-size limit does not prevent depth exhaustion, and defer or recover cannot intercept the failure. This issue is fixed in version 3.11.1.

Record
DEBIAN-CVE-2026-59168
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Updated
2026-11-02
OSVGHSA-cqxr-jxr2-85pq 6.2

Dasel: Unbounded recursion in JSON and XML readers causes unrecoverable stack-overflow DoS

Summary

dasel's JSON and XML readers parse nested structures with unbounded recursion, one native stack frame per nesting level, with no depth guard. A small (sub-10 MB), deeply nested document drives the Go runtime past its goroutine stack limit and triggers a fatal error: stack overflow. This is unrecoverable: it is a runtime fatal error, not a panic, so a consumer's defer/recover cannot intercept it, the entire process dies.

Both readers are affected; neither has a depth limit, and the JSON reader additionally has no input-size cap (the XML reader caps size at 10 MB but not depth).

Affected Versions

github.com/tomwright/dasel/v3 and all v3.x releases through v3.11.0 (current main, commit abc1e1d). This vulnerability is fixed in 3.11.1. Pre-v3 is out of scope.

Description

JSON reader @ parsing/json/json_reader.go

decodeValue (line 54) dispatches to the mutually-recursive decodeObject (line 78) and decodeArray (line 140). Each calls back into both for nested values (decodeArray→decodeArray at line 151, decodeObject at 163; decodeObject→decodeArray at 95, decodeObject at 111). Every [ or { in the input adds one stack frame. There is no depth counter and no len(data) cap anywhere in the reader.

XML reader @parsing/xml/reader.go

parseElement (line 172) recurses at line 211 for every xml.StartElement. The file declares explicit DoS guards — maxXMLSize = 10_000_000, comment count/length — but these bound size and comment volume, not nesting depth. The open tag <a> is 3 bytes, so the 10 MB cap still permits ~3.3 M nesting levels, exhausting the stack long before the size limit fires.

Reachability (both)

Both are on the primary public read path: parsing.Format(<fmt>).NewReader(opts).Read(data), with data fully attacker-controlled and no depth validation before the recursion. The same path backs the dasel CLI (dasel -r json / -r xml). Default reader, no special options. Go stack overflow is a fatal error, so recover() at the call site does not help.

Precedent in this codebase

DoS hardening on the readers is already an accepted concern here, which is why this is a gap rather than a design choice: the XML reader has the maxXMLSize cap, and the YAML reader already implements exactly the fix needed, parsing/yaml/yaml_reader.go:31,90-93 returns ErrYamlExpansionDepthExceeded once expansionDepth > maxExpansionDepth. The JSON and XML readers simply lack the equivalent depth guard.

Proof of Concept

Single runnable program, public API only (poc/main.go, module wired to a local clone via replace):

package main

import (
	"fmt"; "os"; "strings"
	"github.com/tomwright/dasel/v3/parsing"
	_ "github.com/tomwright/dasel/v3/parsing/json"
	_ "github.com/tomwright/dasel/v3/parsing/xml"
)

func main() {
	mode := "json"; if len(os.Args) > 1 { mode = os.Args[1] }
	depth := 6_000_000; if mode == "xml" { depth = 3_200_000 }

	var data []byte
	if mode == "xml" {
		data = []byte(strings.Repeat("<a>", depth))          // ~9.6MB, under the 10MB cap
	} else {
		data = []byte(strings.Repeat("[", depth) + strings.Repeat("]", depth)) // ~12MB
	}

	defer func() { if r := recover(); r != nil { fmt.Println("recovered (NOT fatal):", r) } }()
	r, _ := parsing.Format(mode).NewReader(parsing.DefaultReaderOptions())
	v, err := r.Read(data)
	fmt.Printf("Read returned WITHOUT crash: v=%v err=%v\n", v != nil, err)
}
go run . json    # nested arrays -> fatal error: stack overflow ; ~85 decodeArray frames
go run . xml     # nested <a>    -> fatal error: stack overflow ; ~93 parseElement frames

Observed (Go 1.26, default 1 GB goroutine stack):

  • json depth 6 M (12 MB): runtime: goroutine stack exceeds 1000000000-byte limit → fatal error: stack overflow; backtrace dominated by json.(*jsonReader).decodeArray. depth 2 M completes (~0.83 s), confirming it is depth-driven, not a parse error.
  • xml…
Record
GHSA-cqxr-jxr2-85pq
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weakness
CWE-674
Updated
2026-11-02
OSVUBUNTU-CVE-2026-59168 6.2

Dasel is a command-line tool and library for querying, modifying, and transforming data structures. From 3.0.0 until 3.11.1, parsing/json/json_reader.go decodeValue, decodeObject, and decodeArray, and parsing/xml/reader.go parseElement, recurse once per input nesting level without a depth guard. Deeply nested attacker-controlled JSON or XML supplied through parsing.Format(...).NewReader(...).Read(data), the command-line interface, or the parse selector function can exhaust the Go goroutine stack and raise an unrecoverable fatal error that terminates the entire process. The XML input-size limit does not prevent depth exhaustion, and defer or recover cannot intercept the failure. This issue is fixed in version 3.11.1.

Record
UBUNTU-CVE-2026-59168
CVSS 3.1
6.2 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Updated
2026-11-02
OSVGO-2026-6549 No score

Dasel: Unbounded recursion in JSON and XML readers causes unrecoverable stack-overflow DoS in github.com/tomwright/dasel

Dasel: Unbounded recursion in JSON and XML readers causes unrecoverable stack-overflow DoS in github.com/tomwright/dasel

Record
GO-2026-6549
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
github.com/tomwright/dasel/v3
Go
3.0.0 to 3.11.0
3.11.1
dasel
Debian:14
before 3.11.2-1, plus listed versions
2.8.1-13.11.0-13.8.0-13.8.1-1
3.11.2-1
github.com/tomwright/dasel/v3
Go
3.0.0 up to 3.11.1
3.11.1
github.com/tomwright/dasel
Go
All versions None known
github.com/tomwright/dasel/v2
Go
All versions None known
dasel
Ubuntu:Pro:24.04:LTS
All versions, plus listed versions
2.6.0-12.6.0-1build12.6.0-1ubuntu0.12.6.0-1ubuntu0.22.6.0-1ubuntu0.2+esm12.6.0-1ubuntu0.32.6.0-1ubuntu0.3+esm12.6.0-1ubuntu0.3+esm2
None known
dasel
Ubuntu:26.10
All versions, plus listed versions
2.8.1-1build13.11.0-13.11.2-13.11.2-2
None known
dasel
Ubuntu:26.04:LTS
All versions, plus listed versions
2.8.1-12.8.1-1build1
None known

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-59168 is a medium vulnerability (CVSS 6.2) in Tomwright Dasel, published September 21, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.13%, the 2nd percentile. Fixed in github.com/tomwright/dasel/v3 3.11.1.

References

Show 4 moreShow less
This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open