YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
PoC: hnswlib loadIndex β cur_element_count > max_elements β heap OOB WRITE (CWE-787), master unpatched
Target
hnswlib (~4.5k stars) β header-only HNSW approximate-nearest-neighbor library embedded in vector databases and retrieval stacks (ChromaDB, Milvus ecosystem, countless RAG pipelines). Saved index files are loaded via HierarchicalNSW::loadIndex() / the index-loading constructor.
Vulnerability
loadIndex (master hnswalg.h, verified 2026-07-18) reads both max_elements and cur_element_count from the file, then:
// integrity walk: only checks total file-size consistency β NEVER compares
// cur_element_count against max_elements
data_level0_memory_ = (char *) malloc(max_elements * size_data_per_element_); // :776
input.read(data_level0_memory_, cur_element_count * size_data_per_element_); // :779
A crafted index with max_elements=4, cur_element_count=50 allocates 96 bytes and then reads 1200 bytes into it β a heap-buffer-overflow WRITE of 1104 attacker-controlled file bytes. The "index seems to be corrupted" integrity check added to master does not catch it: it only verifies that the file's total size matches cur_element_count, which the attacker satisfies by simply including the data.
Immediately after the overflow, loadIndex allocates linkLists_ (an array of heap pointers) and proceeds to read per-element link lists β overflowing into this region corrupts pointers that are later dereferenced during search/insertion, i.e. the primitive is sufficient for controlled-pointer corruption β potential control-flow hijack, not just a crash.
Proof of concept (this repo)
gen_malicious_index.pyβ writesmalicious.hnsw(1496 B), crafted to pass the master integrity walkpoc_driver.cppβ loads it with the real library:new hnswlib::HierarchicalNSW<float>(&space, "malicious.hnsw")asan_trace.txtβ captured output
python3 gen_malicious_index.py malicious.hnsw
g++ -fsanitize=address -g -O0 -std=c++17 -I. poc_driver.cpp -o poc_driver -pthread
./poc_driver malicious.hnsw
Result (master headers fetched 2026-07-18):
==3940013==ERROR: AddressSanitizer: heap-buffer-overflow
WRITE of size 1199
#4 hnswlib::HierarchicalNSW<float>::loadIndex(...) hnswalg.h:779
#5 hnswlib::HierarchicalNSW<float>::HierarchicalNSW(...) hnswalg.h:85
0 bytes after a 96-byte region. Fully deterministic.
Impact
Any service loading user-supplied HNSW index files (vector-DB snapshot import, model/index sharing, RAG deployment pipelines) is exposed to attacker-controlled heap corruption at load time. Same "file-supplied count trusted without cross-validation" class as the model-parser vulnerabilities tracked as CVE-2026-27940 / CVE-2026-7482 ("Bleeding Llama", CVSS 9.1) β here in the vector-index layer that AI infrastructure actually ships.
Suggested fix
In loadIndex, after reading the header: if (cur_element_count > max_elements) throw std::runtime_error("cur_element_count exceeds max_elements"); β before both the integrity walk and the allocation.
Note on distinctness
Distinct from GHSA-xwc8-rf6m-xr86 (double free via init_index with large M β different function, different root cause) and from the neighbor-id search-time OOB (searchBaseLayerST, separate issue). This is a load-time allocation/read size mismatch in loadIndex itself, unpatched on master as of 2026-07-18.