Author: dwolven

  • News Roundup: October 22–November 2, 2026

    A few things worth your attention from the past week and a half:

    Multipath TCP flagged as a remote-code-execution risk on Linux — and Go enables it by default. The Go security team warned on October 29 that Go’s networking stack turns on multipath TCP (MPTCP) automatically, which combines with a kernel-side bug to open a remote-code-execution path on affected Linux systems. A lot of self-hosted tooling is written in Go, so if you’re running Go-based services, check whether a kernel fix has reached your distro yet, and consider disabling MPTCP as a stopgap in the meantime. Source

    MikroTik ships RouterOS 7.25 stable. The “important security update” MikroTik flagged in the 7.25 beta a few weeks back — without saying what it fixed, as usual — has now landed in the October 22 stable release. It also brings dynamic ARP inspection and IP source guard on bridges, a new BGP always-compare-med option, and a fix for fragmented IPv6 traffic getting dropped by DHCPv6 snooping. Worth updating sooner rather than later given the undisclosed fix. Source

    nginx 1.31.8 (mainline) released. A small follow-up to the October 14 security release: fixes an HTTP/3 undefined-behavior bug and some working_directory handling issues. No new CVEs this round. Source

    Linux 7.4 merge window closes as an unusually large cycle — and it’s expected to be the next LTS. Torvalds called it a genuinely “big” merge window: nearly 20,000 commits landed, versus the more typical ~15,000. If you’re the type who picks a kernel version to standardize a fleet on, 7.4 is one to keep an eye on. Source

    KeePassXC 2.8.0 released, after a month of beta testing. The password manager finally moved its UI from Qt5 to Qt6, auto-type now works under Wayland via XDG desktop portals, and there’s a new option to import a database straight from a remote host over SFTP/SCP. If a shaky KeePassXC experience was the last thing keeping you on an Xorg session, this removes some of the excuse. Source

    Critical auth bypass in Avada/Fusion Builder (CVE-2026-97670, CVSS 9.1). An unauthenticated attacker can trigger arbitrary WordPress action hooks through a form-notification code path on any site with a published Avada form — one disclosed test request permanently deleted trashed posts, pages, and comments. Fixed in Avada 7.16.2; update now if you’re running the Avada theme or Fusion Builder. Source

    Authentication bypass in the LatePoint booking plugin (CVE-2026-110653, CVSS 9.1). A race condition in the one-time-passcode attempt counter lets an attacker bypass authentication entirely, no credentials needed. Fixed past version 5.7.4 — patch it if you use LatePoint for appointment scheduling on a self-hosted site. Source

  • Bills 36, Ravens 10: Hard to Grade a Win Over a Third-String QB

    The Bills came off the bye, beat Baltimore 36-10 at home, and are 6-1. A 26-point win over the Ravens should feel bigger than this one does, and the reason it doesn’t is who was playing quarterback for Baltimore for most of the afternoon.

    Lamar Jackson was coming back from a three-game absence and threw exactly one pass. He hurt his throwing thumb on it and didn’t return, and the Ravens have since said he needs surgery and is headed to injured reserve. I don’t root for that, even against a team that has given Buffalo as much trouble as Baltimore has. Tyler Huntley took over, then left in the second quarter with a toe injury. That left Joe Fagnano, an undrafted rookie who had never taken an NFL snap, to play the rest of the game.

    From there it went about how you’d expect. Fagnano was 10-of-21 for 91 yards with an interception, and late in the fourth quarter he fumbled an aborted snap that Buffalo recovered. Baltimore finished with 144 total yards and 91 passing yards. The Bills sacked Ravens quarterbacks four times and forced three turnovers, including a Cole Bishop strip-sack of Huntley early in the second quarter that set up a field goal.

    So here’s the context check. The Ravens came in averaging about 24 points and 366 yards a game, which sounds like a tough offense, and Lamar was a big part of that. In the three games Huntley started before this one, they scored 30, 10 and 13. Ten points against Buffalo with a third-stringer under center is right in line with that. Meanwhile, the Bills defense had been giving up 28.5 points a game before the bye. One afternoon against a rookie making his debut doesn’t tell me that problem is fixed.

    Allen was good without needing to be great. He went 21-of-34 for 289 yards, threw touchdowns to DJ Moore and Dalton Kincaid, and ran one in from a yard out on the opening drive. Kincaid had 86 receiving yards and looked like the most dangerous guy on the field for stretches. James Cook ground out 80 yards on 21 carries and scored from 5 yards out in the third quarter.

    The part that bugged me was the first half. Buffalo led only 16-7 at halftime against a team that couldn’t throw the ball, and a lot of that was self-inflicted. Allen threw an interception at his own 17 that handed the Ravens their only touchdown. Moore fumbled at the Baltimore 18 a couple of minutes before the half. Tyler Bass kicked three field goals, which is great for Bass (he hit from 56 and 51) and less great for an offense that kept stalling. The Bills also had ten penalties for 87 yards. Against Baltimore with Lamar, those mistakes probably lose you the game.

    Once Cook’s touchdown made it 23-10 midway through the third quarter, it was over. Allen added the two touchdown passes in the fourth, and the defense kept a rookie with no help in check the rest of the way.

    This is a win the Bills were supposed to get, and they got it comfortably once the second half started. It just doesn’t tell me much. Next Monday night is the one that will: a trip to Minnesota to face a 6-1 Vikings team whose defense had been allowing about 12 points a game before the Lions put 19 on them Sunday. If the offense stalls in the red zone up there the way it did in the first half here, field goals won’t be enough. After that it’s the Jets on the road. Speaking as a Lions fan too, I already enjoyed watching the Vikings lose once this week, and I’d happily do it again.

  • Lions 19, Vikings 15: Gibbs Runs Through the Best Defense in the Division

    Last week I said I wanted to see a clean game before I’d believe the Lions were ready for a team as good as Minnesota. I didn’t get a clean game. I got a win anyway. Detroit beat the Vikings 19-15 at Ford Field, handed them their first loss of the season, and moved to 5-2.

    This one was won on the ground. The Lions ran for 230 yards on 39 carries against a defense that had been giving up about 12 points a game. Gibbs had 153 yards on 23 carries, including a 30-yard touchdown straight up the middle in the third quarter, and Sione Vaki chipped in 65 more. I’ve spent most of this season watching Goff and the receivers carry the offense, so it was strange and kind of great to watch Detroit just line up and push a good defense around.

    The go-ahead drive was the best stretch of the day. Minnesota had just taken a 15-12 lead with under nine minutes left, and the Lions answered by going 69 yards in seven plays, five of them runs. Goff finished it with a 7-yard touchdown to Jameson Williams, and the Vikings never got close again. After Minnesota punted with three minutes to go, Gibbs ripped off runs of 14 and 8 yards, the Vikings burned all three timeouts trying to stop the clock, and Goff took two knees.

    The passing game was quiet. Goff went 18-of-25 for 176 yards with a touchdown and an interception, and he got sacked four times. Minnesota’s front is a big reason they started 6-0, and it showed whenever the Lions got into obvious passing downs. Leaning on the run made a lot of sense against this group.

    It could have been more comfortable. Amon-Ra St. Brown and Williams both drew taunting flags in the first quarter, and the one on Williams pushed the Lions back 15 yards on a drive that ended in a field goal. Penei Sewell was flagged for two false starts and a hold. Detroit finished with seven penalties for 76 yards. They also missed the two-point try after the Gibbs touchdown, which is why Minnesota’s touchdown and two-point conversion in the fourth quarter put the Vikings ahead instead of just tying it. Against this opponent, all of those small things mattered.

    Now the usual check on the defense. Minnesota came in averaging about 21 points and 282 yards a game. They got 15 points and 266 yards. That’s a little under their normal, which is fine, though the Vikings offense was never the scary part of that team. Kyler Murray went 17-of-29 for 210 yards and two touchdowns, and the one real breakdown was a 51-yard completion to Jordan Addison that set up their go-ahead score. D.J. Reed had an interception late in the first half, and the defense got a fourth-down stop at the Detroit 25 early in the fourth quarter. That makes three straight weeks of holding an offense to roughly its usual output. I’ll call that steady and leave it there until they do it against an offense that can actually hurt them.

    The bigger takeaway is the run game. Minnesota’s defense had been the best unit in the division, and the Lions ran on it for four quarters. If that holds up, this offense gets a lot harder to deal with, because teams can’t sit back and only worry about St. Brown and Williams anymore.

    Detroit is 5-2, a game behind the 6-1 Vikings, with the head-to-head win in hand for now. Next up is a trip to Miami, which is 1-6, and then New England at home. The Lions should win both, and this is also the kind of stretch where they’ve let teams hang around this year. I’d like to see them put one away early for a change.

  • Lions 20, Packers 17: Saved by a Blocked Kick

    I’ll take a win over Green Bay any way it comes, and this one came about as ugly as it gets. Jake Bates hit a 22-yarder with one second left, the Lions beat the Packers 20-17, and Detroit is 4-2 with its first division win. Most of the afternoon was spent making that harder than it needed to be.

    The giveaways were mostly self-inflicted. Up 10-7 late in the second quarter with the ball at the Green Bay 12, Gibbs coughed it up and the Packers recovered at their own 8. Then early in the third quarter, Goff botched a snap at his own 41 and Green Bay fell on it. A couple of minutes later Jordan Love found Josh Jacobs for a 25-yard touchdown and the Packers were ahead 14-10. That’s two fumbles in a game where Detroit outgained Green Bay 415 to 324, and it turned what should have been a comfortable afternoon into a coin flip.

    Then there was the fourth-down call. Tied at 17 with just under five minutes left, Dan Campbell went for it on fourth-and-1 from his own 24. Gibbs got stuffed for a loss of two, and Green Bay took over at the Detroit 22. I like that Campbell trusts his offense, and I usually defend these calls. This one I’d have punted. The defense held the Packers to five yards on three plays, and D.J. Wonnum blocked the 35-yard field goal that would have put Green Bay up three. That block saved the game, and it probably saved a week of arguing about the call.

    The last drive was the Lions at their best. A roughing the passer flag on a LaPorta catch moved the ball into Green Bay territory, and after that it was mostly Gibbs running right at them while the Packers burned all three timeouts. Goff took a knee to drain the clock and Bates did the rest. Gibbs finished with 116 yards on 29 carries. The team only averaged 3.6 yards a carry, so it wasn’t pretty, but he was the reason they could close it out on the ground.

    The passing game carried everything before that. Goff was 22-of-32 for 303 yards and two touchdowns, both to Jameson Williams. Amon-Ra St. Brown caught nine balls for 153 yards and looked like the best player on the field for long stretches. When this offense isn’t handing the ball to the other team, it moves it on anybody.

    Now the defense, since two weeks ago I told everyone not to get carried away. Holding Green Bay to 17 points and 324 yards sounds like progress, and against what Detroit had been allowing (just over 400 yards and almost 30 points a game coming in) it is. But check it against Green Bay’s own numbers. The Packers came in averaging about 21 points and 329 yards a game. They got almost exactly their normal yardage, and a few points less than normal with a blocked kick helping out. Love threw 45 times for 274 yards, which is a lot of work for 6.1 yards an attempt, and Brian Branch picked him off to open the fourth quarter. The run defense held Green Bay to 60 yards, though the Packers are under three yards a carry for the season, so that’s less impressive than it looks.

    So that’s two straight games of the defense holding an offense to roughly what it usually does. That’s better than the first month, when opponents were moving the ball at will. It’s still a long way from a unit you’d lean on to win a game.

    And here comes the team that will test that. Minnesota is 6-0 and comes to Ford Field on Sunday giving up about 12 points a game. Their offense isn’t scaring anyone, but their defense is the kind that turns two lost fumbles into a loss. Against Green Bay the Lions could survive their own mistakes. Against the Vikings I don’t think they get that luxury, and I’d like to see a clean game before I believe they’re ready for a team that good.

  • Lions 45, Cardinals 21: Let’s Not Crown the Defense Yet

    A 24-point road win is a good day, and I’ll happily take 3-2. But the week of chatter about Kelvin Sheppard’s defense “answering the critics” doesn’t hold up when you look at who they played.

    Some context first. Going into Sunday, the Lions were giving up 31.8 points and nearly 424 yards a game, among the worst numbers in the league. Sheppard spent the week saying talk was cheap and he needed to see real change on the field, and called the outside criticism poison. So when the defense held Arizona to 21, the takes wrote themselves.

    Here’s my problem with that. Arizona came into this game averaging just under 22 points a game (26, 7, 30 and 24 in their first four). They scored 21. And one of those touchdowns came with 2:17 left in a game that was long over.

    The yardage looks like progress until you check it against the right number. The 327 yards Arizona put up is about 100 fewer than Detroit had been allowing, but that 424 average came against New Orleans, Buffalo, the Jets and Carolina. Arizona’s own offense had been averaging about 295 yards a game (393, 151, 365 and 270). Against the Lions it gained more than that. A middle-of-the-pack offense with Jacoby Brissett at quarterback had a slightly better than normal day against a defense that had been getting carved up for a month. That’s what you’d expect.

    The pass rush did its thing: five sacks, 12 QB hits, and a fourth-and-one sack from Hutchinson and Malcolm Rodriguez late. There was also an interception to end the first half. But the front has been the one part of this defense that’s worked all year. Detroit came in second in the league in pressures, with Hutchinson second among individual players. Hutchinson and company are very good. The problem has never been talent up front; it’s a unit that doesn’t play coordinated, where pressure up front doesn’t connect to anything behind it. Sheppard more or less said the same thing about the back end last week. Brissett still threw 48 times for three touchdowns, and plenty of that was Arizona playing from way behind.

    The offense is the real story again. After going down 7-0, Detroit scored 24 in the second quarter and never looked back. Goff was 19-of-30 with three touchdowns and no picks, Jameson Williams caught two of them including a 39-yarder, LaPorta took one 38 yards, and the run game put up 163 yards and three scores. That’s the formula: score enough that the defense only has to be average.

    Average won’t cut it for what’s next, though. After the bye it’s Green Bay at home and then a Minnesota team that’s 5-0. Detroit is 3-2 and sitting last in the division on tiebreakers. Holding a 1-4 team to its usual output is fine. Doing it against the Packers and Vikings would actually mean something.

    So, good win, good offensive day, and a defense that was fine. I’ll be more convinced when “fine” shows up against someone in the NFC North.

  • News Roundup: October 5 – 12, 2026

    A lighter week on the usual beats (no fresh Proxmox, nginx, WordPress, or Ubuntu news worth flagging beyond what’s already in last week’s roundup), but a solid OpenSSH release and a Home Assistant update make up for it.

    OpenSSH 10.6: compression side-channel mitigation, post-quantum signatures, tighter SFTP
    Released October 6. The LZ77 dictionary coder is now disabled by default in ssh/sshd to close a compression-based side-channel, so don’t be surprised if SSH compression feels less effective afterward. The project suggests handling compression at the application layer instead if you need it. Also notable: the hybrid ssh-mldsa44-ed25519 post-quantum signature algorithm is enabled, a new WarnWeakCrypto option logs connections using non-PQ-safe key exchange, SFTP gets stricter path validation against malicious servers, and usernames passed on the command line can no longer contain $ or \. Worth the upgrade on anything facing the internet. Release notes.

    Home Assistant 2026.10: map card rebuilt on OpenStreetMap, trigger IDs get a UI
    Out October 7. The map card was rebuilt on OpenStreetMap vector tiles via a new “Map tiles” integration, after the previous provider’s API-key requirement broke maps for a lot of installs last release. Dark mode is included, with older devices falling back to the classic map. Automations with multiple triggers are easier to manage now that trigger IDs have a proper UI, and there’s a one-click toggle for AI integrations if you’re into that. Also worth knowing: Nabu Casa plans to rename Home Assistant Cloud to Home Assistant Link in the December release, features unchanged. Full changelog.

    LWN: the LAVD scheduler’s path from gaming hack to general-purpose sched_ext scheduler
    From this week’s LWN Weekly Edition, a Kernel Recipes 2026 writeup on LAVD, a sched_ext-based CPU scheduler that started as a latency tweak for gaming workloads and has since grown into something usable more broadly. If you’re running Proxmox or any other box where scheduler latency under mixed VM/container load matters, it’s a useful look at where sched_ext is heading as an alternative to CFS/EEVDF. LWN Weekly Edition, October 8 (full article behind the subscriber paywall for non-subscribers until it ages out).

    MikroTik RouterOS 7.26beta1: per-VLAN DHCP snooping, initial centralized management
    A development-channel build dated October 1. It’s not stable, so don’t put it on production gear yet, but it’s worth watching. Highlights include per-VLAN DHCP snooping on bridges, a fix for loop-protect when a VLAN interface joins a bridge, tighter ECDSA/EdDSA certificate validation, DHCPv6 server fixes, DoH stability improvements, and an early version of a centralized platform for monitoring and alerting across RouterOS devices. Forum announcement.

  • A Small Conscience for the Machine

    A Small Conscience for the Machine

    The agent I’ve been building talks to customers on phone and chat and takes real actions on their behalf: reboot a device, open a ticket, reschedule a dispatch, run a speed test. It’s barred from one thing: changing contact info on the account. That goes through the self-service portal, not the model.

    The problem

    Each turn produces two outputs: the reply text, and a log of what actions were attempted and whether they succeeded. Nothing keeps them in sync. The model generates the next plausible line of dialogue without checking the log first. “I’ve opened a ticket for you” is a plausible thing to say whether or not the ticket actually got created.

    This showed up in the first few turns after a new action tool was wired in, not after an extended testing phase. The agent claimed success on an action the log showed had failed to fire.

    Example

    Customer asks to move an appointment. The scheduling action fails, timeout or a silent step failure. The model still says “you’re all set, moved to next week,” because that’s the plausible reply to that request. The customer hangs up believing it’s done. Nobody shows up to the old slot, and the next contact is a missed-appointment notice for an appointment the agent said it had already moved.

    Why voice makes it worse

    There’s no slack in a phone call for a pause while something double-checks itself; a pause reads as broken and people talk over it or hang up. A false claim that’s merely annoying in a chat window becomes something a person hears in a confident voice and believes outright.

    The fix

    A pass runs on the reply text after generation, before the customer sees it:

    • Scan for language claiming a concrete action completed: ticket opened, appointment moved, reboot sent, speed test run.
    • Check each claim against the action log for that turn. Strip any claim without a matching success.
    • If the customer explicitly asked to change contact info, redirect to the portal link instead of a vague reply that reads as a yes.
    • If stripping leaves nothing useful, fall back to a plain line: can help with that, don’t have it available right now.
    • Log every strip. A repeated pattern on one action shows up later instead of staying buried in a transcript.

    Where that leaves things

    A narrow filter for one kind of confident overreach, not a smarter model. Its only job is making sure the agent doesn’t say “done” unless the log agrees.

  • News Roundup: September 28 – October 5, 2026

    A quiet week for most of the usual beats — no Proxmox, MikroTik, InfluxDB, WordPress, or Home Assistant news worth flagging — but LWN’s Kernel Recipes coverage and a fresh kernel/Ubuntu security batch are worth your time.

    Kernel security team’s message on the LLM bug-report flood: don’t panic

    At Kernel Recipes 2026, Greg Kroah-Hartman talked about how the kernel’s security team is coping with a sharp rise in vulnerability reports, many generated with LLM assistance. The real problem isn’t a lack of competent reports — it’s duplicate reports of the same issue arriving from different groups before a fix can even be merged, which makes coordinated disclosure harder than it used to be. March alone saw over 6,200 new CVE numbers issued across all software, 171 of them for the kernel.
    Coping with the onslaught of kernel security bugs (LWN)

    PostgreSQL’s Andres Freund on where the kernel still gets in the way

    Also from Kernel Recipes: a rundown from the Postgres performance maintainer on rough edges between the kernel and database workloads — fsync semantics, I/O, and memory management among them. Relevant reading if you’re running Postgres (or anything else I/O-heavy) in a VM or container on your own hardware rather than someone else’s managed instance.
    The kernel from a PostgreSQL point of view (LWN)

    Can C ever be made memory-safe?

    Martin Uecker’s Kernel Recipes talk, also covered by LWN this week, splits “memory safety” into type, spatial, and temporal safety, and looks at what upcoming C2y features (bounds-checking interfaces, “demon removal” of undefined behavior) actually buy you. Short version: incremental progress, not a Rust-style rewrite of the problem.
    Reducing undefined behavior in the C language (LWN)

    Seven new stable kernels: 7.2.9, 6.18.55, 6.12.112, 6.6.158, 6.1.189, 5.15.222, 5.10.271

    Greg Kroah-Hartman pushed the usual pile of fixes across every supported branch on October 3. No single headline bug this round — just the usual accumulated backlog — but if you’re tracking any of these branches on Proxmox hosts, NAS boxes, or bare metal, it’s worth pulling sooner rather than later.
    Seven stable kernels for Saturday (LWN)

    Ubuntu’s early-October security batch: OpenSSL plus a stack of kernel variants

    Several USNs landed in the first days of October, including an OpenSSL fix and kernel updates across the generic, GKE, FIPS, and Raspberry Pi variants. Nothing dramatic individually, but it’s a reboot-required batch, so worth a maintenance window on your Ubuntu boxes this week.
    Ubuntu security notices

  • Forking Net::Radius::Packet for mid-session CoA against a CGNAT-enabled BNG

    Forking Net::Radius::Packet for mid-session CoA against a CGNAT-enabled BNG

    A while back I forked Net::Radius::Packet into its own module for a project called radiusNE, instead of subclassing it or patching it in place. I hadn’t looked at the diff in long enough that I’d genuinely forgotten what was in it, so this post is as much me rediscovering my own code as it is writing it up.

    The actual reason for the fork

    The project sits in front of a CGNAT-enabled BNG platform, managing IPoE subscriber sessions. The specific thing I needed to do was alter a session already in progress, mid-flight, without the subscriber reconnecting: flipping a captive portal on or off for a given session being the clearest example. That’s not something a normal Access-Request/Access-Accept exchange handles, because that exchange only fires when a session is being established. Changing something on a session that’s already up means originating a CoA-Request (or a Disconnect-Request, if the goal is to kick the session entirely) from the RADIUS side and sending it to the NAS.

    Net::Radius::Packet can decode CoA and Disconnect packets fine, and it can respond to requests it receives, but building one to send in the first place is a different problem, and it’s where the fork actually starts.

    CoA and Disconnect have their own authenticator rules

    A normal Access-Request authenticator is 16 random bytes the client picks. A response authenticator is computed from the request. CoA-Request and Disconnect-Request follow neither pattern: RFC 5176 has them use the same scheme as Accounting-Request from RFC 2866. Pack the whole packet with 16 zero bytes standing in for the authenticator, MD5 that against the shared secret, then splice the digest into the authenticator field before sending. Order matters here. The digest has to be computed over the packet as if the authenticator were still zero, not over the final packet with a placeholder already swapped in.

    The fork adds a dedicated pack_coa() that does exactly this, along with paired accessors for the authenticator value so it can be stashed and retrieved cleanly instead of getting tangled up with the request/response authenticator the base module already manages:

    sub set_authenticator_coa {
        my $authenticator_placeholder = "\x00" x 16;
    }
    
    sub get_authenticator_coa {
        my ($self) = @_;
        return exists $self->{AuthenticatorCOA} ? $self->{AuthenticatorCOA} : ("\x00" x 16)
    }

    and the packing itself:

    my $authenticator_placeholder = $self->get_authenticator_coa();
    my $packet_header = pack($p_hdr, $codes{$self->code}, $self->identifier,
        $total_packet_length, $authenticator_placeholder);
    my $packet_before_authenticator = $packet_header . $attstr;
    my $authenticator = Digest::MD5::md5($packet_before_authenticator . $shared_secret);
    substr($packet_before_authenticator, 4, 16, $authenticator);
    return $packet_before_authenticator;

    IPv6 prefix encoding, for real this time

    The upstream module’s own documentation is honest about this one: ipv6addr, date, and ifid are, in its own words, simply mapped to other types until correct encoding is implemented. ipv6prefix and tagged-ipv6prefix aren’t handled upstream at all. For dual-stack IPoE sessions on that platform that’s not a cosmetic gap, since Framed-IPv6-Prefix and similar attributes need to actually round-trip correctly for a session to come up with working IPv6, not just IPv4.

    The fork adds real pack and unpack for both, using inet_pton/inet_ntop against the RFC-defined wire format (a reserved byte, a prefix length byte, then 16 bytes of address):

    "ipv6prefix" => sub {
        my $prefix = $_[0];
        my ($ipv6, $length) = split('/', $prefix);
        my $packed_ipv6 = inet_pton(AF_INET6, $ipv6);
        if (length($packed_ipv6) != 16) {
            warn "Invalid IPv6 address length";
        }
        return pack("C C a16", 0, $length, $packed_ipv6);
    }

    with the corresponding unpack turning the wire bytes back into a human-readable address/prefixlen string. Small in isolation, but this is the piece that actually fixed dual-stack sessions rather than just working around them.

    Tagged prefixes, and a bit of debugging courtesy

    The plain prefix handling above covers ipv6prefix, but there’s a tagged variant too, tagged-ipv6prefix, used where an attribute needs to carry a tag byte ahead of the usual reserved/length/address fields (the same tagging convention RFC 2868 uses elsewhere). The fork adds that as well:

    "tagged-ipv6prefix" => sub {
        my ($tagged) = @_;                       # "5,2001:db8::/48"
        my ($tag, $prefix) = split /,/, $tagged, 2;
        my ($addr, $plen) = split '/', $prefix;
        my $packed = inet_pton(AF_INET6, $addr)
                or die "inet_pton failed for $addr";
        return pack 'C C C a16', $tag, 0, $plen, $packed;
    }

    with a matching unpack on the receive side, so tagged prefixes round-trip the same way plain ones do.

    The other change is smaller but has saved more debugging time in practice. Stock behavior when the VSA-packing loop hits an attribute type it doesn’t recognize is to just skip it, silently. On a live NAS exchange, a VSA that quietly failed to make it into the outgoing packet is exactly the kind of thing that burns an afternoon before you think to suspect it. The fork adds a warning at that exact point instead:

    unless ( defined $type && exists $vsapacker{$type} ) {
        carp "Unknown VSA $vid/$attr – dropped" if $self->{unknown_entries};
        next;
    }

    Same fallback behavior, but now it says so.

    Making CoA-NAKs readable

    RFC 5176 defines a set of numeric Error-Cause values a NAS can return in a NAK, and out of the box you just get the number. The fork adds an errorCodes() lookup covering the RFC 5176 causes, from residual session cleanup (201) through the various fatal request errors (401 through 407) to the proxy and resource ones (501 through 508), each with both the short cause and the fuller RFC description. Debugging a rejected CoA against that box goes from grepping the RFC for what error 403 means to just reading it off the response.

    Why a fork instead of a patch

    All of this could theoretically have been contributed upstream or maintained as a patch series, but a CoA workflow specific to that platform with a fairly specific captive-portal use case is not something I’d expect the general module to want to carry, and patch series rot the moment the upstream module moves out from under them. A standalone copy, called directly instead of through the usual namespace, keeps it simple: what’s in the file is what’s running, no patch application step, no version skew to track.

    The tradeoff is exactly what you’d expect: any future upstream fix or improvement to Net::Radius::Packet has to be manually ported over if I want it, since there’s no dependency link back to the original at all. For a fork this targeted, that’s been a fair trade so far.

  • News Roundup: September 21 – 28, 2026

    One urgent patch dominates this week — everything else is smaller housekeeping, but there’s a decent pile of it.

    WordPress 7.1.2: unauthenticated RCE, patch immediately if you haven’t already

    WordPress pushed an emergency release on September 22 for CVE-2026-87902 (CVSS 9.2), a flaw in page-template resolution where an attacker can manipulate the value used to pick a page template and get get_page_template() to include an arbitrary readable PHP file from outside the active theme’s directories. No account, no vulnerable plugin, and no admin interaction required — on the right server/theme combination that’s remote code execution. It affects every branch back to 4.7.0, with backported fixes in 7.1.2, 7.0.6, 6.9.9, and 6.8.10. Attackers were probing within hours of disclosure, and CISA added it to its Known Exploited Vulnerabilities catalog on September 25. If auto-updates are off on any site you run, do this one manually today.
    WordPress 7.1.2 release notes

    MikroTik RouterOS 6.49.22 (long-term): the MikroTrick fix finally lands on the 6.x branch

    Released September 21, this backports the fix for CVE-2026-67281 — part of the same public-key SSH authentication bypass family that made up the “MikroTrick” chain a few weeks back — to the old 6.49.x long-term branch. If you’ve got legacy RouterBOARD hardware still pinned to 6.49.x because it can’t run RouterOS 7, this is the update you’ve been waiting for; the 7.x branch already got its fix in an earlier release.
    RouterOS 6.49.22 announcement

    Ubuntu: large batch of kernel fixes across every supported LTS

    September 25 brought a heavy round of kernel security updates — nearly 100 CVEs fixed on 24.04 LTS alone, plus smaller batches for 20.04, 18.04, and 16.04 LTS (the latter two still on extended security maintenance). Nothing here looks like a single standout bug, just the usual accumulated backlog of kernel hardening, but if you’re running any of these releases it’s a reboot-required update, so plan a maintenance window rather than letting it sit.
    Ubuntu security notices

    Ubuntu: libwebsockets RCE and DoS (USN-8822-1)

    Fixed September 28 — libwebsockets mishandled certain malformed CBOR data (potential crash or arbitrary code execution) and certain SSH protocol messages in its SSH handler (resource-exhaustion DoS). Most homelab boxes won’t have much linked against libwebsockets directly, but it shows up as a dependency in some IoT/MQTT and reverse-proxy tooling, so worth a quick check if you’re not sure what pulled it in.
    USN-8822-1 advisory

    systemd v262 released

    A meatier release than usual. Highlights for anyone running servers: TPM-sealed credentials are now pinned to the TPM’s Storage Root Key (protects against an interposed/spoofed TPM), Argon2id is now supported for TPM2 PIN enrollment, a new RestartRandomizedDelaySec= option staggers automatic service restarts instead of having everything hammer back at once, and newly created fscrypt-backed home directories default to fscrypt v2. It also adds support for building a single statically-linked PID 1 for minimal container images, and drops the legacy udev control socket protocol in favor of Varlink. Nothing here demands an immediate action, but it’s a good one to read through before it lands in your distro’s next release.
    systemd v262 release notes

    Home Assistant 2026.9.4 patch release

    Routine bug-fix release on September 27 for the 2026.9 series: fixes Tuya fans shutting off at zero speed, incorrect Todoist timed-event durations, and ISEO Argo BLE discovery scope. Safe to apply if you’re already on 2026.9.
    Home Assistant 2026.9.4 release notes

    Kernel corner: io_uring’s non-blocking guarantee is harder than it sounds

    Worth a read if you’re into the CLI/kernel side of things rather than just running the box: LWN covered an RFC from io_uring maintainer Jens Axboe proposing a scheduler-level mechanism (a new PF_IO_HANDOFF task flag) to detect when a supposedly non-blocking io_uring operation actually blocks somewhere in the kernel. Axboe himself calls it “potentially scary” and isn’t expecting it to merge soon, but it’s a good look at how deep the cracks run in io_uring’s core promise.
    Thread-identity switcheroo for io_uring (LWN)