Skip to content

fix(sea): silence benign LIEF warnings during postject injection#265

Merged
robertsLando merged 3 commits intomainfrom
fix/sea-postject-warnings
Apr 23, 2026
Merged

fix(sea): silence benign LIEF warnings during postject injection#265
robertsLando merged 3 commits intomainfrom
fix/sea-postject-warnings

Conversation

@robertsLando
Copy link
Copy Markdown
Member

Summary

Every SEA build currently prints a handful of noisy warnings on stderr that look alarming but are harmless:

warning: The signature seems corrupted!
warning: Can't find string offset for section name '.note.100'
warning: Can't find string offset for section name '.note.100'
warning: Can't find string offset for section name '.note.100'
...

These come from LIEF inside postject when it re-parses the Node binary after expanding the ELF section table to make room for NODE_SEA_BLOB. The pre-existing .note.* section-name offsets and .note.gnu.build-id signature layout no longer resolve cleanly through .shstrtab, so LIEF falls back to synthetic names ('.note.100') and warns. The injection itself still succeeds, and on macOS we re-sign the binary with codesign afterwards, so the "signature seems corrupted" line is purely cosmetic too.

Users reasonably read these as build failures and file issues, so this PR filters them out.

Approach

Wrap the postject.inject() call (lib/sea.ts) in a tiny helper, withFilteredPostjectStderr, that:

  • Replaces process.stderr.write with a version that drops only lines matching a strict allow-list regex:
    • warning: The signature seems corrupted!
    • warning: Can't find string offset for section name '.note…
  • Passes everything else through unchanged — real errors from postject or anywhere else are not hidden.
  • Restores the original process.stderr.write in a finally block so the override never leaks past the inject call.
  • Honors any completion callback passed to write (e.g. by console.warn) via process.nextTick.

Filtering at the process.stderr.write layer works because postject is an Emscripten/WASM module whose Module.printErr defaults to console.warn.bind(console), which ultimately calls process.stderr.write. No changes to postject are required.

Why not the alternatives

  • Redirecting fd 2 at the OS level would also catch C-level writes but is invasive and can swallow legitimate stderr from concurrent work (e.g. child processes or unrelated logging).
  • Patching postject would require a fork; these messages come from LIEF, not from postject's own code.
  • Running postject in a child process adds a fork/exec on every target — the CI issues that led us to the JS API in the first place (see the existing comment above the call) would come back.

Test plan

  • yarn build passes
  • yarn lint clean (no Prettier / ESLint issues)
  • Direct postject call reproduces the LIEF warnings (A/B control)
  • node lib-es5/bin.js --sea --target node22-linux-x64 … now emits zero .note.* / "signature seems corrupted" lines
  • Reviewer: sanity-check on macOS (Mach-O path) — .note.* warnings don't appear there, but the "signature seems corrupted" line can; re-signing then happens in signMacOSIfNeeded
  • Reviewer: sanity-check on Windows (PE path) — LIEF is quieter here, but confirm no regressions

LIEF (inside postject) prints "signature seems corrupted" and
"Can't find string offset for section name '.note.100'" to stderr
after postject expands the ELF section table to make room for
NODE_SEA_BLOB. The messages are cosmetic — the injection succeeds
and macOS binaries are re-signed afterwards — but users reasonably
assume something is wrong.

Wrap the postject.inject() call in a tiny stderr filter that drops
only those specific lines. Everything else passes through
unchanged, and the original process.stderr.write is restored in a
finally block.
@robertsLando robertsLando requested a review from Copilot April 23, 2026 15:08
Replace `unknown` + `...rest: unknown[]` (which forced two `as` casts
and a runtime `rest.find` to locate the callback) with the actual
write() overload parameters: `chunk: string | Uint8Array`,
`encodingOrCb?: BufferEncoding | WriteCallback`, `cb?: WriteCallback`.

Disambiguate the pass-through call so the right write() overload is
dispatched, and handle plain Uint8Array chunks explicitly.

Whitelist `BufferEncoding` as a global in the TS ESLint block,
mirroring how `NodeJS` is already handled — both are type-only
identifiers that `no-undef` can't resolve on its own.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to reduce alarming-but-harmless stderr noise during SEA builds by filtering specific known-benign LIEF warnings emitted via postject during NODE_SEA_BLOB injection.

Changes:

  • Add a withFilteredPostjectStderr helper that temporarily wraps process.stderr.write to drop allow-listed benign warning lines during postject injection.
  • Wrap the postjectInject(...) call in bake() with that stderr filter helper.
  • Update ESLint TS globals to include BufferEncoding to satisfy linting for the new type usage.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
lib/sea.ts Introduces stderr-filter wrapper and applies it around postject SEA blob injection.
eslint.config.js Adds BufferEncoding as a readonly global for TS linting.

Comment thread lib/sea.ts
Comment thread lib/sea.ts
Keep the unbound write function for restoration so process.stderr.write
regains its exact prior identity after the call. Use a separate bound
copy internally for calling from the filter.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@robertsLando robertsLando merged commit 974df53 into main Apr 23, 2026
8 checks passed
@robertsLando robertsLando deleted the fix/sea-postject-warnings branch April 23, 2026 16:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants