Public preview · Registration and live billing are not open.
Anti-AIClonePILOT

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

All sources and reproduction status ↗