A Remote Router Shell Without Port Forwarding or an Exposed SSH Port, After MikroTrick
On 5 September, CERT Polska told MikroTik owners to disable exposed management services or block them from everything outside trusted management networks, naming "SSH, WWW/WWW-SSL, and the bandwidth-test server" in particular. Attackers were already inside. This post is about the narrower problem behind that advice: getting a remote router shell without port forwarding, so there is no SSH port on the WAN side for the next bug to land on. We will use shell.online, our browser link to any terminal process, and be specific about where it fits on a small Linux device and where it does not.
What MikroTrick needed: a listening SSH server
CERT Polska's technical analysis of MikroTrick, published on 22 September, describes a chain of two RouterOS bugs. In CVE-2026-67279, a rekey started during user authentication sent the SSH server on to channel handling instead of back to authentication, so it accepted a session channel without ever sending SSH_MSG_USERAUTH_SUCCESS, the message RFC 4252 defines as the end of a successful login. In CVE-2026-86060, sshd passed the unvalidated username to its login binary as an argument. A username of -2 was read as a file descriptor, and the login process took its username and policy mask from the attacker's pseudoterminal. The result was full administrative console access with no credentials.
The timeline is short. CERT Polska's earliest public attack logs are from 2 September, patched builds (7.25beta3, 7.24.2, 7.23.4 and 6.49.21) shipped on 3 September, and CVE-2026-86060 went into CISA's Known Exploited Vulnerabilities catalog on 10 September with a three-day deadline. The Hacker News reported federal agencies had until 13 September to patch.
The same write-up has a detail that matters for anyone running agents. CERT Polska did much of the analysis with LLM agents driving a lab of 40 RouterOS virtual machines across 24 releases, and the authors write that "The LLM created and operated the tools that performed these tasks." CERT Polska also says CVE-2026-86060 was identified within an hour of diffing the patch. Once a fix ships, a management port that is reachable from the internet is racing whoever diffs it first.
A remote router shell without port forwarding
shell.online turns the connection around. The CLI runs on the device, starts a command under a PTY, and connects outbound over HTTPS and WebSockets to a relay. A browser with the link and password connects to the same relay. Nothing on the device accepts inbound connections from the internet, so there is no port to forward and nothing for a scanner to find.
That claim is checkable in the shell.online source on GitHub. On Unix, each session's local control channel (used by shell list, shell attach and shell kill) is a Unix domain socket set to mode 0600, opened in cmd/shell/local_transport_unix.go. The only TCP listener in the CLI is a 127.0.0.1 loopback port that the optional account sign-in opens for its OAuth callback, and a router does not need an account.
A typical session on the device looks like this:
shell --read-only logread -f
The terminal prints a URL, a ten-character password and a QR code. Open the URL on a phone, type the password, and you see the live system log. With --read-only, the security model page says input "is rejected by both the relay and the CLI. A modified browser cannot turn this into an interactive session." For watching a router during a firmware change or a flaky uplink, that is usually all you want.
When you do need to type, give the session an end time:
shell --auto-close 30m sh
The session closes when sh exits or when 30 minutes pass, whichever comes first; at the deadline the CLI cancels the wrapped process too, so a forgotten root shell does not sit open overnight. Durations combine (1h30m), and the command reference also accepts clock times such as tomorrow 09:00. shell list shows what is running, and shell kill -- <ID> stops one session without touching the others.
Getting the binary onto a small Linux device
The supported platforms page lists Linux builds for 386, amd64, armv5, armv6, armv7, arm64, mips, mipsle, mips64, mips64le, ppc64, ppc64le, riscv64, s390x and loong64, each runtime-checked under QEMU. Those are the CPU families you find in Linux-based routers and small boards, including devices running OpenWrt. The page is direct about the limit: a device "still needs a working PTY and outbound HTTPS/WebSockets", and "Vendor firmware, kernel restrictions and storage can affect small Linux devices; QEMU checks do not cover those hardware differences." We do not publish a list of tested router models.
Storage is the constraint you will hit first. In the v0.25.0 release, shell-linux-mipsle is 9,765,057 bytes and shell-linux-armv7 is 8,585,378 bytes. They are static binaries, which is why they run without a matching libc, but many routers do not have that much free flash. On devices where /tmp is RAM-backed, installing there works for a maintenance session and disappears on reboot:
wget -qO- https://shell.online/install | SHELL_ONLINE_INSTALL_DIR=/tmp/bin sh
/tmp/bin/shell --version
The installer script is short enough to read before you pipe it to sh. It maps uname -m to a release asset (mips, mipsel, armv7l and so on), downloads with curl or wget, and refuses to install unless sha256sum or shasum verifies the checksum. If the device's wget lacks an option the script uses, download the matching shell-linux-<arch> asset and its .sha256 file from the release page and check them yourself.
What the link is, and what encryption hides
On a router, the wrapped process usually runs as root. The URL and password together are a bearer credential: anyone holding both can view, and unless the session is read-only, type with that process's permissions. Do not paste the QR code into a ticket screenshot, because it contains the password for one-scan access.
Terminal traffic is end-to-end encrypted by default. The passwords and encryption page describes how: the link's #salt= fragment carries a random salt, and the host and browser each derive an AES-256-GCM key with PBKDF2-HMAC-SHA256 at 600,000 iterations. URL fragments are not sent in HTTP requests, so the relay never gets the password. It does see timing, addresses, encrypted sizes, labels and lifecycle metadata, and it can delay or drop traffic. Ten random base64url characters give 60 bits; for anything long-lived, set a longer password with SHELL_ONLINE_E2EE_PASSWORD.
If a link escapes, shell password rotate <ID> changes the password, salt and cipher generation and disconnects current viewers while the process keeps running. It cannot take back output someone already saw.
What this does not fix
shell.online is not a RouterOS package, and RouterOS is not on the supported host list, which is macOS, Windows, Linux, the BSDs and Solaris. For MikroTik hardware, the fix is CERT Polska's: install a patched build, and take SSH, WebFig and the bandwidth-test server off untrusted networks.
It also does not protect a device that is already compromised. The security page says plainly that end-to-end encryption "does not protect against malicious code on either endpoint." If an attacker is on the router, they can read the terminal before it is encrypted. CERT Polska's indicators (a failed login for user -2 from an unknown address, an unexpected ops account in the full group) are what you would go and look for, ideally from a read-only session.
Removing the inbound port shrinks the attack surface. It does not remove the need to patch, and the share link becomes the credential you have to protect instead.
Finally, the view depends on the device keeping its outbound connection. The connection troubleshooting guide says a temporary network failure does not intentionally stop the process, the CLI and browser retry automatically, current hosts restore the screen when viewers return, and an ordinary disconnected share can recover its link for 12 hours. So if you change the interface the relay connection runs over, the command keeps running on the router and you lose only the view until the route comes back. If the change leaves the device with no route out at all, you need another way in, and that is a reason to keep a LAN-side console rather than a reason to reopen WAN SSH.
The same outbound-only reasoning is why Pilot Protocol connects agents behind NAT without a VPN, using STUN, hole punching and an encrypted relay as fallback instead of open ports. For a longer description of the shell.online model, see our introduction to the live terminal browser link.
A router shell with nothing listening on the WAN
Install the CLI on the device, run shell --read-only logread -f, and open the link from your phone. The process and its PTY stay on the router.
Try shell.online