Skip to content

CVE-2026-33721: Verified Reproduction

CVE-2026-33721: MapServer: heap-buffer-overflow in SLD Categorize parser msSLDParseRasterSymbolizer

CVE-2026-33721 is verified against mapserver · c. Affected versions: 4.2.0 - 8.6.0. Fixed in 8.6.1. This medium reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00183.

REPRO-2026-00183 mapserver · c May 28, 2026 CVE entry .txt
Severity
MEDIUM
CVSS
5.3
Reproduced in
14m 33s
Tool calls
177
Spend
$1.33
01 · Overview

What Is CVE-2026-33721?

CVE-2026-33721 is a high-severity heap-buffer-overflow (out-of-bounds write, CWE-787) in MapServer's OGC SLD parser. Parsing a crafted <se:Categorize> element can overflow a fixed-size buffer. Pruva reproduced it (reproduction REPRO-2026-00183).

02 · Severity & CVSS

CVE-2026-33721 Severity & CVSS Score

CVE-2026-33721 is rated medium severity, with a CVSS base score of 5.3 out of 10.

MEDIUM threat level
5.3 / 10 CVSS base
Weakness CWE-787 (Out-of-bounds Write) — Out-of-bounds Write

Medium — meaningful risk under specific conditions. Schedule a fix in the normal cycle.

03 · Affected Versions

Affected mapserver Versions

mapserver · c versions 4.2.0 - 8.6.0 are affected.

How to Reproduce CVE-2026-33721

$ pruva-verify REPRO-2026-00183
or curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00183/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2026-33721

Reproduced by Pruva's autonomous agents — 177 tool calls over 15 min. Full root-cause analysis and the complete transcript are below.

How the agent worked 608 events · 177 tool calls · 15 min
15 minDuration
177Tool calls
141Reasoning steps
608Events
3Dead-ends
Agent activity over 15 min
Support
15
Repro
308
Variant
281
0:0014:33

Root Cause and Exploit Chain for CVE-2026-33721

Versions: 4.2.0 — 8.6.0 (last vulnerable tag: rel-8-6-0)Fixed: 8.6.1 (rel-8-6-1)

MapServer versions 4.2.0 through 8.6.0 contain a heap-buffer-overflow vulnerability in the OGC SLD (Styled Layer Descriptor) XML parser. The function msSLDParseRasterSymbolizer in src/mapogcsld.cpp allocates a fixed-size buffer for 100 threshold pointers when parsing a <se:Categorize> element. The reallocation guard incorrectly checks nValues == nMaxThreshold instead of nThresholds == nMaxThreshold. Because nValues and nThresholds increment at different rates, the buffer is never expanded when more than 100 <se:Threshold> children are present, causing subsequent pointer writes to spill past the 800-byte (100 × 8) array boundary. The bug is reachable unauthenticated via the SLD_BODY parameter in a WMS GetMap request.

  • Package: OSGeo MapServer (mapserv CGI binary)
  • Affected versions: 4.2.0 — 8.6.0 (last vulnerable tag: rel-8-6-0)
  • Fixed version: 8.6.1 (rel-8-6-1)
  • Risk level: High (CVSS 3.1: 7.5)
  • Consequences: At minimum, an attacker can crash the MapServer worker process (denial of service). Depending on heap layout and input control, the overflowed pointers may be further exploitable.

Root Cause

In src/mapogcsld.cpp, around line 2880, msSLDParseRasterSymbolizer initializes:

int nMaxThreshold = 100;
char **papszThresholds = (char **)msSmallMalloc(sizeof(char *) * nMaxThreshold);

As the parser iterates over <se:Categorize> children, every <se:Threshold> increments nThresholds and stores a pointer into papszThresholds. The growth guard is meant to reallocate the array when it fills:

// VULNERABLE (rel-8-6-0):
if (nValues == nMaxThreshold) {
    nMaxThreshold += 100;
    papszThresholds = (char **)msSmallRealloc(
        papszThresholds, sizeof(char *) * nMaxThreshold);
}

However, nValues tracks a different counter (the number of <se:Value> elements), while nThresholds tracks the actual number of threshold entries. When an SLD contains more than 100 thresholds, nThresholds exceeds 100 but nValues may still be much lower (e.g., 1), so reallocation never occurs. The next papszThresholds[nThresholds] = … write lands beyond the 100-slot buffer, producing a heap-buffer-overflow.

Fix commit: ddd246b90acc6c7f920dfd056f33613cebe9154d
Merge commit: 7dbe91b
The patch changes exactly one line:

