Go 1.17.2 bounds WebAssembly startup arguments
The WebAssembly security repair coordinates a reserved memory region in the linker with a limit in wasm_exec.js. Updating both deployment artifacts is part of the fix.
A Go WebAssembly deployment includes assumptions shared between generated code and its JavaScript launcher. Startup arguments occupy part of the module's linear memory. The linker places program data elsewhere. When the argument writer and data layout do not maintain a sufficient boundary, a large input can reach memory that the module uses for another purpose.
The October 7 security announcement describes CVE-2021-38297. Large arguments passed when invoking Go WebAssembly modules can overwrite portions of the module with argument data. It announces Go 1.17.2 and Go 1.16.9 and explicitly tells wasm_exec.js users to replace their copy after rebuilding modules.
The release history lists the security changes in the linker and misc/wasm. Those locations describe two parts of one repair. A toolchain update must produce a new module, and a deployed support script must carry the matching validation.
I like the deployment simplicity of Go executables, but this target has an additional artifact with a real runtime role. Treating the JavaScript file as an incidental example would miss part of the program that establishes its startup state.
The launcher writes into linear memory
The Go 1.17.2 launcher implementation shows how run prepares an instance. It creates a DataView over the exported memory buffer. Then it writes command-line arguments and environment variables into that memory, beginning at offset 4096.
Its string helper encodes a string with a terminating zero byte and copies the encoded bytes into a Uint8Array view. The offset advances by the encoded size, then rounds up to an eight-byte boundary. Each copied string contributes a pointer to a list that the launcher will also place in memory.
The argument list and environment therefore share the startup region. The launcher sorts the environment keys and writes each key-value entry as a string. It appends null pointer entries to delimit the lists. After the strings, it writes pointer values and advances the offset for each entry.
That layout means the final size depends on more than the number of visible characters in one argument. Encoded bytes consume space, alignment can consume additional bytes, and the pointer list has its own cost. The final offset represents the complete preparation performed by this code path. Checking only one argument length would not describe that combined allocation.
These are writes inside the module's memory buffer. Staying inside that buffer is not enough to establish that they avoid every other object stored there. A writer can use a valid linear-memory address while violating the internal division between startup data and program data. The security problem concerns that division.
The linker and launcher agree on a boundary
The release diff adds a constant to the linker called wasmMinDataAddr. Its value is 4096 plus 4096. The associated comment reserves one region for the zero page and another for wasm_exec.js to store command-line arguments. Data sections start at least at address 8192.
The linker adjusts address assignment so that the next relevant section cannot begin below that minimum on WebAssembly. This gives the generated module a layout property the launcher can rely on. It does not make the startup argument region grow to accommodate arbitrary input.
The JavaScript side uses the same minimum. After preparing strings and pointers, it checks the resulting offset. The new condition appears immediately before the call into the module's exported run function.
const wasmMinDataAddr = 4096 + 4096;
if (offset >= wasmMinDataAddr) {
throw new Error("command line too long");
}
This rejects the prepared startup state when it reaches the reserved boundary. The code does not promise a successful invocation with an arbitrarily large command line. It gives the launcher a defined failure path before it starts the module with that state.
Both files have comments requiring the constants to remain synchronized. That is an explicit cross-language contract. One side controls placement of module data, and the other controls whether prepared startup input is acceptable. The comments make the dependency visible to future maintainers changing either implementation.
A rebuilt module is only part of deployment
The advisory's instruction to replace wasm_exec.js follows directly from this split. Rebuilding with the new linker changes the module layout. Copying the support script changes the launcher's check. A deployment that updates one artifact while leaving the other unchanged does not match the repaired arrangement described by the patch.
This matters when static assets have different publication paths. A module and its launcher may have distinct filenames or cache lifetimes. The relevant operational requirement is that the pair deployed for execution carries the intended layout and validation together. Updating the compiler installed on a development machine does not replace a support script already served to users.
The affected target in the announcement is GOOS=js with GOARCH=wasm. It does not describe native Go binaries as having this startup-memory layout. The platform qualification is part of assessing exposure, since the helper file and linker changes address the JavaScript WebAssembly execution path.
I find the patch useful as a reminder to examine the code that runs before the application starts. The launcher establishes arguments and environment values on the application's behalf. Its memory assumptions are consequently part of program correctness, even though most application source code never names that offset.
The failure is within the module's layout
The advisory describes overwriting portions of the module with argument data. That should not be inflated into a claim that the patch demonstrates a browser sandbox escape. The inspected code and announcement establish an internal memory-layout failure and its coordinated repair. They do not establish effects outside that environment.
The repair makes the startup limit explicit in the launcher and establishes a minimum data address in the linker. Its deployment instructions identify the two artifacts that carry those changes. For this release, a complete update means using the rebuilt module with the replacement wasm_exec.js so the layout guarantee and startup check agree.