ns2jb Chains SmileBASIC and Filesystem Bugs on Switch 2
ns2jb chains SmileBASIC memory corruption with filesystem control; follow the native-code path and decide whether the published research is enough to proceed.

A valid signed archive header can accompany an entirely different executable in the ns2jb exploit chain. This Switch 2 jailbreak is software-only and tethered, and it hands you arbitrary native code in ordinary system modules plus the built-in filesystem module. Tracing its path through SmileBASIC and the loader shows what researchers actually gained—and what you need to verify before you even think about reproducing it.
For homebrew developers and game researchers, the payoff is concrete: modding, backing up saves, and reaching most peripherals through memory-mapped I/O. The author's account describes native code execution as any ordinary sysmodule and as the built-in fs sysmodule.
WebKit stalled; SmileBASIC supplied the entry point
Codex's initial WebKit route went nowhere. It chased a known WebKit bug through a custom Wi-Fi captive portal, but swapping one JavaScript function object for another never generalized into arbitrary IPC calls. That left a hard gap between browser execution and useful system services.
The author pivoted to Switch 1 games, specifically SmileBASIC. Its interpreter had already fallen on the 3DS, and Codex found a usable integer overflow in this implementation. The SmileBASIC agent worked on Switch 1 while the WebKit agent kept running on Switch 2.
“The jailbreak itself took substantial effort for ~2 weeks.”
— the ns2jb write-up
That quote matters because the author explicitly rejects the idea that a playful prompt autonomously produced the jailbreak. Codex contributed research; the separate Mario Kart World mod was, in the author's words, entirely vibecoded in a day.
How does SmileBASIC turn array removal into memory access?
The interpreter validated an array-removal range with position + count <= array.length, but the addition can overflow a signed 32-bit integer. A wrapped negative result passes the check. The write-up illustrates the subsequent copy with this code:
memmove(
backing + position * 8, // start of the gap
backing + (position + count) * 8, // elements after the gap
(length - position) * 8 // bytes to copy
);The example uses a string array named R with length 4, followed by this command:
REMOVE R,&H60000000,&H3FFFFFFFThe sum wraps to 0x9fffffff, negative as a signed 32-bit integer. The multiplications wrap too, yielding the equivalent of memmove(backing, backing - 8, 32). The command reports an Out of memory error, but the copy has already happened.
The preceding 8 bytes hold a pointer to the array itself. Shoving that pointer into the string array makes operations on R[0] treat the array backing as a string. A pointer now sits in the apparent string-length field, granting an enormous length; substring operations then hand you out-of-bounds reads and writes. The decisive failure: an error reported after memory has already been corrupted.
An fs path overflow crossed into a privileged service
The next useful boundary was the built-in filesystem service, fs. Its IFileSystem interface exposes GetEntryType, which normalizes a supplied path through Path::Normalize. Paths containing a parent-directory component with a backslash—/..\—hit a helper that allocates a temporary buffer of 0x301 bytes.
The copied path can exceed that buffer. Codex spotted a useful neighbor: a BufferedStorage cache entry. When its dirty bit is set, file reads and writes follow a pointer to cached data. Corrupting that pointer gave arbitrary read/write inside fs.
The author then changed the saved process identifier in SmileBASIC's connection object to 1, grabbing what the service calls FullPermission. That unlocked privileged filesystem operations, including dumping internal storage and ordinary system-module code for offline analysis.
Controlling fs let the researchers attack the loader's trust in filesystem responses. It wasn't just a game process with corrupted data anymore.
The loader trusted a filesystem ns2jb already controlled
The loader's signature checks didn't independently guarantee the executable bytes matched the authenticated archive. Games and ordinary system modules ship in Nintendo Content Archives (NCAs), which contain an executable filesystem called ExeFS. The built-in ldr module asks fs to open that filesystem.
These are the relevant pieces of that loading arrangement:
Component | Role described in the write-up |
|---|---|
main | The program's main executable inside ExeFS. |
main.npdm | Program metadata containing process permissions and the developer's public key. |
NCA header hash and signature | Cryptographic information supplied by fs to the loader for signature checking. |
The responsibility for matching the served filesystem to the archive header's filesystem hash sat with fs. With arbitrary read/write already there, the exploit could swap the ExeFS object behind the loader's handle for a temporary filesystem. It kept valid developer metadata while serving an arbitrary executable.
The original header hash and signature had already been supplied. The exploit therefore changed the content provider without forging a developer signature. It also controlled when fs processed loader messages by substituting an event handle for the connection handle fs waited on, letting the replacement happen between the relevant requests.
The result: execution under the permissions of any program the researchers had metadata for. Their fs access let them harvest that metadata for ordinary system modules and games.
ro supplied the permissions needed to patch fs
The ordinary system module ro was valuable because its metadata permitted executable-memory operations. The author found it was the only ordinary system module with permission to map executable code. The write-up also notes CFI, PAC, and XOM protections, making a loader logic flaw more attractive than directly chasing memory corruption in ro.
The researchers launched their own code using ro's metadata. They used MapProcessMemory to create a writable view of fs's existing code, which also let them dump that code. Getting fs's process handle took another pass of the existing arbitrary read/write; the handle could then be sent to the custom ro process.
That completed the transition from reading and changing service data to patching service code. The reported outcome is native code execution with ordinary system-module permissions and inside fs, not merely control over the original game interpreter.
Check ns2jb requirements before using a research console
Verify the console firmware, SmileBASIC build, and launch requirements against the repository material. Require a documented match for your intended target rather than assuming a Switch 1 game entry point works across unspecified Switch 2 configurations.
Separate the milestones when evaluating a reproduction. SmileBASIC memory access, arbitrary read/write in fs, execution using ro's permissions, and patching fs are different achievements. Evidence of an earlier stage shouldn't be counted as evidence the whole chain completed.
Establish a crash-recovery procedure before automating attempts. The author's setup needed a physical power-button press when the Switch 2 crashed. Don't treat remote controller input as proof recovery is also covered.
A tethered jailbreak is not finished custom firmware
The supplied account lacks a firmware compatibility matrix, a patched-version list, and an end-to-end installation sequence. Some intermediate explanations are incomplete, including the enumerated loader checks and writes. That leaves insufficient information to name supported versions or present a reliable installation guide from this text alone.
The author hopes this capability helps the homebrew community progress toward custom firmware (CFW). That's a direction for further work, not a claim that complete CFW is already delivered. Likewise, the description explicitly says tethered; it shouldn't be rewritten as a promise of untethered operation or persistence.
Valid signatures didn't protect the executable-loading boundary once the filesystem service supplying the bytes was under attacker control.
Frequently asked questions
How did Codex interact with the physical consoles?
JetKVM devices let Codex send controller inputs over USB and receive video over HDMI. A Bluetooth light-switch mechanism physically pressed the Switch 2 power button so the console could be restarted after a crash.
Why might the researchers revisit WebKit later?
The author says a WebKit data-only attack might become worthwhile after identifying a valuable system-module bug. WebKit is accessible offline and cannot be withdrawn like an eShop title, although the author judged that route too costly for iteration speed at this research stage.
Does the author claim ns2jb is the first Switch 2 exploit of its kind?
The author qualifies that statement with “To my knowledge” and calls it the first such exploit for the Switch 2. That is a qualified claim from the write-up, not independent confirmation of priority.
Source: You can get a copy of the exploit from the ns2jb repository.
How this article was made: drafted with AI from the source above and fact-checked against it. How we write and check articles.



