GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration

GHSA-6HWM-XVPH-95VM

Vulnerability from github – Published: 2026-09-01 20:27 – Updated: 2026-09-01 20:27
VLAI
Summary
NLTK: Uncontrolled search path when invoking the Graphviz 'dot' binary
Details

Two NLTK sites executed the Graphviz dot program by bare name, so process creation resolved it via the search path — and on Windows via the current working directory — rather than a validated absolute location. An attacker who can place a file named dot where resolution looks (the CWD on Windows, or a writable/relative entry such as . on PATH) has their binary executed in place of Graphviz (arbitrary code execution).

Affected (<= 3.10.2): - nltk.parse.dependencygraph.dot2img — called find_binary("dot") but discarded the returned validated path and then ran the bare name ["dot", ...], so the validation had no effect. - nltk.translate.api.AlignedSent._repr_svg_ — ran the bare name with no validation at all (IPython SVG rendering).

This is the same class already fixed for the senna, weka, boxer, malt, repp and hunpos wrappers. nltk.internals.find_binary refuses a CWD-relative match for a bare tool name and returns only a trusted absolute path; the fix runs that path in both sites.


Attack demonstration

Captured output, not illustrative. A ./dot that writes a PWNED marker, planted in the CWD with . prepended to PATH.

The vulnerable behaviour (old bare-name exec):

Control (OLD behavior) — bare ['dot'] in this dir with '.' on PATH:
  bare ['dot'] executed planted binary = True

The patched functions refuse it:

FIXED code, with ./dot planted and '.' on PATH:
  dependencygraph.dot2img : Exception "Cannot find the dot binary..."  | planted-binary-executed=False  safe
  AlignedSent._repr_svg_  : Exception "Cannot find the dot binary..."  | planted-binary-executed=False  safe

And find_binary itself was attacked directly (the fix trusts nothing else):

Attack 1: ./dot in CWD, no dot on PATH            -> LookupError (refused)  safe
Attack 2: ./dot/dot (dir 'dot' holding 'dot')     -> LookupError (refused)  safe
Attack 3: '.' on PATH + ./dot                     -> LookupError (refused)  safe
Attack 4: attacker-writable ABSOLUTE dir on PATH  -> returned /…/evilbin/dot (absolute)

Attack 4 is out of scope: trusting an absolute directory that is already on PATH is the operating system's own trust model — an attacker who can write to a PATH directory owns the account regardless of NLTK. find_binary defends specifically against the CWD/relative injection that bare-name exec is vulnerable to (attacks 1–3), which is exactly what this fix inherits.

Environment: python 3.13.7. dot is not required to reproduce — the planted binary is the payload.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 3.10.2"
      },
      "package": {
        "ecosystem": "PyPI",
        "name": "nltk"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "3.10.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-78680"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-426",
      "CWE-427"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-09-01T20:27:20Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "Two NLTK sites executed the Graphviz `dot` program by bare name, so process creation resolved it via the search path \u2014 and on Windows via the current working directory \u2014 rather than a validated absolute location. An attacker who can place a file named `dot` where resolution looks (the CWD on Windows, or a writable/relative entry such as `.` on `PATH`) has their binary executed in place of Graphviz (arbitrary code execution).\n\nAffected (\u003c= 3.10.2):\n- `nltk.parse.dependencygraph.dot2img` \u2014 called `find_binary(\"dot\")` but discarded the returned validated path and then ran the bare name `[\"dot\", ...]`, so the validation had no effect.\n- `nltk.translate.api.AlignedSent._repr_svg_` \u2014 ran the bare name with no validation at all (IPython SVG rendering).\n\nThis is the same class already fixed for the senna, weka, boxer, malt, repp and hunpos wrappers. `nltk.internals.find_binary` refuses a CWD-relative match for a bare tool name and returns only a trusted absolute path; the fix runs that path in both sites.\n\n---\n\n## Attack demonstration\nCaptured output, not illustrative. A `./dot` that writes a `PWNED` marker, planted in the CWD with `.` prepended to `PATH`.\n\n**The vulnerable behaviour (old bare-name exec):**\n```\nControl (OLD behavior) \u2014 bare [\u0027dot\u0027] in this dir with \u0027.\u0027 on PATH:\n  bare [\u0027dot\u0027] executed planted binary = True\n```\n\n**The patched functions refuse it:**\n```\nFIXED code, with ./dot planted and \u0027.\u0027 on PATH:\n  dependencygraph.dot2img : Exception \"Cannot find the dot binary...\"  | planted-binary-executed=False  safe\n  AlignedSent._repr_svg_  : Exception \"Cannot find the dot binary...\"  | planted-binary-executed=False  safe\n```\n\n**And `find_binary` itself was attacked directly** (the fix trusts nothing else):\n```\nAttack 1: ./dot in CWD, no dot on PATH            -\u003e LookupError (refused)  safe\nAttack 2: ./dot/dot (dir \u0027dot\u0027 holding \u0027dot\u0027)     -\u003e LookupError (refused)  safe\nAttack 3: \u0027.\u0027 on PATH + ./dot                     -\u003e LookupError (refused)  safe\nAttack 4: attacker-writable ABSOLUTE dir on PATH  -\u003e returned /\u2026/evilbin/dot (absolute)\n```\nAttack 4 is out of scope: trusting an absolute directory that is already on `PATH` is the operating system\u0027s own trust model \u2014 an attacker who can write to a `PATH` directory owns the account regardless of NLTK. `find_binary` defends specifically against the CWD/relative injection that bare-name exec is vulnerable to (attacks 1\u20133), which is exactly what this fix inherits.\n\nEnvironment: python 3.13.7. `dot` is not required to reproduce \u2014 the planted binary is the payload.",
  "id": "GHSA-6hwm-xvph-95vm",
  "modified": "2026-09-01T20:27:20Z",
  "published": "2026-09-01T20:27:20Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/nltk/nltk/security/advisories/GHSA-6hwm-xvph-95vm"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-78680"
    },
    {
      "type": "WEB",
      "url": "https://github.com/nltk/nltk/commit/1a3cd1764ab3deb084fb66d0ffb4873717659538"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/nltk/nltk"
    },
    {
      "type": "WEB",
      "url": "https://github.com/nltk/nltk/releases/tag/v3.10.3"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/nltk-before-arbitrary-code-execution-via-graphviz-dot-binary"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "NLTK: Uncontrolled search path when invoking the Graphviz \u0027dot\u0027 binary"
}



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…

Detection rules are retrieved from Rulezet.

Loading…

Loading…

Loading…