Severity Daily

IT and AI security incidents, checked against the primary source

Tag: CVE-2026-90776

  • Seven of today’s nine stories describe a fix that never reaches the running install

    Seven of today’s nine stories describe a fix that never reaches the running install

    The most important thing published today is not the day’s highest score. HAProxy CVE-2026-90678 is a 7.5, against a 9.8 for sngrep’s stack overflow. HAProxy outranks it on where it sits and on what a reader can do about it. A remote, unauthenticated HTTP/3 client can desynchronize reused backend connections, slip requests past a frontend deny rule, and swallow other users’ Authorization headers — at the edge, in front of everything behind it. And the fix is a commit, not a release: 3.3.14 and 3.4.4 are the newest builds on their maintained branches and both sit inside the affected range, which makes “update to the latest version,” the advice most coverage will give, wrong. sngrep’s 9.8 is real, but it is a terminal SIP viewer an operator points at traffic by hand, the blast radius is one workstation, and its fix is likewise a commit on master that no tagged release and no Debian package carries.

    There is a thread, and it is the day’s actual story. In seven of the nine stories published today, a fix exists somewhere other than in something you can install. HAProxy’s and sngrep’s are commits. snappy-java’s 7.5 out-of-bounds write has no fix at all — the newest artifact on Maven Central was published in July 2025 and is the top of the affected range. LangBot 4.10.11 generates its new recovery key only when none exists, so upgrading leaves an existing installation holding the 24-bit secret the release was cut to replace. ESPnet’s patched release raises an error below PyTorch 2.6 while its own metadata still declares torch>=2.3.1, so an install that satisfies the declared dependencies gets a fixed path that throws and unfixed paths that run. Nodemailer’s denial of service was introduced by the security fix in 9.1.0 and repaired only in 10.x, so a 9.x user has to cross a major version to escape it. And Really Simple Security’s fix has been auto-updating to three million sites since September 1 under a changelog line that reads like a display bug: the code arrived, the reason to care did not.

    Order of business behind HAProxy. LangBot next, because the reset endpoint is unauthenticated and the remedy is a key rotation by hand that the upgrade will not perform for you. Then ESPnet and Nodemailer, both dependency audits rather than emergencies. Really Simple Security mostly needs confirmation that auto-update ran. snappy-java is availability-only and lands on the one decompression call that makes the caller size its own output buffer. Two records close the day: Flowise’s cross-workspace credential flaw, patched in July and given CVE IDs on Friday, six weeks later and by a third-party CNA rather than the vendor; and Internet Download Manager’s kernel driver, where a public proof of concept turns idmwfp.sys into an arbitrary registry write for any logged-in user and the vendor, by the CVE record’s account, has not responded.

    Still open at the end of the day. Two federal deadlines come due tomorrow: NVD’s records for ConnectWise ScreenConnect CVE-2026-84869 and GitLab CVE-2026-85706 both carry a cisaActionDue of 2026-09-14, Monday, September 14, 2026. Tonec has said nothing about the IDM driver, so there is no patch to wait for. snappy-java has shipped no release in more than a year. And Flowise is the day’s inverse case, worth keeping in view: the code was fixed on time, and the record took six weeks to say so.

  • Nodemailer’s remote DoS was introduced by the security fix in 9.1.0, and only 10.x carries the patch

    Nodemailer’s remote DoS was introduced by the security fix in 9.1.0, and only 10.x carries the patch

    A denial-of-service flaw disclosed Friday and given a CVE ID Sunday was introduced by a security fix in nodemailer 9.1.0 — the hardening that closed one address-parsing hole opened a quadratic one.

    What happened

    On September 13, 2026, NVD published CVE-2026-90776, an algorithmic-complexity denial-of-service flaw in Nodemailer, the most widely used email library for Node.js. The record carries a CVSS 3.1 base score of 7.5 (High) and a CVSS 4.0 base score of 8.7 (High), both from VulnCheck, the CNA that assigned the ID, and it is classified CWE-407, inefficient algorithmic complexity. The underlying advisory, GHSA-prgh-xp8r-p3m5, was published two days earlier, on September 11.

    The affected range is precise: Nodemailer 9.1.0 through 10.0.4. The fix shipped in 10.0.5, published to npm at 12:10 p.m. UTC on September 11 — one minute after 10.0.4. The current release is 10.0.9. Versions before 9.1.0 are not affected.

    That range is the story. The vulnerable code did not drift in over years; it was added deliberately in 9.1.0, and it was added as a security fix. Nodemailer’s address parser assembles an email address by accumulating its atoms — the pieces between separators — into a growing string. Before 9.1.0, a comment inside an address was allowed to glue two atoms together. That is a real problem: an address written [email protected](x)evil.com could be flattened into the single domain example.comevil.com, delivering mail to a domain the sender never named. The 9.1.0 release closed that gap with a guard that refused to join two atoms across a comment unless the run already ended in @. The guard read the last character of the accumulator back off the string with slice(-1) on every token.

    Reading the last character that way forces the JavaScript engine to walk the whole accumulated string each time. Over an address built from many comment-joined atoms — a@b(c)@b(c)@b(c)... — the work grows with the square of the input. The comment in the patched code names the trade directly: the slice(-1) “makes the engine flatten the whole growing string on every token, which is quadratic over an address built from many comment-joined atoms.” The security fix worked; it just carried a quadratic tail no one caught in review.

    What we verified

    We downloaded the shipped packages from the npm registry and ran the parser against the advisory’s own proof of concept — an address of roughly 130,000 comment-joined atoms, about 635 KB — on Node.js 22. The results track the affected range exactly:

    • 9.0.6 (before the regression): 474 ms
    • 9.1.0 (regression introduced): 8,198 ms
    • 9.1.1: 7,424 ms
    • 10.0.4 (last affected): 7,216 ms
    • 10.0.5 (fixed): 237 ms
    • 10.0.9 (current): 147 ms

    A single input froze the parser — and, in a single-threaded Node.js process, the entire event loop — for more than seven seconds on affected versions, against a quarter-second on the versions on either side of the affected range. We confirmed the source of the difference by reading the code: 10.0.4 still carries the parts[parts.length - 1].slice(-1) line; 10.0.5 replaces it with a lastChars[state] value carried forward as each token is appended, so the last character is known without re-reading the string. The guard against comment-joined domain spoofing is preserved; only the quadratic read is gone.

    Why it matters

    This is a clean example of a pattern worth naming: a fix for one class of bug that introduces another, in the same function, in the same release. The 9.1.0 hardening was correct security work — the domain-spoofing gap it closed was the more dangerous of the two flaws. But the reviewer’s attention was on whether the guard was right, not on what it cost, and the cost was a remote denial of service that sat in the tree for two weeks across five releases before it was noticed. Anyone who upgraded to 9.1.0 specifically to get the spoofing fix took the DoS along with it. The lesson is not “don’t fix bugs”; it is that a change to a hot parsing path deserves a complexity read, not only a correctness read.

    The reachability of this one matters as much as the severity, and it cuts against Nodemailer’s usual shape. Nodemailer is an outbound library — its job is sending mail — and an application usually controls the addresses it sends to. If the address parser only ever sees strings the application itself supplies, an attacker has no lever. The advisory is explicit that the dangerous path is a different one: the same parser is reachable via mailparser, the companion library that processes inbound email. Inbound headers are attacker-controlled by definition. A service that parses incoming mail — a ticketing system, a mailing-list processor, an inbound webhook that reads the From or To line — hands the parser a string it did not write, and a single crafted message can stall it. The advisory reports the flaw is reachable through mailparser’s inbound header parsing without authentication.

    The blast radius is a function of how the process is deployed. A worker that parses one message at a time, synchronously, is stalled for the duration of each malicious message — a queue of them is a sustained outage. A web server sharing the event loop with request handling stops answering everything, not just mail, while the parse runs. Because the cost is quadratic, the attacker’s effort is cheap: doubling the payload roughly quadruples the freeze, so a few megabytes buys a much longer stall than the seven seconds we measured at 635 KB.

    There is no exploitation observed. This is a disclosed-and-patched flaw with a public proof of concept, not an incident. The reason to move is that the proof of concept is trivial to reproduce — we reproduced it from the advisory in one run — and the patched and unpatched releases differ by a single npm version bump, which makes the diff easy for anyone to read and weaponize.

    What to do

    Upgrade Nodemailer to 10.0.5 or later; the current release is 10.0.9. If you cannot move off the 9.x line immediately, note that there is no fixed 9.x release — the patch shipped only on 10.x — so the upgrade is a major-version bump, and 10.0.0 landed on September 4, 2026 with its own set of changes worth reading before you jump.

    Prioritize by exposure to untrusted input. If your application only sends mail to addresses it controls, this is a low-urgency dependency update. If you parse inbound mail with mailparser, or feed any user-controlled string to the address parser, treat it as the real risk it is and patch first. Check your lockfile for the resolved Nodemailer version rather than the range in package.json; a caret range can resolve to an affected build. As a stopgap where you cannot upgrade, cap the size of address strings you accept before parsing — the attack needs a large input to be worth anything, so a length limit on inbound header fields blunts it.

    Sourcing note

    We verified the affected and fixed ranges by downloading Nodemailer 6.10.1, 9.0.6, 9.1.0, 9.1.1, 10.0.4, 10.0.5, 10.0.6, 10.0.7, 10.0.8, and 10.0.9 from the npm registry and timing the shipped address parser against the advisory’s proof of concept on Node.js 22.22.2; the numbers above are our own measurements. We read the parser source across versions and confirmed the 9.1.0 diff that introduced the slice(-1) guard and the 10.0.5 diff (commit c07f175) that replaced it. The CVSS scores, CWE, and timestamps are from NVD’s record for CVE-2026-90776 (published September 13, 2026, 12:17 p.m. UTC); the affected range, patched version, credit to mmadersbacher, and the “reachable via mailparser” characterization are from GHSA-prgh-xp8r-p3m5 (published September 11, 2026). npm registry metadata supplied the release timestamps. One item we did not independently test: the advisory’s specific claim about mailparser’s inbound path — we confirmed the shared parser is the vulnerable component and reproduced the DoS directly against it, but did not run a crafted message end-to-end through mailparser. VulnCheck is the CNA and the scoring source; there is no second independent advisory, and no exploitation has been reported.