ANT-2026-NQ9DPCK0 · osgeo/gdal
heap-buffer-overflow high
Severity Claude high · Security research firm high · Maintainer -
Discovered by Claude Mythos Preview
Anthropic's analysis, sealed at approval. Disclosure to the maintainer was performed by Ada Logics.
ANT-2026-NQ9DPCK0: Heap-buffer-overflow in hfaopen.cpp:3533
When GDAL opens an HFA/ERDAS Imagine raster file, HFADataset::Open invokes HFAReadCameraModel, which calls HFAEntry::BuildEntryFromMIFObject. This function performs a 4-byte read at an offset that lands 8 bytes before the start of a 10-byte heap buffer previously allocated by HFAEntry::LoadData. An attacker who can supply a crafted .img file to any GDAL-based application triggers the out-of-bounds read on file open, with no authentication or interaction beyond file parsing.
Target
Project: gdal
Location: hfaopen.cpp:3533
Technical Details
ASAN: READ of size 4 at 0x7bacb43e3e88, located 8 bytes before a 10-byte heap region. BuildEntryFromMIFObject computes a pointer into the entry data buffer (allocated at hfaentry.cpp:424) that underflows the allocation — the 10-byte buffer is too small for the offset arithmetic performed at line 205, and the code lacks a bounds check before the 4-byte dereference.
Crash trace (truncated — full trace in attached crash.log):
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 1626728843
INFO: Loaded 1 modules (1158086 inline 8-bit counters): 1158086 [0x5b73a153fa60, 0x5b73a165a626),
INFO: Loaded 1 PC tables (1158086 PCs): 1158086 [0x5b73a165a628,0x5b73a2806288),
/out/hfa_fuzzer: Running 1 inputs 1 time(s) each.
Running: /tmp/poc
EXIT_CODE:1
=== ASAN Report ===
=================================================================
==27==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7bacb43e3e88 at pc 0x5b739a0c7903 bp 0x7ffe3d3e4410 sp 0x7ffe3d3e4408
READ of size 4 at 0x7bacb43e3e88 thread T0
#0 0x5b739a0c7902 in HFAEntry::BuildEntryFromMIFObject(HFAEntry*, char const*) /src/gdal/frmts/hfa/hfaentry.cpp:205:5
#1 0x5b739a0df7c2 in HFAReadCameraModel /src/gdal/frmts/hfa/hfaopen.cpp:3533:9
#2 0x5b739a0bcb49 in HFADataset::Open(GDALOpenInfo*) /src/gdal/frmts/hfa/hfadataset.cpp:4656:22
#3 0x5b739a107884 in GDALDriver::Open(GDALOpenInfo*, bool) /src/gdal/gcore/gdaldriver.cpp:105:16
#4 0x5b739a1469ed in GDALDataset::Open(GDALOpenInfo*, char const* const*, char const* const*) /src/gdal/gcore/gdaldataset.cpp:4365:39
#5 0x5b739a145145 in GDALOpenEx /src/gdal/gcore/gdaldataset.cpp:4106:12
#6 0x5b7399ddbbab in LLVMFuzzerTestOneInput /src/gdal/./fuzzers/gdal_fuzzer.cpp:222:24
#7 0x5b7399c77d6d in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:619:13
[... 25 more frames — full trace in crash.log]
Reproduction
- Craft an HFA file with a camera model entry whose MIF object data buffer is undersized (~10 bytes) relative to the offsets BuildEntryFromMIFObject expects
- Deliver the file to the target (upload, email, GIS data exchange, web map tile source, etc.)
- Target calls GDALOpenEx on the file; HFAReadCameraModel -> BuildEntryFromMIFObject dereferences 4 bytes at buffer-8
[No reproducer or sanitizer output attached — request from security-cvd@anthropic.com if needed.]
Acknowledgement
This vulnerability was discovered by Claude, Anthropic's AI assistant, and triaged by the Anthropic security team in collaboration with Anthropic Research. Please direct questions to security-cvd@anthropic.com and reference ANT-2026-NQ9DPCK0.
Reference: ANT-2026-NQ9DPCK0
Anthropic CVD Policy: https://www.anthropic.com/coordinated-vulnerability-disclosure
Triage and disclosure were performed by Ada Logics.
- Verdict
- true positive
- Severity
- high
The change that resolved this finding.
diff --git a/autotest/gdrivers/data/hfa/poc_14547.img b/autotest/gdrivers/data/hfa/poc_14547.img
new file mode 100644
index 000000000000..c11d9339d05e
Binary files /dev/null and b/autotest/gdrivers/data/hfa/poc_14547.img differ
diff --git a/autotest/gdrivers/hfa.py b/autotest/gdrivers/hfa.py
index 26af09c1d640..7e9a2cf934c2 100755
--- a/autotest/gdrivers/hfa.py
+++ b/autotest/gdrivers/hfa.py
@@ -1375,3 +1375,8 @@ def test_hfa_rat_new_types(tmp_vsimem):
rat.SetValueAsWKBGeometry(0, 2, wkb)
assert rat.GetValueAsWKBGeometry(0, 2) == wkb
+
+
+def test_hfa_read_poc_14547():
+
+ gdal.Open("data/hfa/poc_14547.img")
diff --git a/frmts/hfa/hfaentry.cpp b/frmts/hfa/hfaentry.cpp
index 990fa71ce0b3..521a2fe80da2 100644
--- a/frmts/hfa/hfaentry.cpp
+++ b/frmts/hfa/hfaentry.cpp
@@ -201,7 +201,15 @@ HFAEntry *HFAEntry::BuildEntryFromMIFObject(HFAEntry *poContainer,
}
GInt32 nMIFObjectSize = 0;
- // We rudely look before the field data to get at the pointer/size info.
+ // We look before the field data to get at the pointer/size info.
+ const GByte *pabyEntryData = poContainer->GetData();
+ CPLAssert(reinterpret_cast<const GByte *>(pszField) - pabyEntryData >= 0);
+ if (reinterpret_cast<const GByte *>(pszField) - pabyEntryData < 8)
+ {
+ CPLError(CE_Failure, CPLE_AppDefined, "Invalid %s entry",
+ osFieldName.c_str());
+ return nullptr;
+ }
memcpy(&nMIFObjectSize, pszField - 8, 4);
HFAStandard(4, &nMIFObjectSize);
if (nMIFObjectSize <= 0)https://github.com/OSGeo/gdal/commit/03ee967da1b22ec61cc7a6b8abb5de3307f213c7
Dates from discovery through public reveal.
- 2026-03-24 Reported to tracker
- 2026-05-11 Sent to maintainer
- 2026-05-13 Maintainer acknowledged
- 2026-06-05 Patch released
- 2026-07-20 Publicly revealed
SHA-3-512 hash:
f57f3a9f0d76212352423279892545fb34dc45d1cecf6cff9244e0f706b157a60b4ad8e55ee07c5ffc4ff7c7670d053b842d9258561dbb9b9a1c9897a1c34405
Committed 2026-05-13 10:55 PT
Revealed 2026-07-20 22:01 PT
Verify (download preimage.json)
Show preimage JSON
{
"ant_id": "ANT-2026-NQ9DPCK0",
"bug_class": "Heap-buffer-overflow",
"claude_severity": "high",
"commit_sha": null,
"created_at": "2026-03-24T18:28:22+00:00",
"description": "When GDAL opens an HFA/ERDAS Imagine raster file, HFADataset::Open invokes HFAReadCameraModel, which calls HFAEntry::BuildEntryFromMIFObject. This function performs a 4-byte read at an offset that lands 8 bytes before the start of a 10-byte heap buffer previously allocated by HFAEntry::LoadData. An attacker who can supply a crafted .img file to any GDAL-based application triggers the out-of-bounds read on file open, with no authentication or interaction beyond file parsing.",
"discovered_at": null,
"location": "hfaopen.cpp:3533",
"poc_sha256": null,
"preimage_version": 1,
"project": "gdal",
"reproduction": [
"1. Craft an HFA file with a camera model entry whose MIF object data buffer is undersized (~10 bytes) relative to the offsets BuildEntryFromMIFObject expects",
"2. Deliver the file to the target (upload, email, GIS data exchange, web map tile source, etc.)",
"3. Target calls GDALOpenEx on the file; HFAReadCameraModel -> BuildEntryFromMIFObject dereferences 4 bytes at buffer-8"
],
"technical_details": "ASAN: READ of size 4 at 0x7bacb43e3e88, located 8 bytes before a 10-byte heap region. BuildEntryFromMIFObject computes a pointer into the entry data buffer (allocated at hfaentry.cpp:424) that underflows the allocation — the 10-byte buffer is too small for the offset arithmetic performed at line 205, and the code lacks a bounds check before the 4-byte dereference.",
"title": "Heap-buffer-overflow in hfaopen.cpp:3533",
"vendor_severity": "high"
}