How to use the WebAssembly (wasm) binary module in macos App

During the release of our macOS App, we encountered the following issue:

We need to support dynamic code loading of WebAssembly (wasm) inside our App, mainly by loading WebAssembly (wasm) binary modules.

We discovered a problem: a wasm file is neither an executable nor a bundle, so it cannot be code-signed. Since our App needs to pass notarization, we have not set the com.apple.security.cs.allow-unsigned-executable-memory entitlement.

Without setting com.apple.security.cs.allow-unsigned-executable-memory, loading a wasm module results in an “unsigned code” error that causes the process to crash.

Could you please advise on what we should do to avoid this problem? Is it possible to apply for a special entitlement to allow com.apple.security.cs.allow-unsigned-executable-memory?

Answered by DTS Engineer in 864448022

Yeah, I figured you’d get see something like this.

IMPORTANT All of the following assumes you’re targeting macOS. The story for iOS and its child platforms is very different.

From the perspective of code signing on Apple platforms, this is data not code. We touch on this in Placing content in a bundle; see the discuss of shell scripts in that doc. Given that, you should place these files in Contents/Resources where they’ll be sealed over by the code signature like any other resource file.

That takes care of the on-disk side of things. How you handle this in memory depends on your WebAssembly runtime. Some runtimes are pure interpreters. Those don’t generate code on the fly, and thus don’t need to take any special action to allow that code to run.

However, high-performance WebAssembly runtimes often include a JIT. There are two ways you can create a JIT:

  • The recommended path is the one described in Porting just-in-time compilers to Apple silicon.
  • Many legacy JITs don’t follow those rules, relying instead of com.apple.security.cs.allow-unsigned-executable-memory. This is significantly less secure.

Both approaches are compatible with both of our distribution channels, that is, the Mac App Store and direct distribution using Developer ID signing.

And that brings me to this:

Is it possible to apply for a special entitlement to allow com.apple.security.cs.allow-unsigned-executable-memory?

That entitlement is unrestricted [1], that is:

  • Any developer can use it at any time.
  • It doesn’t have to be authorised by a provision profile.

Likewise for the entitlements used by our recommended JIT path.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] In the terminology defined by TN3125 Inside Code Signing: Provisioning Profiles.

Thanks for bringing this to the forums.

I’m pretty sure that’s a straightforward answer to this, but before I go into details I want to confirm one thing. When you do this:

% file /path/to/module

where /path/to/module is one of these WebAssembly binary modules, what does it report?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

@DTS Engineer it reports: WebAssembly (wasm) binary module version 0x1000d

Yeah, I figured you’d get see something like this.

IMPORTANT All of the following assumes you’re targeting macOS. The story for iOS and its child platforms is very different.

From the perspective of code signing on Apple platforms, this is data not code. We touch on this in Placing content in a bundle; see the discuss of shell scripts in that doc. Given that, you should place these files in Contents/Resources where they’ll be sealed over by the code signature like any other resource file.

That takes care of the on-disk side of things. How you handle this in memory depends on your WebAssembly runtime. Some runtimes are pure interpreters. Those don’t generate code on the fly, and thus don’t need to take any special action to allow that code to run.

However, high-performance WebAssembly runtimes often include a JIT. There are two ways you can create a JIT:

  • The recommended path is the one described in Porting just-in-time compilers to Apple silicon.
  • Many legacy JITs don’t follow those rules, relying instead of com.apple.security.cs.allow-unsigned-executable-memory. This is significantly less secure.

Both approaches are compatible with both of our distribution channels, that is, the Mac App Store and direct distribution using Developer ID signing.

And that brings me to this:

Is it possible to apply for a special entitlement to allow com.apple.security.cs.allow-unsigned-executable-memory?

That entitlement is unrestricted [1], that is:

  • Any developer can use it at any time.
  • It doesn’t have to be authorised by a provision profile.

Likewise for the entitlements used by our recommended JIT path.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] In the terminology defined by TN3125 Inside Code Signing: Provisioning Profiles.

How to use the WebAssembly (wasm) binary module in macos App
 
 
Q