CVE-2026-35385: dropbear scp, OpenWrt 24.10.7 to 24.10.8
OpenWrt 24.10.8 takes six fixes of Dropbear 2026.90
(OpenWrt commit 262c093).
Four are in scp, which OpenWrt builds into the same binary as the
server:
- CVE-2026-35385:
scpkept the setuid and setgid bits of the files it received, so a server could plant a setuid program. The fix, from OpenSSH, clears them. - The rest of the CVE-2019-6111 fix: names a server sends must match the pattern asked for, with braces expanded.
-rinto a directory that exists is refused.
The other two are in the server: an authenticated user could bypass the
command= option of authorized_keys where the server runs with -t,
and authorized_keys is now opened without blocking. Neither has a CVE.
OpenWrt runs sstrip on what it ships, so only the segments of the file
are left. On MIPS, Dropbear is MIPS32.
Get the binaries
$ for v in 24.10.7 24.10.8; do
mkdir -p $v
curl -s https://downloads.openwrt.org/releases/$v/targets/armsr/armv8/openwrt-$v-armsr-armv8-rootfs.cpio.gz \
| gunzip | (cd $v && cpio -id usr/sbin/dropbear)
done
Compare
$ hereticus --format markdown 24.10.7/usr/sbin/dropbear 24.10.8/usr/sbin/dropbear
| FUNCTION | CHANGE | SCORE | +/-/~ | TOUCHED | MATCHED BY |
|---|---|---|---|---|---|
sub_1650c -> sub_1623c | changed | 0.69 | 369/64/14 | 63 branch, 40 call, 1 callee, 31 jump, 63 mem, 4 text | similar |
sub_1a5cc -> sub_1a83c | changed | 0.94 | 75/58/19 | 12 branch, 16 call, 1 callee, 6 jump, 43 mem, 2 const | similar |
sub_3d08 -> sub_3d88 | changed | 0.99 | 21/4/4 | 2 branch, 2 call, 1 jump, 9 mem, 2 const, 1 text | similar |
sub_105a4 -> sub_10128 | changed | 0.99 | 6/9/0 | 2 mem, 1 const | similar |
sub_13ec8 -> sub_13530 | changed | 0.80 | 5/1/0 | 2 call, 2 mem | similar |
sub_12144 -> sub_11b90 | changed | 0.94 | 4/5/1 | 1 call, 4 mem | similar |
sub_13dfc -> sub_134a8 | changed | 0.46 | 3/22/3 | 2 branch, 1 call, 2 jump, 11 mem | same callers |
sub_11bec -> sub_13594 | changed | 0.97 | 3/4/2 | 1 mem | similar |
sub_17dc0 -> sub_18028 | changed | 0.98 | 3/0/0 | 1 branch, 1 mem | similar |
sub_1d2a8 -> sub_1d83c | changed | 0.99 | 3/3/3 | 2 const | similar |
sub_23f3c -> sub_245c8 | changed | 1.00 | 3/3/1 | 2 mem | similar |
sub_1cea8 -> sub_1d440 | changed | 1.00 | 3/4/3 | 2 const | similar |
sub_1cbb0 -> sub_1cb48 | changed | 0.96 | 1/0/0 | - | similar |
sub_10c70 -> sub_107e8 | changed | 0.97 | 1/2/0 | 2 mem | similar |
sub_22ad4 -> sub_23160 | changed | 0.99 | 1/1/1 | - | similar |
sub_8200 -> sub_82d0 | changed | 0.78 | 0/0/1 | - | similar |
sub_1d8e4 -> sub_1de78 | changed | 0.98 | 0/0/1 | - | similar |
sub_c40c -> sub_c4dc | changed values | 1.00 | - | 1 text | identical shape |
sub_10bc8: new
419 matched (399 unchanged, 20 changed), 0 gone, 1 new
The texts each function points at name the first rows:
| Row | Function | Texts |
|---|---|---|
sub_1650c | sink of scp | "mtime.sec not delimited", and new "filename does not match request" |
sub_1a5cc | the authentication of the server | "unknown service in auth" |
sub_3d08 | the options of the server | "Bad maxauthtries '%s'" |
sub_105a4 | the progress meter of scp | " %3d%% " |
The fix is on row 1: GCC inlined the new pattern matching and brace
expansion into sink, which took 369 instructions.
Read the fix
$ hereticus --view il --diff sub_1650c 24.10.7/usr/sbin/dropbear 24.10.8/usr/sbin/dropbear
...
x21 = load.64 [@umask]
...
call exit
+ w0 = w0 | 0xe00
+ store.32 [sp + 0x90] = w0
+ call x21
...
x21 holds the address of umask. 0xe00 is 07000, the setuid,
setgid and sticky bits: sink now adds them to the mask of the process,
so no file it creates keeps them.
The other architectures
| Build | Rows | Row of the fix |
|---|---|---|
armsr/armv8, AArch64 | 19 | 1 |
armsr/armv7, A32 | 21 | 1 |
malta/be, MIPS32 big endian | 16 | 1 |
malta/le, MIPS32 little endian | 28 | 1 |
In 24.10.8 the linker gave some static objects a slot of the global
offset table of their own, where 24.10.7 loaded the slot of the page and
added the low half. That added half no longer reads as an edit
(RESEARCH.md, “Two ways MIPS loads an address”); before, it put 18
more rows in the report for MIPS32 little endian, and the fix on row 2.
hereticus-cli/tests/truth_cves.rs locks these ranks, and
fixtures/cve_binaries.py fetches and pins the binaries.