Skip to content

Selector lexer panics on trailing whitespace in `parseCurRune`

Moderate
TomWright published GHSA-65gg-g7rw-6cpc Jun 27, 2026

Package

gomod https://github.com/TomWright/dasel (Go)

Affected versions

All v3.x

Patched versions

3.11.2

Description

Same panic class as GHSA-m5j3 and GHSA-m6xr, sister site on the same function. Trigger is any selector ending in whitespace: dasel query 'a ' panics at selector/lexer/tokenize.go:60.

The whitespace-skip loop right above (lines 55-57) advances p.i to p.srcLen when the input is all-whitespace or whitespace-trailing. The very next line reads p.src[p.i] without a bounds check.

Vulnerable code

selector/lexer/tokenize.go:53-74 (v3.11.0):

func (p *Tokenizer) parseCurRune() (Token, error) {
	// Skip over whitespace
	for p.i < p.srcLen && unicode.IsSpace(rune(p.src[p.i])) {
		p.i++
	}

	// Skip over comments
	if p.src[p.i] == '/' && p.i+1 < p.srcLen && p.src[p.i+1] == '/' {
		// ...

Lines 69-71 right below already do the bounds check after the comment-skip path. The whitespace-only path slipped past it.

Reproduce

$ echo '{"a":1}' | dasel query -i json 'a '
panic: runtime error: index out of range [2] with length 2

goroutine 1 [running]:
github.com/tomwright/dasel/v3/selector/lexer.(*Tokenizer).parseCurRune(...)
	selector/lexer/tokenize.go:60
github.com/tomwright/dasel/v3/selector/lexer.(*Tokenizer).Next(...)
github.com/tomwright/dasel/v3/selector/lexer.(*Tokenizer).Tokenize(...)
github.com/tomwright/dasel/v3/selector.Parse(...)
github.com/tomwright/dasel/v3/execution.ExecuteSelector(...)

Other inputs that hit it: ' ', $'a\t', $'a\n', 'a ?? ', 'a + '. Any token (or no token) followed by whitespace.

Reachable directly from the library too - dasel.Query(ctx, input, "a ") panics the same way. Project-style test reproducer that fails on current main:

// drop into selector/lexer/ as tokenize_trailing_ws_test.go
package lexer_test

import (
	"testing"
	"github.com/tomwright/dasel/v3/selector/lexer"
)

func TestTokenize_TrailingWhitespacePanic(t *testing.T) {
	defer func() {
		if r := recover(); r != nil {
			t.Fatalf("Tokenize panicked: %v", r)
		}
	}()
	_, _ = lexer.NewTokenizer("a ").Tokenize()
}

Impact

Process crash, no auth, no preconditions. Same severity tier as the two May 13 advisories on this file.

Affected versions

All v3.x. The whitespace-skip loop was added in 78fcca9 (Dasel V3, ~9 months ago); line 60's indexing landed in 9bfe966 (~6 months ago). Reproduced on github.com/tomwright/dasel/v3@v3.11.0.

Suggested fix

One line, between the whitespace-skip loop and the comment-skip access. Same shape as lines 69-71:

func (p *Tokenizer) parseCurRune() (Token, error) {
	for p.i < p.srcLen && unicode.IsSpace(rune(p.src[p.i])) {
		p.i++
	}

	if p.i >= p.srcLen {
		return NewToken(EOF, "", p.i, 0), nil
	}

	if p.src[p.i] == '/' && p.i+1 < p.srcLen && p.src[p.i+1] == '/' {

Prevalence

The other two cases in this class shipped fixes two weeks ago; this one wasn't covered in those patches. I checked the rest of parseCurRune for other unguarded direct-access points after a pos++ - nothing else stood out. A testing.F harness on lexer.NewTokenizer(s).Tokenize() catches all three with trivially short inputs and would close the class.

Severity

Moderate

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Local
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
High

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

CVE ID

CVE-2026-62866

Weaknesses

Improper Validation of Array Index

The product uses untrusted input when calculating or using an array index, but the product does not validate or incorrectly validates the index to ensure the index references a valid position within the array. Learn more on MITRE.

Credits