oven-sh/bun · error · bun_exe_format::pe::Error
UnexpectedOverlayPresent
Error message
UnexpectedOverlayPresent
What it means
After removing the certificate table, bytes still remain beyond the last section's raw-data end (src/exe_format/pe.rs:422-426). Those trailing bytes are an 'overlay' (debug data, appended archives, a second signature) that strip_authenticode did not account for; the injector refuses to proceed because the overlay's meaning is unknown.
Source
Thrown at src/exe_format/pe.rs:37
#[error("InvalidDOSSignature")]
InvalidDOSSignature,
#[error("InvalidPESignature")]
InvalidPESignature,
#[error("UnsupportedPEFormat")]
UnsupportedPEFormat,
#[error("InsufficientHeaderSpace")]
InsufficientHeaderSpace,
#[error("TooManySections")]
TooManySections,
#[error("SectionExists")]
SectionExists,
#[error("InputIsSigned")]
InputIsSigned,
#[error("InvalidSecurityDirectory")]
InvalidSecurityDirectory,
#[error("SecurityDirInsideImage")]
SecurityDirInsideImage,
#[error("UnexpectedOverlayPresent")]
UnexpectedOverlayPresent,
#[error("InsufficientSpace")]
InsufficientSpace,
}
/// Windows PE Binary manipulation for codesigning standalone executables
pub struct PEFile {
pub(crate) data: Vec<u8>,
// Store offsets instead of pointers to avoid invalidation after resize
pub(crate) pe_header_offset: usize,
pub(crate) optional_header_offset: usize,
pub(crate) section_headers_offset: usize,
pub(crate) num_sections: u16,
}
// PE/COFF on-disk header structs are byte-packed (no padding) per spec, and may
// live at arbitrary byte offsets inside a `Vec<u8>` image, so `align_of` must be 1
// for it to be sound to materialize references/pointers to them from the buffer.View on GitHub (pinned to 8c5296ac45)
Solutions
- Use the plain Bun executable as the base — it has no overlay.
- Strip the overlay from the custom base: truncate the file to max(section PointerToRawData+SizeOfRawData) with a small script, or use a PE overlay remover tool, then compile.
- Confirm with `pefile` (Python) or `dumpbin` that Overlay offset/size are zero after cleaning.
- Re-sign the final output (`signtool sign`) after Bun compiles it — signing last avoids the strip path entirely.
Example fix
# before: base has appended overlay -> UnexpectedOverlayPresent
bun build app.ts --compile --base sfx-stub.exe --target=windows-x64
# after: truncate overlay, then compile (and re-sign after)
python -c "import pefile,os; p=pefile.PE('sfx-stub.exe', fast_load=True); end=max(s.PointerToRawData+s.SizeOfRawData for s in p.sections); os.truncate('clean.exe' if False else 'sfx-stub.exe', end)"
bun build app.ts --compile --base sfx-stub.exe --target=windows-x64 Defensive patterns
Strategy: fallback
Validate before calling
python -c "
import pefile
pe = pefile.PE('base.exe')
last = max((s.PointerToRawData + s.SizeOfRawData) for s in pe.sections)
assert len(pe.__data__) <= last or (pe.OPTIONAL_HEADER.DATA_DIRECTORY[4].VirtualAddress == last), 'unexpected overlay present'
" Prevention
- Reject installer/SFX stubs and overlay-carrying exes as compile bases
- Truncate custom bases to the last section end before compiling
- Do post-compile signing so no overlay is ever present at injection time
When it happens
Trigger: `bun build --compile --target=windows` where the base exe has data appended after the last section in addition to (or instead of) the certificate table — e.g. self-extracting installer stubs, bootstrappers that append a ZIP, or PEs with detached debug-directory file content.
Common situations: Using installer/SFX stubs or packer output as the compile base; executables with appended .NET native payloads or embedded ZIPs; CI bases processed by tools that append metadata blobs.
Related errors
AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16).
Data as JSON: /api/errors/82eca850b21063b7.
Report an issue: GitHub.