
Editorial artwork generated using the official Flint 3e design as a reference.
On firmware 4.8.7, I could execute commands as root on my GL.iNet GL-BE6500 without logging in to the router. Network Storage had to be enabled, and the NAS service had to be reachable from the client. Under those conditions, an unauthenticated network request could reach code running with the highest privileges on the device.
That finding became CVE-2026-19983. Three other root RCE findings in authenticated management features also received CVEs, along with a WebDAV authorization bypass that allowed unauthenticated writes to private storage locations. This article covers those five public CVEs.
The work began with the router in my hands, its casing broken open, and access to the UART interface.
UART dropped me straight into a root shell
I obtained a GL-BE6500, also sold as the Flint 3e, and broke open its enclosure to reach UART. When I connected to the console, it dropped me straight into a root shell. That was my first major red flag.
From that shell, I ran ps aux to see which processes and services were running on the device and which user owned them. Every process shown in the listing was running as root. That was a second major red flag: the router's running software shared the same highly privileged execution account.
Seeing the services run as root made the consequence clear. A code-execution flaw in a network-facing process could immediately inherit system-wide privileges. The attacker would not need a separate privilege-escalation bug to reach that level of access. Configuration, stored credentials, firewall rules, and system services could all fall within the compromised process's authority.
Ordinary user activity and request handling should operate with the minimum privileges they need. Tasks that require root should be confined to narrowly scoped components. That separation can limit the damage when a parser, handler, or service is compromised.
With the root shell available through UART, I dumped the firmware and started analyzing it.
Having both the firmware and access to the running device made a difference. I could inspect the handlers and scripts behind the management interface, then check their behavior on the router. When a feature saved a setting, started a service, or changed a file, I could look at the resulting state directly.
That is how the investigation moved from the hardware to the network services. UART gave me visibility during the research. The NAS vulnerability itself was reachable over the network without a router login; it did not depend on someone opening the enclosure.

