SINGLE_FILE: Is there a way to look at the wasm embedded in the .js file?

17 views
Skip to first unread message

John Dallman

unread,
Jun 3, 2026, 7:32:13 AM (6 days ago) Jun 3
to emscripte...@googlegroups.com
I am not producing a web application. Indeed, I'm thoroughly unfamiliar with doing that; my background is C, C++ and assembly languages.  

I'm porting a large library written in C and C++ to WebAssembly using Emscripten, along with the library's test harness. The library is intended to be used in web applications, written by organisations that license this (commercial, closed-source) library. I'm planning to ship the library as an archive library, to be statically linked into web applications. I am not producing a JavaScript binding for it at present, because the API is large, complex, and not designed to be JavaScript-friendly: it uses lots of pointers. 

I'm linking the application and the test harness statically, with SINGLE_FILE, to produce a large .js file to run in Node. It's convenient for my build system to produce a single file, and that has also caused me to notice a potential problem. 

As I'm shipping an archive library, it's possible to do a link which produces basic debug symbols, such as function names. Emscripten doesn't do this by default, but it can. My management is rather jumpy on that subject, feeling that the names of functions in the library reveal significant information about the ways it operates. Since a web application is easier to get hold of than a licensed on-premises application, they're concerned about intellectual property protection. So, we will require organisations that license the WebAssembly library to not ship their web applications with debug symbols.

That raises the question of "How can we tell if they are complying with that requirement?"  
  • If they ship a .wasm file, it's easy: we use emnm to list debug symbols.
  • If they ship a .js file, emnm seems unable to handle that. Which is reasonable, since the wasm code is encoded as strings within the .js. 
Is there a way to extract .wasm code and debug symbols from within a SINGLE_FILE .js file? 

Thanks in advance,

John

Alon Zakai

unread,
Jun 3, 2026, 12:51:00 PM (6 days ago) Jun 3
to emscripte...@googlegroups.com
You can load the application in a browser, then open the devtools and inspect the wasm there.

In Chrome for example, go to the Sources tab in devtools and open the wasm file. That shows a disassembled version, which might be enough information already, and you can also rightclick and save it.


--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-disc...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/emscripten-discuss/CAH1xqgnZrPBrms5hBB9cco-sTv-Vn5PNYep4xMTg3kp32gNuqQ%40mail.gmail.com.

Jukka Jylänki

unread,
Jun 3, 2026, 12:52:30 PM (6 days ago) Jun 3
to emscripte...@googlegroups.com
1. If you are shipping the code for a web browser to execute, _and_
the code footprint is large, it is definitely recommended to ship a
separate .wasm file. That enables streaming WebAssembly compilation
(Wasm is already being compiled while the file is being downloaded),
which improves site loading times by a great deal, compared to a
SINGLE_FILE build.

2. The SINGLE_FILE encoding makes it very easy to examine function
names and C strings in the code in a text editor. That was one of the
design goals. See the attached screenshot. If you want to detect
whether debug symbols were present in a SINGLE_FILE output, you can
search for the bare C strings directly in the file.

3. Reconstructing the original .wasm code from a SINGLE_FILE output is
also very easy, it is effectively a text string snipping job, like
extracting a base64 string in a text file would be. In the attached
screenshot, take the string inside the call to binaryDecode('...'),
that is the Wasm module.

4. WebAssembly is a high-level structured virtual ISA, so it does not
allow unstructuring tricks like omitting frame pointers. Functions,
loops and branches are always explicitly encoded and there are no
spaghetti like with gotos/jumps. This allows easier decompilation back
to high level C, compared to native assembly code, even if debug
symbols were not present.

This might be a scenario to look into some code JS obfuscation strategies.
image.png

Xellos

unread,
Jun 4, 2026, 5:00:44 AM (5 days ago) Jun 4
to emscripten-discuss
There are levels to obfuscation.

Inspecting some of my own WASM files, I can see that internal names from source code appear even in release builds. However, to compilers and interpreters (and even decompilers) it shouldn't matter what exactly those names are - "getNumberOfSkinCareEligibleItemsWithinTransaction()" provides the same information as "foo123()". This is different from obfuscation by changing the data flow. Informative strings in binary are low-hanging fruit and the most common way to leak info. Isn't there a flag to minify/obfuscate them when making the WASM binary?

Alon Zakai

unread,
Jun 4, 2026, 12:18:02 PM (5 days ago) Jun 4
to emscripte...@googlegroups.com
Strings definitely show up in the wasm binary, like they do in normal binaries. But function names are minified by default in optimized builds, and do not appear. Even imports and exports are minified in -O3 and above, which is recommended.

So if you see something like "getNumberOfSkinCareEligibleItemsWithinTransaction()" in the binary, either it is a string, or it isn't an optimized build, or something is going wrong and please file a bug with a testcase.

--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-disc...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages