Log date · Wed
Node.js 26.11.0 ships SEA vfsArchive: assets served from an embedded ZIP
On 2026-10-07 (UTC) Node.js 26.11.0 brought the SEA vfsArchive option, which embeds an unchanged ZIP of assets in the executable.
What happened on 2026-10-07
At 14:43 UTC on 2026-10-07, Node.js published 26.11.0 (Current) on GitHub. Its commit list includes "sea: add vfsArchive to serve the assets from a ZIP archive" (#65810), plus tests and docs for import() with a code cache. According to that PR, vfsArchive is a new option in single executable application (SEA) configuration that points to a prebuilt ZIP. It requires "useVfs": true and cannot be combined with "assets". At build time --build-sea embeds the archive unchanged, checking only its PK signature, and at runtime the SEA virtual file system mounts it. sea.getAsset() does not serve individual files from it; reads go through the fs APIs. In the PR's benchmark table, the binary for the 128MB asset tier shrank from 284.7MB to 193.9MB. The PR page does not mention encryption.
What it means for a defender's threat model
The goal of this feature is size and startup performance, not protection. According to the PR, the archive is embedded unchanged with only a sanity check on its PK signature. ZIP is a public, standard format, so the honest assumption is that an embedded archive is readable by anyone who has the binary. Packaging an app as a single executable changes how it is distributed; it does not change the fact that what ships in the client package can be retrieved. A code cache is also a performance mechanism and should not be described as encryption. A common mistake among independent developers is treating SEA as a way to hide source code and placing API keys, licensing algorithms or complete paid-feature logic inside it. The correct boundary is to treat everything in the executable as public and keep real secrets and core rules on the server.
Checks on your own builds
After each build, inventory your own executable: list every file in the ZIP and confirm there are no .env files, private keys, internal configuration, test data or source maps you did not intend to ship. Replace embedded keys with short-lived credentials fetched from your server at runtime, and let the server make core-rule decisions. If you also obfuscate JavaScript, make sure obfuscation runs before files go into the ZIP, then rerun functional tests on the packaged executable, especially code that relies on __dirname-relative paths and sea.getAsset(). On Windows and macOS, sign and notarize after the resources are injected, and verify the resulting signature. Read the release notes and the relevant PRs before upgrading Node.js.
Your checklist
- List every file in the SEA's embedded ZIP and confirm no keys or stray source maps
- Move keys and core rules server-side and use short-lived credentials in the client
- Sign and notarize after injecting resources, then rerun functional tests
Primary sources
- GitHub: nodejs/node release v26.11.0 · Source date 2026-10-07 · Checked 2026-10-12
- GitHub: nodejs/node PR #65810 sea: add vfsArchive to serve the assets from a ZIP archive · Source date 2026-09-19 · Checked 2026-10-12