SEA: BlobDeserializer SIGSEGVs when fuse byte is set but no NODE_SEA_BLOB is present
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 76/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Domain
- operating-systems
Research direction
Start in src/node_sea_bin.cc at node::sea::FindSingleExecutableBlob() and trace the postject_find_resource("NODE_SEA_BLOB", ...) result before BlobDeserializer runs. Reproduce with the supplied fuse-flipping command, then verify that a missing blob produces a clear startup error and nonzero exit instead of a SIGSEGV.
Written by the indexing model from the issue text.
Description
Version
v26.1.0 (also reproduces on v25.6.0)
Platform
Linux arm64 (reproduced on Apple Silicon via Docker Desktop, but the SEGV is platform-independent)
Subsystem
sea
What steps will reproduce the bug?
Binaries where the postject fuse byte is set to 1 but NODE_SEA_BLOB cannot be located at runtime currently die with a NULL-deref SIGSEGV inside BlobDeserializer::ReadArithmetic, with no error message indicating the cause.
Take any Node binary, flip the fuse byte from 0 to 1 without injecting an actual SEA blob:
python3 -c "
sent = b'NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2'
with open('hello','rb') as f: buf = bytearray(f.read())
i = buf.find(sent)
buf[i + len(sent) + 1] = ord('1')
with open('hello','wb') as f: f.write(bytes(buf))
"
chmod +x hello
./hello --version # → Segmentation fault, exit 139
This state arises naturally when postject is run against a host binary with no PT_NOTE program header — postject silently fails to inject the note but still flips the fuse byte. See https://github.com/nodejs/postject/issues/107 and https://github.com/nodejs/unofficial-builds/issues/200.
How often does it reproduce? Is there a required condition?
100% reproducible. Required condition: fuse byte set to 1 AND no NODE_SEA_BLOB discoverable via postject_find_resource().
What is the expected behavior? Why is that the expected behavior?
A clear error indicating that the SEA fuse is set but no blob is present, rather than a bare SIGSEGV at startup. The current behavior makes it look like a crash in OpenSSL or libc (because the SIGILLs from OpenSSL's ARM crypto-extension probes show up first under gdb), when the actual cause is much earlier and recoverable.
What do you see instead?
Program received signal SIGSEGV, Segmentation fault.
#0 memcpy ()
#1 node::BlobDeserializer<...>::ReadArithmetic<unsigned int>()
#2 node::sea::FindSingleExecutableResource()
#3 node::sea::FixupArgsForSEA(int, char**)
#4 node::Start(int, char**)
postject_find_resource("NODE_SEA_BLOB", &size, ...) returns NULL, then BlobDeserializer::ReadArithmetic calls memcpy(dst, NULL, sizeof(uint32_t)) → SIGSEGV.
Additional information
Suggested fix in node::sea::FindSingleExecutableBlob() (src/node_sea_bin.cc) — guard the deserialization on the resource lookup:
const char* blob = static_cast<const char*>(
postject_find_resource("NODE_SEA_BLOB", &size, ...));
if (blob == nullptr) {
fprintf(stderr,
"node: SEA fuse is set but no NODE_SEA_BLOB resource was found "
"in this binary. The host binary may be missing a PT_NOTE program "
"header (run `readelf -lW <binary> | grep NOTE` to check).\n");
exit(static_cast<int>(node::ExitCode::kGenericUserError));
}
Either that or CHECK_NOT_NULL(blob) — anything that surfaces a cause rather than a bare SEGV.
Related:
- https://github.com/nodejs/unofficial-builds/issues/200 — upstream cause (arm64-musl tarball with no PT_NOTE)
- https://github.com/nodejs/unofficial-builds/pull/233 — fix for that root cause
- https://github.com/nodejs/postject/issues/107 — companion postject issue (silent injection failure)
- Dominant language
- JavaScript
- Stars
- 122k
- Forks
- 37.4k
- Avg merge
- 4d 4h
- Merged PRs (30d)
- 276
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from nodejs/node
-
doc
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
-
build
Difficulty 1/5 Under an hour Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
-
feature request
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Similar issues
-
ai-observability bug team/ai-observability
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
AllTheMods/ATM-10-L#19 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
SignalK/n2k-signalk#345 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
Difficulty 1/5 1-3 hours Newbie friendliness 88/100
JuliaPluto/PlutoPlotly.jl#72 ·