Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

CVE-2026-30873: jsonfilter, OpenWrt 24.10.5 to 24.10.6

OpenWrt 24.10.6 adds one patch to jsonfilter, the fix of CVE-2026-30873, which Trail of Bits found (TOB-OWRT-3) (OpenWrt commit 77d54cc):

  • jp_get_token reads one token of a JSONPath expression into an operation on its stack. match_token copies the text of a string, a label or a regular expression into it with strdup, and jp_alloc_op copies it again, so each such token leaked its first copy. The fix frees it (jsonpath commit e086664).

The version of the package stays 2025.04.18~8a86fb78. OpenWrt runs sstrip on what it ships, so only the segments of the file are left.

Get the binaries

$ for v in 24.10.5 24.10.6; 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/bin/jsonfilter)
  done

Compare

$ hereticus --format markdown 24.10.5/usr/bin/jsonfilter 24.10.6/usr/bin/jsonfilter
FUNCTIONCHANGESCORE+/-/~TOUCHEDMATCHED BY
sub_402c48changed0.925/0/01 branch, 1 callsimilar

86 matched (85 unchanged, 1 changed), 0 gone, 0 new

The one row is the fix. GCC inlined jp_get_token into the function that parses an expression.

Read the fix

$ hereticus --view il --diff sub_402c48 24.10.5/usr/bin/jsonfilter 24.10.6/usr/bin/jsonfilter
...
  w2 = load.32 [sp + 0x68]
  x4 = 0
  call sub_402274
+ x19 = x0
+ x0 = load.64 [sp + 0x60]
+ if (x0 == 0) goto $-0x88
+ call free
...

sub_402274 is jp_alloc_op, and [sp + 0x60] is the str field of the operation on the stack. The lines read as the C of the fix:

-	return jp_alloc_op(s, op.type, op.num, op.str, NULL);
+	newop = jp_alloc_op(s, op.type, op.num, op.str, NULL);
+	/* match_token might alloced str using strdup() */
+	if (op.str)
+		free(op.str);
+
+	return newop;

The other architectures

BuildRowsRow of the fix
armsr/armv8, AArch6411
armsr/armv7, A3241
malta/be, MIPS16e big endian11
malta/le, MIPS16e little endian11

On malta, jsonfilter is a MIPS16e executable that is not PIC, and calls each import through a MIPS16e PLT stub that GNU ld puts after .fini. hereticus names each stub by the slot it jumps through, so the call of the fix reads call free.

hereticus-cli/tests/truth_cves.rs locks these ranks, and fixtures/cve_binaries.py fetches and pins the binaries.