[Homebrew/Publisher] Publish bottles containing Wasm side modules safely - #1119
Closed
brandonpayton wants to merge 1 commit into
Closed
Conversation
Homebrew bottles may contain both process executables and dylink.0 side modules. Validate their distinct loading contracts without treating a filename or mode as an exemption from executable ABI checks. Resolve bin/sbin entrypoints before inspection, reject side modules exposed as process entrypoints, validate side-module memory/import/fork structure, and keep executable ABI-version validation unchanged. Cover valid and malformed roles, unsupported imports, and uninstrumented side-module fork imports.
brandonpayton
force-pushed
the
homebrew/wasm-side-module-publisher-qk044
branch
from
July 27, 2026 22:05
b03688e to
7253144
Compare
brandonpayton
changed the base branch from
homebrew/mostly-lazy-shell-cutover-qk044
to
packaging/schema3-stacked-a0-qk044
July 27, 2026 22:05
Member
Author
|
The current staging failure is a stacked-branch artifact-state mismatch, not a classifier failure. This PR intentionally changes only the bottle classifier relative to its #1112 base, so change-scope correctly sets package staging to false. However, the current main durable index predates the six image cache keys inherited through #1116, so aggregate materialization rejects shell, LAMP, Nginx, Node, and WordPress before any split suite runs. #1116 staging built all six successfully. After #1116 lands and its exact artifacts are published, retargeting/re-running this stack against current main will give the classifier a current canonical baseline. No classifier code or package scope is being weakened to hide the mismatch. |
Member
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A Homebrew bottle can contain two different kinds of WebAssembly (Wasm)
modules:
php, which the kernel launches; andcurl.so, which an alreadyrunning process loads through
dlopen.The bottle inspector previously treated every Wasm member as a process
executable. That was safe for bottles containing only programs, but it rejected
valid side modules because they intentionally do not export the executable-only
__abi_versionfunction.This change makes the distinction from the artifact's real structure. It does
not exempt
.sofilenames or weaken executable checks. A file exposed throughHomebrew's
bin/orsbin/paths must still be a process executable.What changed
dylink.0section, which is the same structural contract used by Kandelo's dynamic
linker.
__abi_version.kernel.kernel_forkentrypoint; andenv.fork.bin/andsbin/links before Wasm validation and reject aside module exposed as a launchable entrypoint.
the shared validator.
PHP evidence
The PHP bottle that exposed this gap now classifies according to its actual
runtime behavior:
bin/phpcurl.so,intl.so,phar.so,zend_test.so,zip.soopcache.soopcache.soremains a side module and does not need the executable-only__abi_versionexport. Its fork status isrequiredfor a separate reason: itimports the side-module
env.forkentrypoint and carries the completewpk_fork_*continuation surface.Validation
Run in the repository-declared development shell:
bash scripts/test-homebrew-inspect-bottle.shbash scripts/test-wasm-artifact-guards.shruby scripts/check-homebrew-publish-workflow-trust.rbbash scripts/test-homebrew-publish-workflow.shOn the current stacked head, the three focused checks passed. The complete
publisher workflow passed through the real Homebrew lifecycle, OCI layout,
launcher isolation, Formula closure, bottle inspection, runtime evidence,
immutable-release recovery, and staging-release tests. Its first fresh-clone
run then stopped because root
node_moduleshad not been installed. After thedeclared
npm ci --ignore-scriptspreparation, the remaining VFS-release andmain-shell closure suites passed, including all 21 image-contract cases. The
pull-request workflow will repeat the complete prepared run.
The focused inspector fixtures cover:
bin/;dylink.0section;env.forkside module;.so-named ordinary Wasm executable missing__abi_version; andfork-instrumentation failures.
Additional checks:
git diff --check.Stacking and scope
This draft is based on the exact current head of
Automattic/kandelo#1112, which is itself based on the exact currentAutomattic/kandelo#1116shell-cutover head. That gives the migration oneordered chain: mostly-lazy shell, sealed schema-3 recipe publisher, then Wasm
side-module publication. This PR's only commit is the artifact-role classifier.
It does not change the shell image, package inventory, release locks,
publication pins, kernel, or ABI. As the two prerequisite PRs land, this PR
will be retargeted down the chain before merge.