-          if (nValues == nMaxThreshold) {
+          if (nThresholds == nMaxThreshold) {

This ensures the array is resized based on the same counter that tracks live entries.

Reproduction Steps

The complete reproduction is automated in repro/reproduction_steps.sh. It performs the following:

  1. Clones MapServer at rel-8-6-0 (vulnerable) and rel-8-6-1 (fixed).
  2. Builds both mapserv binaries with AddressSanitizer (-fsanitize=address).
  3. Generates a minimal test.map, a tiny GeoTIFF (tiny.tif), and a malicious SLD payload (payload.sld) containing 200 <se:Threshold> elements.
  4. Invokes the vulnerable binary through the real CGI path (QUERY_STRING + REQUEST_METHOD=GET) with the SLD payload via SLD_BODY.
  5. Captures the ASAN crash log (logs/vulnerable_asan.txt).
  6. Runs the same request against the fixed binary and verifies it returns a valid PNG image with no ASAN error (logs/fixed_response.txt).

Evidence

  • Vulnerable ASAN log: logs/vulnerable_asan.txt
    • Key excerpt:
      ==10268==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x518000008fa0
      WRITE of size 8 at 0x518000008fa0 thread T0
          #0 0x7fd97611c7d4 in msSLDParseRasterSymbolizer /.../src/mapogcsld.cpp:2895
      0x518000008fa0 is located 0 bytes after 800-byte region [0x518000008c80,0x518000008fa0)
      
  • Fixed response: logs/fixed_response.txt
    • Starts with Content-Type: image/png and contains a valid PNG stream, confirming the fixed binary processes the same payload without crashing.
  • Runtime manifest: repro/runtime_manifest.json — records binary paths, tags, crash signature, and payload details.
  • Validation verdict: repro/validation_verdict.json — marks status confirmed.

Recommendations / Next Steps

  1. Immediate fix: Upgrade to MapServer 8.6.1 or later. The patch is a single-line bound-check correction and carries no functional regression.
  2. Defensive measure: If upgrading is not immediately possible, restrict the SLD_BODY / SLD query parameters at the reverse-proxy or WAF level, or disable WMS SLD support in the MapServer configuration.
  3. Testing: Add a regression test that submits an SLD with >100 thresholds and asserts the process does not crash.
  4. Code-review note: When arrays are grown dynamically, always use the same counter for both indexing and resize checks.

Additional Notes

  • Idempotency: repro/reproduction_steps.sh was run twice consecutively with identical results (confirmed heap-buffer-overflow on vulnerable, valid PNG on fixed).
  • Edge cases: The crash is triggered with any SLD containing >100 <se:Threshold> children inside a <se:Categorize> block. The exact threshold count is 100; 101 is sufficient to overflow. The reproduction uses 200 to provide a clear safety margin.
  • Limitations: The reproduction requires a functional GDAL/PROJ/libxml2 environment. The script installs missing Debian/Ubuntu packages automatically if they are absent.

CVE-2026-33721 Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.

Full session Replay every step — scrub the timeline or play it back.

Event 1/40
0:000:43
0:00
session startedaccounts/fireworks/models/kimi-k2p6 · cve-2026-33721 · cve-2026
0:22
0:22
0:22
error

Unknown error

0:22
web search
0:22
error

Unknown error

0:36
0:36
extract_facts
no facts extracted
0:37
0:37
0:37
supportrepro
0:39
0:40
0:40
0:40
0:40
0:40
0:40
0:41
0:41
0:42
0:42
0:43
08 · How to Fix

How to Fix CVE-2026-33721

Upgrade mapserver · c to 8.6.1 or later.

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2026-33721 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2026-33721

How is CVE-2026-33721 reached?

MapServer is a CGI binary that parses OGC SLD XML to style layers served over WMS/WFS. A request supplying an SLD with a <se:Categorize> element containing more than 100 thresholds drives the off-by-one reallocation guard and overflows the heap buffer.

Which MapServer versions are affected by CVE-2026-33721, and where is it fixed?

MapServer versions 4.2.0 through 8.6.0 are affected. It is fixed in 8.6.1 — upgrade to 8.6.1 or later.

How can I reproduce CVE-2026-33721?

Download the verified script from this page and run it in an isolated environment against MapServer 4.2.0-8.6.0. It submits an SLD with an oversized <se:Categorize> threshold list and shows the heap-buffer-overflow that 8.6.1 fixes.
11 · References

References for CVE-2026-33721

Authoritative sources for CVE-2026-33721 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.