fix(wasm_optimize): resolve symlinked inputs via loom_wrapper (#490) - #497
Merged
Conversation
wasm_optimize runs loom.wasm under `wasmtime run --dir=.`. A fetched or adopted component input (e.g. an http_file-sourced component) is staged by Bazel as a symlink whose target escapes the exec-root preopen, so wasmtime's WASI sandbox (cap-std) refuses to follow it and loom reports "Input file not found" — while wasm_validate on the same target succeeds because wasm-tools is a native binary, not sandboxed. Add a pure-Go //tools/loom_wrapper (mirroring //tools/wasmsign2_wrapper, as the existing TODO suggested) that resolves each path argument with EvalSymlinks and preopens the resolved real directories for wasmtime. loom.wasm is passed as the first argument (wasmtime opens the module natively, so it needs no WASI mount); only wasmtime is located via runfiles. Verified: loom_wrapper compiles and wasm_optimize analyses. End-to-end run against a fetched component still needs confirmation on the reporter's falcon setup (offered in the issue). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 13, 2026
Follow-up to the #490 preopen fix. avrabe verified the symlink fix works (zero "Input file not found"), but the wrapper then failed to locate wasmtime: Wasmtime binary not found at .../loom_wrapper.runfiles/+wasmtime+wasmtime_toolchain/wasmtime The hardcoded runfiles Rlocation `+wasmtime+wasmtime_toolchain/wasmtime` embeds the canonical repo name, which is correct only when rules_wasm_component is the root module. Consumed as a dependency (e.g. via git_override in jess), the canonical name gains a `rules_wasm_component+` prefix (`rules_wasm_component++wasmtime+wasmtime_toolchain`), so the lookup fails. Remove the runfiles lookup entirely: the rule now passes the wasmtime binary path as the first argument (and stages it as an action input), exactly as it already does for loom.wasm. wasmtime opens both natively, so neither needs a WASI mount, and there is no longer any canonical-repo-name dependency — the wrapper behaves identically whether rules_wasm_component is root or a dep. (The sibling wasmsign2_wrapper has the same latent Rlocation bug; tracked separately.) Verified: //tools/loom_wrapper compiles and //wasm/private:wasm_optimize analyses. Downstream falcon end-to-end re-test requested from the reporter. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
avrabe
added a commit
that referenced
this pull request
Jun 14, 2026
…nfiles (#501) (#503) * fix(wasmsign2_wrapper): pass wasmtime + wasm paths from rules, not runfiles (#501) wasmsign2_wrapper located wasmtime and wasmsign2.wasm via hardcoded canonical runfiles Rlocations (`+wasmtime+wasmtime_toolchain/wasmtime`, `+_repo_rules+wasmsign2_cli_wasm/file/wasmsign2.wasm`). Those canonical names are correct only when rules_wasm_component is the root module; consumed as a dependency they gain a `rules_wasm_component+` prefix, so the lookups fail at runtime and wasm_sign/verify/keygen break for downstream consumers. This is the same bug confirmed and fixed for loom_wrapper in #490/#497. Fix (mirrors #497): the wasm_sign/wasm_verify/wasm_keygen rules now pass the wasmtime binary and the wasmsign2 component as `--bazel-wasmtime=` / `--bazel-wasm-component=` arguments (and stage them as action inputs via the wasmtime toolchain + a `_wasmsign2_wasm` attr). The wrapper consumes those and no longer touches runfiles, so it is root/dependency-agnostic. Verified in-repo: keygen + sign + verify build end-to-end and //examples/wasm_signing:verify_embedded reports "Signature is valid." Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(#501): also fix wsc_attestation wrapper callers; share helper CI caught that wsc_attestation.bzl has three more wasmsign2_wrapper callers (wasm_attest / wasm_verify_chain / wasm_show_chain) that the first commit missed — making --bazel-wasmtime/--bazel-wasm-component mandatory broke them (e.g. //examples/wasm_signing:signed_component_chain_json, WasmShowChain). Extract the helper into wasm/private/wasmsign2_tools.bzl (WASMTIME_TOOLCHAIN, WASMSIGN2_WASM_ATTR, add_wrapper_tools) and load it from both wasm_signing.bzl and wsc_attestation.bzl. All six wrapper callers now pass wasmtime + the wasm component as action inputs/args; none use runfiles. Verified: `bazel build //examples/wasm_signing/...` (28 targets, incl. the show-chain target that failed CI) builds; verify targets report "Signature is valid." Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Fixes #490.
Problem
wasm_optimizerunsloom.wasmunderwasmtime run --dir=.. A fetched/adopted component input (e.g. anhttp_file-sourced component) is staged by Bazel as a symlink whose target escapes the exec-root preopen. wasmtime's WASI sandbox (cap-std) refuses to follow such a symlink, so loom reportsInput file not found— whilewasm_validateon the same target succeeds, because wasm-tools is a native binary and isn't sandboxed.The rule already carried a TODO noting the fix should mirror
wasmsign2_wrapper.Fix
//tools/loom_wrapper(mirrors//tools/wasmsign2_wrapper). ItEvalSymlinkseach path argument to its real location and preopens the resolved real directories for wasmtime (--dir <real dir>).loom.wasmis passed as the first argument — wasmtime opens the module natively, so it needs no WASI mount; only wasmtime is located via runfiles.wasm_optimizerewired to invoke the wrapper instead of wasmtime directly (the wrapper ownswasmtime+ the--dirresolution). The now-unusedwasmtime_toolchain_typedependency is dropped from the rule.Verification
bazel build //tools/loom_wrapper— the Go wrapper compiles.bazel build //wasm/private:wasm_optimize— the rewired rule loads/analyses; wrapper deps resolve.http_filecase in wasm_optimize: LoomOptimize action cannot find a fetched/symlinked input (wasmtime --dir=. preopen) #490) still needs confirmation — @avrabe offered to test against the falcon component in the issue. The wrapper follows the exact pattern of the already-workingwasmsign2_wrapper.🤖 Generated with Claude Code