SurrealML process-abort PoC (load_model / embedded NUL byte)
This repository contains a proof-of-concept .surml file for a responsibly-disclosed
vulnerability in surrealdb/surrealml (tested at commit
152ac2d508f1bae9ee62c46b7d211d80e40a6425), reported via huntr's Model File Vulnerability
program.
What this file is
malicious_nul_name.surml is a syntactically valid (but minimal) SurrealML container: a 4-byte
big-endian header-length prefix, a header whose name field is the literal string
evil\x00name (a raw embedded NUL byte, all other header fields left empty/fresh), and 16 bytes
of placeholder model data. It follows exactly the header format documented and unit-tested in the
project's own modules/core/src/storage/header/mod.rs.
What happens when you load it
import ctypes
lib = ctypes.CDLL("libc_wrapper.so") # or .dll / .dylib
lib.load_model(b"malicious_nul_name.surml")
load_model() reads and parses the file successfully (the header format tolerates an embedded
NUL byte fine), then panics while converting the name field to a C string
(CString::new(name).unwrap() at modules/c-wrapper/src/api/storage/load_model.rs:124), since a
CString cannot represent an interior NUL byte. Because load_model is a plain extern "C" fn
rather than extern "C-unwind", this panic aborts the entire host process โ it cannot be caught
as an exception by a Python/Node/etc. caller, and no error result is ever returned.
A single ~65-byte file is enough to kill any process that calls load_model() on it โ no
inference, no other API call required.
See the reporter's full write-up submitted via huntr for the complete technical analysis, the
related prior-art discussion (GitHub issue
surrealdb/surrealml#20, a similar
"malformed file crashes the whole server" report from 2024 that was reopened after an incomplete
fix), and a second, unrelated finding (a use-after-free in the Python client's to_bytes()).
Scope note
This PoC is provided solely for the purpose of responsible vulnerability disclosure and
reproduction by the surrealml maintainers / huntr triage team. It is not intended for any other
use.