- The paper introduces a binary-level transpiler that injects stack canaries and function-wise ASLR into WebAssembly binaries to mitigate buffer overflow vulnerabilities.
- It employs random value generation and redundant checks in each function’s prologue to detect corruption and disrupt exploitation attempts.
- Evaluation shows measurable overhead with effective defense, though limitations remain due to entropy constraints and granular injection challenges.
Defending Buffer Overflows in WebAssembly: A Transpiler Approach
Introduction
This paper presents a binary-level approach for defending against buffer overflow vulnerabilities in WebAssembly (Wasm) by automatically injecting stack canaries and Address Space Layout Randomization (ASLR) into Wasm binaries using a transpiler. The proposed method addresses a critical gap in Wasm security: most protections against memory corruption, such as those in modern C/C++ toolchains, are absent in the default Wasm compilation pipeline. The solution is specifically aimed at defending unmanaged regions of Wasm linear memory, where high-level constructs are mapped and where typical buffer overflow exploits are feasible.
WebAssembly Memory Model and Attack Surface
WebAssembly defines a strict separation between managed (local variables, globals, return addresses) and unmanaged (linear memory) data. Managed data is inaccessible via raw addresses and protected via the VM. In contrast, complex constructs (arrays, structs) and often the program stack are implemented within linear memory using explicit pointer management, rendering them vulnerable to traditional stack-based buffer overflow attacks. While sandboxing in the VM reduces the severity of certain exploits, it does not fully mitigate risks, especially as Wasm is increasingly deployed for edge-cloud workloads or shared environments where attackers may leverage buffer overruns for lateral movement or privilege escalation.
Figure 1: Example of a WebAssembly program in wat format illustrating linear memory access and stack manipulation.
Binary Rewriting as a Security Posture
Two architectural options exist for Wasm security enhancement: modification of the original compiler to inject mitigations, or binary rewriting (post-processing) of compiled Wasm output. The paper's approach is the latter—a transpiler that accepts insecure Wasm binaries and rewrites them to add stack canaries and ASLR, facilitating retroactive hardening of legacy or third-party code without recompilation. This design choice enables frictionless, source-agnostic application, though it is necessarily constrained by the limited binary-to-source mapping information at the Wasm level.
Implementation: ASLR and Stack Canary for Wasm
Random Value Generation
Correct protection requires high-entropy randomness for canary and layout diversification. The transpiler integrates random generation logic by harvesting existing implementations (via Emscripten's srand/rand/time patterns), injecting them into the Wasm binary and corresponding JavaScript glue layer.
Function-wise ASLR
Traditional x86 ASLR randomizes global memory regions per process start; in Wasm, the transpiler randomizes the global stack pointer per function invocation. This localizes entropy between caller/callee stack frames, disrupting deterministic stack-based offset attacks, as demonstrated in the prologue code pattern. The randomized offset is carefully bounded to avoid out-of-bounds errors due to the 32-bit address constraint of Wasm and alignment requirements.
Stack Canary Injection
The transpiler appends code to each function's prologue and epilogue for canary set/check. A random canary is written to a local variable (which remains managed and inaccessible by linear memory manipulation), then mirrored—via an injected store—into unmanged stack space within the function. During return, the canary is reloaded and compared; mismatch (indicating adjacent stack corruption) triggers an "unreachable" instruction, causing immediate program termination.
Notably, canary value storage in function-local variables yields higher tamper-resistance compared to traditional approaches that store the canary within linear memory, as linear memory is directly attackable via overflow.
Security Evaluation
Overhead Analysis
Each protection mechanism introduces per-function instruction overhead, with ASLR and canary logic adding up to 20-40 instructions per function. This cost is function-call proportional, and the two mechanisms share prologue RNG logic to minimize duplication. The additional dynamic checks and pointer manipulation instructions yield a tangible but bounded cost in most practical applications due to typical function granularity.
Coverage
The paper validates the approach against a known vulnerable Wasm program, confirming both that ASLR disrupts targeted stack manipulations required by exploits and that stack canaries effectively terminate execution on successful buffer overflow attempts. This is highly significant given prior work demonstrating approximately one third of Wasm binaries store stack data in vulnerable, unmanaged regions and that a substantial fraction of call instructions are indirect—a classic avenue for control-flow hijacking.
Limitations
The primary limitation is the restricted entropy space for randomized values in Wasm—a 32-bit address space yields at most an 8-bit effective randomization window for stack frame separation before risking runtime errors due to memory exhaustion. As a result, brute-force attempts remain tractable in high-iteration exploit settings.
A further constraint is that the transpiler cannot reorder local variables or insert fine-grained canary values between adjacent buffers within the same stack frame. For stronger intra-function isolation, compiler-level collaboration would be required to enable buffer-reordering strategies found in modern hardening toolchains.
Stack canaries generated with time-based seeds may leak if the attacker can precisely control execution timing, making the approach less robust against adaptive threats. Enhanced entropy sources or runtime-generated secrets are needed for defense-in-depth.
Global variables residing in "managed" regions cannot be protected without VM support; if overflows corrupt critical global state, the proposed scheme cannot intercept such attacks.
Implications and Future Directions
Practically, this transpiler-based approach provides immediate, deployable buffer overflow hardening for Wasm in scenarios where recompilation is not feasible, enhancing the Wasm security ecosystem for both browser-based and edge-deployed workloads. Theoretically, it demonstrates the effectiveness—and limits—of binary-level injection for post-hoc memory safety hardening in register- and pointer-rich low-level intermediate languages.
Further research is warranted in two main directions:
- Compiler/VM Integration: To enable variable reordering and harden global state, cooperation with Wasm compilers and the core VM is necessary.
- Advanced Control-flow Integrity: Protection of the indirect call table through runtime randomization or signature checking must be improved to raise the bar for control-flow attacks.
- RNG Robustness: Side-channel-resistant entropy injection should replace time-based seeds to strengthen canary and ASLR defense against adaptive adversaries.
Conclusion
The paper presents a methodical transpiler-driven solution for defending Wasm binaries against buffer overflows using function-wise ASLR and stack canary injection (2604.03859). While the approach faces entropy and instrumentation granularity limitations, its non-intrusive binary-level deployment makes it immediately valuable for increasing the resilience of Wasm workloads. The analysis establishes a clear baseline for future research integrating compiler-level memory safety features and expanding the protection scope to additional Wasm vulnerability classes.