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 handheld console and broken shields illustrate ns2jb chaining SmileBASIC and filesystem bugs on Switch 2.

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,&H3FFFFFFF

The 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

  1. 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.

  2. 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.

  3. 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.

FAQ

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.

Vishal
· Developer

Vishal writes Trickyworld's tutorials and interview-preparation guides on programming, databases, cyber security and AI. Vishal has been shipping production software long enough to have firm opinions about Python, PHP, Node.js, and JavaScript, and to have been wrong about each of them at least once. The work has run the whole stack: Drupal and Laravel applications, React front ends, MySQL and MongoDB underneath, Redis and Memcached for the things that had to be fast, Apache Solr for the things that had to be findable. That last part turned out to matter more than anyone expected. Tune a Solr index for a season, then watch a language model confidently retrieve the wrong document, and you recognise an old problem wearing new clothes. Most of what is hard about AI systems is not the model. It is retrieval, caching, latency budgets, and deciding what the system does when the answer comes back wrong — which is work he has been doing since well before anyone called it AI engineering. He plays a lot of games, which is less a hobby disclosure than an admission of where a good share of his engineering instinct came from. Real-time systems with a frame budget. State that has to stay coherent while a player does something no designer anticipated. The permanent question of what happens when the frame cannot finish in time. Those habits carry over more directly than they have any right to. He has written several books on programming, all built on the same conviction: most technical writing is unclear because the author never decided what to leave out. More from Vishal → · Editorial policy

More on Cyber Security.

Latest articles

$ subscribe --weekly

Get the next tutorial in your inbox.

Programming, security and AI — the practical bits, no spam. Unsubscribe any time.