GHSA-65GG-G7RW-6CPC

Vulnerability from github – Published: 2026-09-22 19:52 – Updated: 2026-09-22 19:52
VLAI
Summary
Dasel: Selector lexer panics on trailing whitespace in `parseCurRune`
Details

Same panic class as GHSA-m5j3-4634-c2vq and GHSA-m6xr-fvfg-5g64, 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.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/tomwright/dasel/v3"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "3.0.0"
            },
            {
              "fixed": "3.11.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-62866"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-129"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-09-22T19:52:16Z",
    "nvd_published_at": "2026-09-21T17:17:38Z",
    "severity": "MODERATE"
  },
  "details": "Same panic class as GHSA-m5j3-4634-c2vq and GHSA-m6xr-fvfg-5g64, sister site on the same function. Trigger is any selector ending in whitespace: `dasel query \u0027a \u0027` panics at `selector/lexer/tokenize.go:60`.\n\nThe 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.\n\n## Vulnerable code\n\n`selector/lexer/tokenize.go:53-74` (v3.11.0):\n\n```go\nfunc (p *Tokenizer) parseCurRune() (Token, error) {\n\t// Skip over whitespace\n\tfor p.i \u003c p.srcLen \u0026\u0026 unicode.IsSpace(rune(p.src[p.i])) {\n\t\tp.i++\n\t}\n\n\t// Skip over comments\n\tif p.src[p.i] == \u0027/\u0027 \u0026\u0026 p.i+1 \u003c p.srcLen \u0026\u0026 p.src[p.i+1] == \u0027/\u0027 {\n\t\t// ...\n```\n\nLines 69-71 right below already do the bounds check after the comment-skip path. The whitespace-only path slipped past it.\n\n## Reproduce\n\n```\n$ echo \u0027{\"a\":1}\u0027 | dasel query -i json \u0027a \u0027\npanic: runtime error: index out of range [2] with length 2\n\ngoroutine 1 [running]:\ngithub.com/tomwright/dasel/v3/selector/lexer.(*Tokenizer).parseCurRune(...)\n\tselector/lexer/tokenize.go:60\ngithub.com/tomwright/dasel/v3/selector/lexer.(*Tokenizer).Next(...)\ngithub.com/tomwright/dasel/v3/selector/lexer.(*Tokenizer).Tokenize(...)\ngithub.com/tomwright/dasel/v3/selector.Parse(...)\ngithub.com/tomwright/dasel/v3/execution.ExecuteSelector(...)\n```\n\nOther inputs that hit it: `\u0027   \u0027`, `$\u0027a\\t\u0027`, `$\u0027a\\n\u0027`, `\u0027a ?? \u0027`, `\u0027a + \u0027`. Any token (or no token) followed by whitespace.\n\nReachable directly from the library too - `dasel.Query(ctx, input, \"a \")` panics the same way. Project-style test reproducer that fails on current `main`:\n\n```go\n// drop into selector/lexer/ as tokenize_trailing_ws_test.go\npackage lexer_test\n\nimport (\n\t\"testing\"\n\t\"github.com/tomwright/dasel/v3/selector/lexer\"\n)\n\nfunc TestTokenize_TrailingWhitespacePanic(t *testing.T) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tt.Fatalf(\"Tokenize panicked: %v\", r)\n\t\t}\n\t}()\n\t_, _ = lexer.NewTokenizer(\"a \").Tokenize()\n}\n```\n\n## Impact\n\nProcess crash, no auth, no preconditions. Same severity tier as the two May 13 advisories on this file.\n\n## Affected versions\n\nAll v3.x. The whitespace-skip loop was added in `78fcca9` (Dasel V3, ~9 months ago); line 60\u0027s indexing landed in `9bfe966` (~6 months ago). Reproduced on `github.com/tomwright/dasel/v3@v3.11.0`.\n\n## Suggested fix\n\nOne line, between the whitespace-skip loop and the comment-skip access. Same shape as lines 69-71:\n\n```go\nfunc (p *Tokenizer) parseCurRune() (Token, error) {\n\tfor p.i \u003c p.srcLen \u0026\u0026 unicode.IsSpace(rune(p.src[p.i])) {\n\t\tp.i++\n\t}\n\n\tif p.i \u003e= p.srcLen {\n\t\treturn NewToken(EOF, \"\", p.i, 0), nil\n\t}\n\n\tif p.src[p.i] == \u0027/\u0027 \u0026\u0026 p.i+1 \u003c p.srcLen \u0026\u0026 p.src[p.i+1] == \u0027/\u0027 {\n```\n\n## Prevalence\n\nThe other two cases in this class shipped fixes two weeks ago; this one wasn\u0027t 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.",
  "id": "GHSA-65gg-g7rw-6cpc",
  "modified": "2026-09-22T19:52:16Z",
  "published": "2026-09-22T19:52:16Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/TomWright/dasel/security/advisories/GHSA-65gg-g7rw-6cpc"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-62866"
    },
    {
      "type": "WEB",
      "url": "https://github.com/TomWright/dasel/commit/eee03aec28d4a33d6138098d065b7b37b85e3c55"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/TomWright/dasel"
    },
    {
      "type": "WEB",
      "url": "https://github.com/TomWright/dasel/releases/tag/v3.11.2"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Dasel: Selector lexer panics on trailing whitespace in `parseCurRune`"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…