{
  "ticket_id": "CVE-2026-33721",
  "code_root": "external/mapserver",
  "source": {
    "type": "cve",
    "cve_id": "CVE-2026-33721",
    "ghsa_id": "GHSA-cv4m-mr84-fgjp",
    "repo": "https://github.com/MapServer/MapServer"
  },
  "facts": {
    "issue_summary": "MapServer's SLD parser msSLDParseRasterSymbolizer (src/mapogcsld.cpp around line 2894) allocates a fixed-size buffer for 100 threshold pointers when handling a Categorize element. The reallocation guard tests the WRONG variable: nValues == nMaxThreshold instead of nThresholds == nMaxThreshold. Because nValues increments at a different rate than nThresholds, reallocation never fires when the number of <Threshold> children exceeds 100; the next writes go past the 100-pointer array. Reachable unauthenticated via any WMS/WFS endpoint that parses SLD (GetMap?SLD_BODY=...).",
    "vulnerability_type": "Heap-based out-of-bounds write in OGC SLD parsing",
    "suspected_cwe": ["CWE-787", "CWE-122"],
    "affected_versions": "4.2.0 through 8.6.0",
    "fixed_versions": ["8.6.1"],
    "reproduce_version": "rel-8-6-0",
    "verify_fixed_version": "rel-8-6-1",
    "repo_url": "https://github.com/MapServer/MapServer.git",
    "checkout_ref": "rel-8-6-0",
    "code_root": "external/mapserver",
    "attacker_access": "Remote, unauthenticated WMS/WFS client able to send an SLD_BODY URL parameter.",
    "primary_entry_point": "msSLDParseRasterSymbolizer in src/mapogcsld.cpp, the Categorize branch, around line 2894. Reached from a WMS GetMap request with a SLD_BODY payload that styles a raster layer with se:Categorize > 100 se:Threshold children.",
    "build_hint": "cmake -B build -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_FLAGS='-fsanitize=address -g -O1 -fno-omit-frame-pointer' -DCMAKE_CXX_FLAGS='-fsanitize=address -g -O1 -fno-omit-frame-pointer' -DWITH_PYTHON=OFF -DWITH_PHP=OFF -DWITH_PERL=OFF -DWITH_FCGI=OFF -DWITH_PROTOBUFC=OFF -DWITH_HARFBUZZ=OFF -DWITH_FRIBIDI=OFF -DWITH_CAIRO=OFF . && cmake --build build -j",
    "trigger_hint": "Build the mapserv CLI binary. Craft a minimal MAP file pointing at a small in-tree raster (e.g., the tests/ directory has a GeoTIFF). Build an SLD with a RasterSymbolizer + Categorize containing > 100 (e.g., 200) <Threshold> children. Invoke mapserv as 'QUERY_STRING=\"MAP=test.map&SERVICE=WMS&REQUEST=GetMap&LAYERS=raster&SLD_BODY=...\" mapserv'. On the vulnerable build: AddressSanitizer reports a heap-buffer-overflow WRITE inside msSLDParseRasterSymbolizer. On the fixed build: mapserv returns a clean OGC response or an OGC error, no ASAN.",
    "end_to_end_requirement": "Show the attacker-controlled SLD_BODY parameter delivered via the actual mapserv CGI entry point (QUERY_STRING) triggering the overflow on rel-8-6-0 and being safely handled on rel-8-6-1. ASAN report alone is acceptable as the crash signal (this IS a memory-corruption bug — there is no separate 'higher-impact path' to demonstrate beyond worker-process crash / DoS), but the trigger MUST come from a real HTTP-style SLD_BODY input fed to the mapserv binary, NOT a unit-test fuzz harness or direct C call. The verdict must record: (a) the SLD_BODY payload used (or path to the file containing it), (b) the ASAN report from the vulnerable build, (c) the clean response from the fixed build.",
    "tested_under": "mapserv CLI binary built from MapServer rel-8-6-0 vs rel-8-6-1 with -fsanitize=address. SLD_BODY delivered via QUERY_STRING environment variable to invoke the CGI path."
  }
}
