Severity Daily

IT and AI security incidents, checked against the primary source

Tag: Nodemailer

  • Four of today’s nine stories are about the gap between a fix and the record of it

    Four of today’s nine stories are about the gap between a fix and the record of it

    The item to act on tonight is Ruby on Rails, and it is not the biggest-sounding thing that happened today. Rails’ patch for CVE-2026-66066 stops the file read that leaks secret_key_base. It does not stop the Marshal deserialization gadget that read exposed, which still executes on a fully patched server for anyone holding a valid key. An organization that upgraded in early August and did nothing else is closed to the theft and still open to code execution by whoever completed the theft first. Patch status and compromise status have come apart here, and the step that reconciles them — rotating secret_key_base and every other secret readable from the application process — is the one no scanner reports as missing. VulnCheck says exploitation began the week of August 24. That claim is thin, and it is not what should decide this: a working exploit against more than 7,100 exposed instances has been public since August 7.

    Bigger headlines were available today, and both of them shrank on inspection. The Justice Department rewrote its China hacking announcement so that NASA, the Federal Reserve, and the Senate are now “among the targets” of QTFY rather than its victims — a withdrawal, not an escalation. And a 9.8 critical CVE for the open-source project hulumi turns out to describe an over-permissive IAM policy in the project’s own CI sandbox account, a resource nobody who installs hulumi has.

    The day did have a thread, and it is a narrow one: in four of the nine stories, the fix and the record of the fix do not match. Rails is one. Nodemailer’s new 9.8 names 8.0.3 as the fixed version, and the 8.0.3 tarball on npm still carries the vulnerable line. Eight MCPHub CVEs published within a single second this afternoon carry fixes shipped between April 22 and August 23 — the critical remote code execution among them was fixed in May and disclosed today. And Eclipse Theia’s agent-mode workspace escape, an 8.8 that let the AI agent write and delete files outside the workspace on a model-supplied path, was closed in a release whose notes described the change only as a breaking API change. The engineering is not the failure in any of the four. The patch exists in all of them. What is unreliable is the thing a vulnerability management program actually reads.

    Second for most shops is Microsoft’s confirmation that Windows is falsely reporting Defender as turned off across effectively every supported client and server version, with no originating update to roll back, no named build to compare against, and alerts that persist even when notification settings are off. Expect it at the service desk at boot tomorrow, and brief staff with Get-MpComputerStatus rather than “ignore it” — the alert being trained out is the tamper signal.

    Then the rest. Seven ToolJet CVEs describe the same cross-tenant authorization gap in tooljet-db, and the worst of them carries a 9.9 and a 2.4 from the same scorer in the same record, against the vendor’s own 5.9. Nutex Health refiled its August 24 breach disclosure under Item 1.05 seven days later without adding the materiality determination that item exists for — a change of flag that automated screening will read and the filing’s own text contradicts.

    Still open: Microsoft has named neither the Defender build that causes the false alert nor a fix date. VulnCheck has published no correction on the ToolJet scoring conflict or the Nodemailer fixed-version range. The Justice Department has not said which, if any, of the seven named bodies QTFY actually compromised, and the pre-edit wording survives only in contemporaneous reporting. Nutex has not said whether it made a materiality determination, and the affected-individual count will come from state and federal breach portals, not EDGAR. And the Rails exploitation claim still rests on one social media post that VulnCheck’s own weekly report for that week does not list.

  • Nodemailer’s new critical CVE marks 8.0.3 as fixed. The shipped 8.0.3 still has the vulnerable line

    Nodemailer’s new critical CVE marks 8.0.3 as fixed. The shipped 8.0.3 still has the vulnerable line

    A CVE published this morning rates a five-month-old Nodemailer flaw at 9.8 and names 8.0.3 as the version that fixes it. The 8.0.3 tarball on the npm registry still contains the vulnerable line.

    What happened

    CVE-2026-82854 entered the National Vulnerability Database at 9:17 a.m. UTC on August 31, 2026. VulnCheck is the assigning CNA and supplied both scores on the record: 9.8 CRITICAL under CVSS v3.1 as the primary metric, and 9.3 CRITICAL under CVSS v4.0 as secondary. The weakness is CWE-93. The subject is Nodemailer, the SMTP client that most Node.js applications use to send mail, and which the npm registry recorded at 23,044,621 downloads in the week of August 23 through August 29, 2026.

    The defect itself is real and small. Nodemailer builds the SMTP MAIL FROM command by pushing arguments onto a list. If the calling application supplies its own envelope object carrying a size property, that value was concatenated into the command with no filtering. The upstream advisory shows the line in lib/smtp-connection/index.js:

    args.push(‘SIZE=’ + this._envelope.size);

    Neighboring envelope fields — the addresses, the DSN parameters — pass through sanitizing helpers first. This one did not. A size value containing CRLF characters therefore terminates the MAIL FROM line and begins a new SMTP command. The advisory’s proof of concept injects a recipient:

    size: ‘100\r\nRCPT TO:<[email protected]>’

    The result is a silent extra recipient on mail sent through that transport — a blind carbon copy the sender cannot see.

    None of that is new. The upstream advisory, GHSA-c7w3-x93f-qmm8 in the Nodemailer repository, was published on March 25, 2026, credited to a reporter named esquilichi. The maintainers rated it Low. Their reasoning is the precondition: Nodemailer’s automatic envelope construction never populates size, so an application is exposed only if it builds a custom envelope and lets untrusted input reach that field. VulnCheck’s advisory text agrees, in its own words — “Exploitation requires the application to expose envelope size to attacker-controlled input” — and then scores the flaw at 9.8 with a vector of AV:N/AC:L/PR:N/UI:N, which describes an unauthenticated attacker reaching the defect across a network with no preconditions at all. The gap between the sentence and the vector is the whole disagreement, and it is on the same page.

    The version conflict

    The scoring gap is arguable. The version data is not. Three statements about the fixed version circulate, and they do not agree:

    • The NVD record’s description reads “Nodemailer before 8.0.4 is vulnerable.”
    • The same record’s machine-readable affected range is nodemailer >= 0, < 8.0.3 — that is, 8.0.3 and later are unaffected.
    • VulnCheck’s advisory is titled “Nodemailer before 8.0.3 SMTP Command Injection via envelope.size” while its body says 8.0.4.

    The upstream GitHub advisory is the origin of the split, because it contains both halves. Its “Affected versions” field reads <8.0.3. Its “Patched versions” field reads 8.0.4. Those two statements are mutually exclusive, and they leave 8.0.3 in neither category. Downstream, the prose inherited one half and the CPE range inherited the other.

    We resolved it by reading the published code rather than the paperwork. Nodemailer 8.0.3 was published to npm on March 18, 2026; 8.0.4 was published on March 25, 2026, the same day the advisory went out. Unpacking all three tarballs from the registry and reading lib/smtp-connection/index.js:

    In 8.0.2, at line 1210, and in 8.0.3, at line 1162, the code is byte-for-byte identical:

    args.push(‘SIZE=’ + this._envelope.size);

    In 8.0.4, at line 1164, it is not:

    const sizeValue = Number(this._envelope.size) || 0;
    if (sizeValue > 0) {
        args.push(‘SIZE=’ + sizeValue);
    }

    The fix is a numeric coercion, and it lands in 8.0.4. Version 8.0.3 carries the vulnerable line. The vendor’s prose is correct; the machine-readable range that scanners consume is wrong by one patch release, in the direction that marks a vulnerable version clean.

    Why it matters

    Almost nobody reads a CVE description. Software composition analysis tools read the CPE range, compare it against a lockfile, and emit a verdict. That is the point of publishing a machine-readable range, and it is why an error there behaves differently from an error in prose: it does not produce a confused engineer, it produces a confident green check.

    Consider the two populations this record creates. An organization pinned to 8.0.2 gets a critical finding, upgrades, and is fine — the bad range still catches them. An organization pinned to 8.0.3 gets nothing. Their scanner reports the dependency as remediated, because 8.0.3 is outside the declared affected range, and the code they are running is the same code that 8.0.2 was running. They will not look again, because from their tooling’s point of view there is nothing to look at. A false negative is worse than a false positive precisely because it generates no work item, no ticket, and no second pass.

    How large that second population is depends on how many teams landed on 8.0.3 and stopped. The window was one week — March 18 to March 25 — and 8.0.3 was the current release for all of it. Any lockfile regenerated in that week pinned the version this CVE now describes as safe. We cannot size that population and will not guess at it; what we can say is that the registry moves more than 23 million copies of this package a week, and the range is wrong for exactly one version in it.

    There is a second, slower problem in the scoring. A CVSS 9.8 on a package with 23 million weekly downloads is a fire alarm in a very large building. When the alarm turns out to describe a defect that requires the application to have hand-built an envelope object and piped user input into its size field, the people who evacuated remember. Severity inflation is not a victimless drafting choice; it is how a scanner’s output stops being read. The maintainers said Low and explained why. The CNA said Critical and, in the same advisory, wrote down the precondition that makes Critical hard to defend. Both numbers are now attached to the same identifier, and a downstream consumer has no principled way to choose between them.

    This publication has now recorded four versions of the same failure mode in a week: an advisory whose stated preconditions contradict what its own researchers told reporters, a patched WordPress flaw whose fixing release is absent from the changelog, a CVSS 10.0 remote code execution described by its vendor as “additional hardening,” and now a fixed-version range that clears a version the vendor never claimed to have fixed. In each case the underlying engineering was fine and the record describing it was not. The defect gets fixed in an afternoon. The wrong number attached to it propagates for years, into scanners, dashboards, and compliance attestations that no human will ever reread.

    What to do

    Upgrade to Nodemailer 8.0.4 or later, and do not treat 8.0.3 as remediated regardless of what a scanner reports. The current release is 9.1.0, published August 31, 2026.

    Check for the pin specifically. npm ls nodemailer resolves the installed version including transitive copies; grep -r '"nodemailer"' package-lock.json finds pins a top-level check misses. The version to look for is exactly 8.0.3.

    If you cannot upgrade immediately, the precondition is your control. Search your codebase for calls to sendMail() that pass a custom envelope object, and confirm that no untrusted input reaches its size property. Applications that let Nodemailer build the envelope automatically are not exposed to this defect at all.

    If you maintain a vulnerability database, an SBOM pipeline, or an internal allowlist that ingested this CVE today, correct the range to < 8.0.4 by hand. The upstream data will stay wrong until someone amends it.

    Note separately that the 9.0.x line has carried related fixes this year — 9.0.2 on June 29 rejecting CRLF in HTTP proxy CONNECT destinations, and 9.0.5 on August 7 keeping control characters out of header values. If you are on 8.x for reasons other than inertia, that is worth revisiting.

    Sourcing note

    Checked against primary sources. CVE-2026-82854 was read from the NVD API at services.nvd.nist.gov/rest/json/cves/2.0?cveId=CVE-2026-82854, which gave the publication timestamp, the CNA identifier, both CVSS metrics and their source, CWE-93, and the affected-version data. The upstream advisory GHSA-c7w3-x93f-qmm8 was read in the Nodemailer repository for the Low rating, the affected and patched version fields, the vulnerable line, the proof of concept, and the credit. VulnCheck’s advisory page gave its title, its CVSS v4.0 vector, its range of “nodemailer >= 0, < 8.0.3,” and its precondition sentence.

    The version finding does not rest on any of those. We downloaded the 8.0.2, 8.0.3, and 8.0.4 tarballs from registry.npmjs.org, extracted them, and read lib/smtp-connection/index.js in each. That comparison is reproducible by anyone in under a minute and is the basis for the statement that 8.0.3 is unfixed. Publication dates for those versions come from the registry’s own time object. The download figure of 23,044,621 is the npm downloads API point value for the week of August 23 through August 29, 2026.

    Unresolved: whether the <8.0.3 range in the upstream advisory is a typo or a claim that a partial fix landed in 8.0.3 — though the identical code in 8.0.2 and 8.0.3 makes the latter hard to sustain. We found no public discussion of the discrepancy, and neither the maintainers nor VulnCheck has published a correction as of this writing. No exploitation of this flaw has been reported by anyone, and it is not in CISA’s Known Exploited Vulnerabilities catalog. CISA’s website returns 403 to automated requests, so KEV status was checked against the cisagov/kev-data JSON mirror on GitHub, catalog version 2026.08.27.