Observed impact and prerequisites from my GL-BE6500 tests. “Unauthenticated” still requires network access to the relevant enabled service.
Unauthenticated root RCE through Network Storage
CVE-2026-19983: authentication bypass chained with command injection
The most serious finding in my reports was in the NAS command service, gl_nas_sys. In my test, opening Network Storage in the router’s management interface started this service as root.
Its authentication logic made a consequential mistake. The service used the HTTP Host header to decide whether a request should be trusted as local and allowed past its token check. But that header comes from the client. A claim inside a request does not prove where the network connection originated.
The component was /usr/bin/gl_nas_sys. My report documented its authorization behavior through reverse engineering and control requests. The trust decision can be summarized as follows; this is explanatory pseudocode, not recovered source:
client_metadata = read_request_headers() access_decision = authorize(token, client_metadata) # Client-supplied metadata influenced the local-trust exception. # It did not establish the identity of the network peer.
A second weakness made the authentication bypass much more damaging. A file-handling operation incorporated filename data into shell commands without keeping that data separate from executable syntax. The service was already running as root. When the two weaknesses were combined, an unauthenticated client could cause commands to execute with those privileges.
This was remote code execution as root, with no router credentials required under the tested configuration. My report included authorization control checks and router-side execution markers, alongside the finding that the service ran as root.
The practical impact is control over the router’s operating system. Root privileges can allow an attacker to read configuration and stored secrets, change DNS and routing behavior, alter firewall rules, and modify services. Because the router controls where traffic goes, that access can affect the network behind it as well. These are consequences of the execution privilege; my proof established command execution using markers rather than carrying out those follow-on actions.
The exposure depended on the feature state and network configuration. Network Storage needed to be enabled, and the client needed to reach the NAS service. My tests established that conditional network attack surface; they did not establish that every router exposed it to the public internet by default.
Root RCE hidden in firewall cleanup
CVE-2026-19982: authenticated command injection
Another root-execution path appeared in firewall management. This one required an authenticated administrator session. The vulnerable code handled cleanup of connection-tracking state when firewall settings changed.
I followed the firewall settings beyond the initial request handler. The management API saved values that the cleanup code later reused in shell commands running as root. Some fields were validated, but that validation did not cover every value the cleanup code consumed.
The source excerpt in my report showed command text being assembled and then handed to the shell. This shortened excerpt retains that structure, with the command templates and arguments omitted:
cmd = string.format(...) cmd = cmd .. string.format(...) os.execute(cmd)
string.format does not make substituted values safe for a shell. The important boundary was the final os.execute(cmd) call: text assembled from stored configuration was interpreted as a command with the process's root privileges.
I documented the problem across port-forwarding, firewall-rule, and DMZ workflows. The failure was delayed: accepting and storing a value could happen before a later operation consumed it as command text. Reviewing only the initial save handler would miss that relationship.
The result was arbitrary command execution as root through an authenticated management interface. An administrator session was the starting requirement, but the affected operation was supposed to manage firewall state. The injection allowed execution outside that operation, with the privileges of the underlying system process.
This was why I had to follow a setting through its later uses. A value that looked like stored configuration at one point became executable input at another.
A WiFi power schedule that could execute as root
CVE-2026-19981: authenticated RCE through generated cron tasks
The Wi-Fi timer was meant to schedule changes to wireless transmit power. Its power-level settings should have been restricted to the small set of choices supported by the feature. The backend did not consistently enforce that restriction before saving them.
Those settings were later incorporated into cron entries. Cron was not simply storing a preference: it would execute the generated task as root. Insufficiently constrained configuration could therefore change the executable task produced by the scheduler.
My report's code reference was the Wi-Fi timer's cron-generation logic. The following pseudocode summarizes that flow without reproducing the full task template:
power_setting = read_saved_configuration() job_text = format_scheduled_task(power_setting) write_privileged_schedule(job_text)
The security check had to happen before a saved value became part of job_text. Treating a value as a setting when it was stored did not keep it from becoming executable text later.
With an administrator session and the timer enabled, I confirmed root command execution and recorded the resulting markers. The consequence was broader than an incorrect power setting or a broken schedule. Input to a wireless-management feature could become a privileged operating-system task.
The interface’s restricted list of power levels did not protect the backend. The allowed values needed to be enforced where the setting was accepted and retained when the scheduled task was generated.
Root RCE in the language update scheduler
CVE-2026-19980: authenticated injection into root cron tasks
The language-update scheduler exposed a similar problem through a different feature. Its handler checked that scheduling fields existed when scheduling was enabled, but did not adequately validate them as time values before saving them.
These two lines from the report show the persistence step:
c:set("gl_timer", "langs", "hour", hour) c:set("gl_timer", "langs", "min", min)
The setters stored the supplied values. They did not establish that those values were valid numeric times. That guarantee needed to come from validation before storage and remain true when the scheduler consumed them.
The saved values were used to generate root cron entries. A field intended to describe when an update should run could influence the executable content of the resulting task. My tests confirmed root execution through this path, with an authenticated administrator session and scheduling enabled.
The result was remote code execution as root through the language-update settings. Together, the two scheduler findings showed the same failure in different features: configuration reached a privileged job without the validation needed to keep it from changing what that job executed.
WebDAV could overwrite private files without a login
CVE-2026-19979: unauthenticated destination authorization bypass
The WebDAV issue crossed a file-permission boundary. With WebDAV enabled and a public read-write share configured, an unauthenticated client could affect private sibling files within the WebDAV storage namespace.
The service checked permission for the source of a COPY or MOVE operation. It did not apply an equivalent permission check to the destination. Access to a public source could therefore be used to make the service act on a private destination.
My reverse-engineering notes traced this behavior in /usr/bin/webdav_ser. The destination-handling path eventually reached the following filesystem operation, shown here as the normalized call recorded in the report:
rename(source_path, destination_path);
The call itself was not the authorization mechanism. The service had to establish permission to affect both paths before reaching it. Checking the source alone left the destination write outside the intended access control.
The control checks were important here. Direct unauthenticated access to the private locations was denied. Router-side verification nevertheless showed that the affected operations could create files there and overwrite existing files. The private boundary existed in the direct-access path, but was not enforced consistently across operations.
The confirmed impact was unauthorized creation and overwrite of private files, without authentication, within the exposed storage namespace. For a user relying on the separation between public and private shares, that means private content could be altered or destroyed by someone who could reach the service. This finding established a storage-integrity failure; the four preceding findings established root RCE.
An operation involving two paths needs permission checks for both. The destination must be resolved and authorized before any write or replacement takes place.
What root execution means in these findings
Four of the five CVE-linked findings let me execute commands as root. The NAS chain reached that result without authentication once the service was enabled and reachable. Firewall cleanup and the two schedulers reached it from authenticated administrator workflows.
For the authenticated findings, a compromised administrator session could be used to run operating-system commands as root through the affected features. For NAS, reaching the enabled service was enough. That difference in access is substantial, even though the execution privilege at the end was the same.
My original NAS report assessed the enabled-and-reachable service scenario as Critical. The table below lists the CVSS v3.1 ratings published by the assigning authority.
| CVE | CVSS v3.1 |
|---|---|
| CVE-2026-19983 | 8.3 High |
| CVE-2026-19982 | 7.4 High |
| CVE-2026-19981 | 7.4 High |
| CVE-2026-19980 | 7.4 High |
| CVE-2026-19979 | 8.3 High |
Reporting the findings and testing the fix
I documented the findings in two reports dated June 15, 2026. In the June 17–18 correspondence, GL.iNet discussed the confirmed findings and its plan to provide temporary firmware for verification, followed by CVE applications where applicable.
On June 25, the security team sent an interim GL-BE6500 firmware package and said it had completed the fixes. I flashed that build and reran the original proof-of-concept tests. The reported issues no longer reproduced, and I sent that result back to the team. GL.iNet then confirmed it would proceed with the CVE applications.
The five public CVE records were published on August 17. The vendor emailed confirmation of the NAS CVE on August 18 and confirmed the other four IDs in a subsequent undated message in the correspondence.
Following a setting all the way through
The investigation started with physical access, but the most consequential result was a network path to root without authentication. The firmware dump made it possible to understand how the router’s services reached that state and to connect the behavior on the device with the code behind it.
The root shell on UART was the first warning sign. Seeing every process in the ps aux listing running as root was the second. The later findings showed why privilege boundaries mattered: vulnerable services and generated tasks were already operating with enough authority to compromise the router's operating system. Restricting those privileges would not replace input validation or authorization, but it could reduce what an attacker inherits when either fails.
The recurring problem was the distance between accepting a setting and using it. Firewall cleanup reused saved values. Schedulers converted configuration into executable jobs. The NAS and WebDAV services made authorization decisions without checking the property or resource that actually needed protection.
Following those values and decisions through to their final use led to five public CVEs, including four for root RCE, and a tested interim fix. I appreciate the GL.iNet security team’s work reviewing the reports and providing the patched firmware for verification.