WebAssembly runs validated instructions inside a sandbox with its own linear memory. A module does not receive ambient access to files, networks or operating-system calls. The embedding environment must expose those capabilities through explicit imports.
That is a useful security boundary, but it is not a promise that every WebAssembly application is safe. The host API, runtime, module code and surrounding application still determine what the module can do.
Specifications checked: the WebAssembly Core Specification and WebAssembly security model were reviewed on 29 October 2026.
The short answer
| Question | Answer |
|---|---|
| Does WebAssembly have its own memory? | Yes. A module normally reads and writes its linear memory rather than arbitrary host memory |
| Can a module open a file by itself? | No ambient file access exists in the core specification; the host must provide an imported function or interface |
| Can unsafe C code still corrupt data? | It can corrupt data inside its own linear memory, even though the runtime protects memory outside the sandbox |
| Does the sandbox stop every attack? | No. Host imports, runtime flaws, side channels and application bugs still matter |
| Is browser WebAssembly separate from web security? | No. It also follows browser controls such as same-origin policy and content security rules |
| Is server-side WebAssembly automatically least privilege? | No. The runtime or component host must limit which capabilities it grants |
The sandbox is a boundary around execution. It is not a substitute for capability design.
What the WebAssembly core defines
The WebAssembly Core Specification defines a portable virtual instruction set, binary encoding, validation rules and execution semantics.
Before execution, a runtime validates a module. Instructions must have consistent types, branches must follow structured control flow and memory accesses must stay within defined bounds.
This validation lets a runtime compile WebAssembly to machine code while preserving the language’s execution rules. Invalid modules are rejected rather than executed speculatively as if they were valid.
The core specification deliberately does not define a filesystem, network stack, clock, process model or user interface. Those belong to the environment embedding WebAssembly.
Linear memory is a guarded byte array
A WebAssembly module can use one or more linear memories. A linear memory is an indexed sequence of bytes addressed from zero.
Compiled languages use that space for stacks, heaps, strings and objects. A load or store outside the current memory bounds traps rather than reading arbitrary host memory.
This protects the host from a module simply calculating a pointer into another process or runtime object. It also separates modules from one another when the embedder provides independent memories.
The boundary does not make unsafe source code memory-safe within the module. A C or C++ program can still overwrite the wrong object, use stale data or disclose secrets that are stored elsewhere in the same linear memory. The specification’s own design notes make this distinction explicit: the module cannot break the WebAssembly memory model, but unsafe code can corrupt its own memory layout.
Imports are the capability boundary
A module declares the functions, memories, tables and globals it expects to import. The host chooses whether to provide them.
An import can be narrow, such as:
- calculate a cryptographic hash;
- write to a limited log;
- read one configuration value;
- fetch data from a specified service;
- access a pre-opened directory.
It can also be dangerously broad, such as a function that accepts any file path or executes an arbitrary operating-system command.
The WebAssembly sandbox cannot limit what a powerful imported function does once the module is allowed to call it. The embedder must apply authentication, authorization, path checks, quotas and output validation.
A useful rule is to grant functions that perform one bounded action rather than exposing a general-purpose escape hatch.
Exports work in the other direction
A module can export functions, memory, tables and globals to the host. The host calls those exports through the runtime.
An exported function should be treated like any other untrusted parser or library entry point. Validate lengths, encodings, indexes and state transitions. A valid WebAssembly module can still contain malicious application logic.
If the host shares a memory object with JavaScript or another module, that shared memory becomes part of the trust boundary. The host should not put unrelated secrets into a region that untrusted code can read.
Structured control flow and indirect calls
WebAssembly uses structured blocks, loops and branches rather than arbitrary jumps. Function signatures are declared, and indirect calls are checked against expected types.
These rules support control-flow integrity. A corrupted value cannot simply redirect execution to any byte address as traditional native code might.
This narrows a class of exploits. It does not remove logic bugs. A module can call the wrong authorized function, loop indefinitely, consume resources or return crafted output while obeying every control-flow rule.
The browser adds its own security model
In a browser, WebAssembly runs inside the same web platform security model as JavaScript. The WebAssembly web embedding guidance points to same-origin policy, cross-origin resource sharing and subresource integrity as relevant controls.
A module does not bypass CORS because it was compiled from C. Network access still goes through browser APIs exposed by JavaScript or the embedding.
Content Security Policy can affect whether a page is allowed to compile or execute WebAssembly. Subresource Integrity can help a page verify a fetched module’s bytes when it is loaded from a CDN.
The module also shares the page’s application risks. A cross-site scripting flaw that controls JavaScript may influence which module is loaded, what imports it receives and how its exports are called.
Server-side WebAssembly needs an interface
Outside the browser, a runtime can embed WebAssembly in a server, edge worker, plugin system or command-line application.
The core module still has no ambient operating-system access. Practical applications use an interface supplied by the runtime, such as a component API or WASI implementation.
The security outcome depends on configuration. A runtime that pre-opens one read-only directory is different from one that exposes the entire filesystem. A network policy allowing one origin is different from unrestricted sockets.
Document the capability set as part of deployment, not as an invisible runtime default.
Resource limits are separate from memory safety
A module can stay within memory bounds and still consume excessive resources.
Set limits for:
- maximum linear memory;
- table growth;
- execution time or instruction fuel;
- recursion and call depth;
- concurrent instances;
- open handles;
- output size;
- network requests;
- log volume.
Without limits, a valid module can allocate memory until the host is under pressure or run an infinite loop. A sandbox that prevents memory escape but allows denial of service is incomplete for multi-tenant use.
Side channels remain possible
The core specification notes that WebAssembly is compiled to machine code and can be affected by hardware-level side channels. Timing, caches and speculative execution can reveal information even when direct memory access is blocked.
Browser and runtime mitigations reduce some risks, but an embedder handling high-value secrets should not assume that linear-memory isolation solves every microarchitectural attack.
Keep secrets out of untrusted instances where practical. Use process, virtual-machine or hardware isolation when the threat model requires stronger separation.
Runtime vulnerabilities matter
The sandbox relies on the runtime correctly validating and compiling modules. A bug in a JIT compiler, bounds check or host binding can weaken the boundary.
Operational controls therefore include:
- run a supported runtime version;
- apply security updates promptly;
- disable unused proposals and interfaces;
- isolate high-risk workloads at the process or container level;
- test malformed modules and import failures;
- monitor crashes, traps and resource-limit events;
- verify module provenance and integrity.
Defense in depth matters because the runtime is part of the trusted computing base.
Module provenance and supply chain
A sandbox answers what code can reach at runtime. It does not answer whether the module is the one you intended to deploy.
Record:
- source repository and commit;
- compiler and version;
- build flags;
- dependency lockfile;
- module hash;
- signature or attestation where used;
- runtime and interface version.
Our SLSA build provenance explainer covers how build metadata connects an artifact to its builder and inputs. An SBOM lists components but does not prove the build or guarantee the module is safe.
A review checklist
Before running a third-party module:
- Verify the module hash and source.
- List every import and why it is needed.
- Limit filesystem access to explicit paths.
- Limit network access to required destinations.
- Set memory, time and concurrency quotas.
- Validate all inputs and outputs.
- Avoid sharing memory that contains unrelated secrets.
- Run a supported, patched runtime.
- Log traps and denied capability requests.
- Test the module with capabilities removed.
- Decide whether process or VM isolation is also required.
- Recheck the capability set when the module or runtime changes.
If the module needs a general shell, unrestricted filesystem and unrestricted network, the practical isolation is much weaker than the word sandbox suggests.





