v vanemmerik.ai / SUPPLY-CHAIN
Supply Chain · Watch Friday · 03 July 2026 End-of-day synthesis 4 watches · 27 items

From the watchtower — what crossed the wire today.

A four-times-a-day standing watch on the open-source supply chain. Each pass pulls newly disclosed CVEs, freshly catalogued KEV adds, and active attacks reported in the wild — then ranks them by severity for the day.

The story of the day — Six unrelated open-source projects each shipped a coordinated multi-CVE batch today, from Steeltoe's seven advisories to Zebra's twelve, while the MCP-gateway trust-boundary bug count for the week climbed to four.

Today read as a coordinated-disclosure day: six unrelated projects — Mautic, SimpleSAMLphp, Steeltoe, Craft CMS, Zebra, and 9router — each shipped a batch of two to twelve CVEs in one release instead of the usual single fix. CISA's only fresh KEV entry, a pair of Ubiquiti UniFi OS bugs added June 23, is only surfacing now through this pipeline's backfill window rather than as same-day news.

The trust-boundary theme that opened the week kept compounding: 9router picked up its third critical advisory in a row (a hardcoded fallback JWT secret, after the RCE and the local-only access-gate bypass), and fast-mcp-telegram's Bearer-token check has the same naive-string-as-authorization-boundary shape. On the credential-theft side, JFrog tied two new npm packages — rollup-packages-polyfill-core and rollup-runtime-polyfill-core, typosquatting the real rollup-plugin-polyfill-node — to North Korea-linked operators, landing alongside PamStealer's fake-Maccy macOS campaign and Kaspersky's new Armored Likho attribution: three separate credential-harvesting threads converged on the same day. Mautic's 7.1.2 release alone closes two independent roads to RCE (campaign-import path traversal and unsandboxed Twig execution), and Steeltoe's seven advisories include two operationally urgent ones — plaintext connection strings leaking over /actuator/env and a spoofable Host-header bypass of the port isolation meant to protect it.

→ Operational priority for the night grep every 9router deployment for an unset JWT_SECRET, confirm no project pulled rollup-packages-polyfill-core or rollup-runtime-polyfill-core this week and rotate credentials on any machine that did, and push the Mautic 7.1.2 and Steeltoe upgrades ahead of anything lower on tonight's list — both close multiple independent RCE or credential-leak paths in a single patch.

18:00 ET · First Watch

North Korea-linked npm packages impersonate a Rollup polyfill plugin to steal developer secrets

JFrog traced two published npm packages — rollup-packages-polyfill-core and rollup-runtime-polyfill-core — that typosquat the legitimate rollup-plugin-polyfill-node down to its description and repository metadata, and tied the campaign to North Korea-linked operators via infrastructure and TTP overlap. Confirmed malicious code live on the registry, not a PoC — the same lookalike-package-plus-secret-harvesting shape this pipeline has tracked through IronWorm/Miasma and the VS Code-tasks campaign this year, now with a state-actor attribution attached. Grep lockfiles and CI dependency trees for either package name; if either resolved, treat every secret on that machine as burned and rotate npm tokens, cloud keys, and SSH credentials.

Recce's query-run API lets an unauthenticated caller read and write local files through DuckDB

Recce's OSS server exposes unauthenticated SQL execution through its query-run API, and on DuckDB-backed projects, DuckDB's filesystem primitives turn that into arbitrary local file read/write — disclosure of local files, tampering with dbt/Recce artifacts, and stored XSS via modified browser-served static files, with root-level access if Recce runs as root. Upgrade to 1.50.0; until then, don't expose recce server to an untrusted network and run it as a non-root user.

12:00 ET · Forenoon Watch

9router's third advisory this week: a hardcoded fallback JWT secret lets anyone forge a valid dashboard session

9router falls back to a hardcoded, publicly-known JWT secret ("9router-default-secret-change-me") for signing dashboard session cookies whenever JWT_SECRET isn't set in the environment, and that string is unchanged across every released version. This is the third critical 9router advisory covered here this week — after the unauthenticated RCE and the local-only access-gate bypass — which makes the package itself the story now, not any single bug. Grep every 9router deployment for JWT_SECRET immediately; if it's unset, an unauthenticated attacker can already forge a valid session.

Mautic 7.1.2 also fixes unsandboxed Twig template execution — a second route to RCE in the same release

Mautic's theme engine renders uploaded Twig templates with no sandbox and no function restrictions, so any authenticated user holding theme create/upload rights can plant a template that runs arbitrary code on the host — this is the sixth CVE in the 7.1.2 release already covered here for its campaign-import path-traversal RCE. Two independent roads to RCE landing in the same build raises the urgency past the usual "patch when convenient": if you haven't upgraded yet, revoke theme-upload permissions from non-admins today and upgrade to 7.1.2 (5.2.11/6.0.9/4.4.20 for older branches) this week.

fast-mcp-telegram's Bearer-token check misses path separators, letting an unauthenticated caller hijack the default Telegram session

fast-mcp-telegram authenticates HTTP Bearer tokens by joining the raw token string into a session-file path and only blocks the exact literal "telegram" — not path separators — so a token like ../fast-mcp-telegram/telegram authenticates an unauthenticated remote client as the server's default legacy Telegram session. That's the third MCP-server trust-boundary bug flagged here this week (after 9router and Grackle), and every one so far comes from treating a naive string comparison as an authorization boundary. If you front an MCP gateway with token- or session-name-based routing, audit every place a caller-supplied string is used as a path segment before trusting it as an identity check.

GravitLauncher's file server leaks its own JWT signing key through an unauthenticated path traversal — full auth bypass

LaunchServer's HTTP file handler has an unauthenticated path traversal that reads any file the server process can access, and the readable set includes the server's own ECDSA key that signs access JWTs, the refresh-token salt, and the database credentials in LaunchServer.json. With the signing key, an attacker mints a valid access token for any account, including admins — pre-auth, default config, port 9274. This is full authentication bypass dressed as a file-read bug; patch immediately on any internet-reachable GravitLauncher instance.

Keycloak's SAML broker accepts an encrypted assertion for the wrong principal when the outer response isn't signed

Keycloak's SAML identity broker skips validating an encrypted assertion whenever the overall SAML response is unsigned, so an attacker who already holds one valid signed assertion can craft a response that injects an encrypted assertion naming an arbitrary principal and get unauthorized access under that identity. Keycloak sits in front of a lot of infrastructure, so this is worth prioritizing over its CVSS score alone — patch, and specifically audit SAML broker configs that accept encrypted assertions from external IdPs.

SimpleSAMLphp's HTTP-Artifact receive path validates a response against the wrong IdP's key — third bug in the same batch

A third SimpleSAMLphp fix from today's batch: in the HTTP-Artifact receive flow, SOAPClient::validateSSL() returns normally instead of throwing when the TLS key doesn't match, and SAML2\Message::validate() treats any non-throwing validator call as success — so an unsigned embedded SAML Response from one IdP can pass validation intended for a different, higher-trust IdP. Same root cause as the InResponseTo bug covered this morning: trust delegated to a layer that silently swallows failure. Multi-IdP deployments should treat both SimpleSAMLphp fixes as one upgrade, not two.

Steeltoe's alternate management port checks the Host header instead of the actual socket — trivially spoofed

A seventh Steeltoe advisory: when management endpoints are moved to a separate port, the middleware meant to restrict access to that port checks the HTTP Host header rather than which socket the request actually arrived on, so a crafted Host header reaches every actuator endpoint over the public port — including the env-sanitizer credential leak already covered this morning. If you patched that leak and thought the alternate-port isolation covered you, it doesn't; fix both in the same maintenance window.

Craft CMS's forced folder move can delete a destination folder without delete permission on it — second bug in this release

A second Craft CMS bug from the same release covered this morning: AssetsController::actionMoveFolder() with force=true deletes a conflicting destination folder to resolve a name collision, but only checks deleteAssets permission on the folder being moved — never on the destination. A user who can only move their own folder can delete someone else's by name-colliding into it. Same 5.9.21 upgrade fixes both this and the bulk-duplicate mass-assignment bug.

JSONata's $toMillis ReDoS lets a crafted date string hang any server evaluating user-supplied expressions

JSONata's $toMillis function validates ISO-8601 strings with a regex that backtracks superlinearly on crafted non-matching input — a straightforward ReDoS in any application that evaluates user-supplied JSONata expressions server-side. Upgrade to 2.2.0; if you can't immediately, stop evaluating untrusted expressions until you do.

Linuxfabrik's monitoring sudoers file hands the nagios user root via unrestricted apt-get arguments

Linuxfabrik Monitoring Plugins' shipped Debian sudoers file lets the nagios user run apt-get as root without constraining arguments, so `sudo apt-get update -o APT::Update::Pre-Invoke::="/bin/sh"` gets a root shell. The real barrier is that the nagios account has to be compromised first — this is privilege escalation after a foothold, not an initial way in — but on monitoring hosts that already run third-party check scripts unattended, that foothold isn't hypothetical. Tighten the sudoers entry to the specific update subcommand this pipeline needs.

Algernon leaks server-side Lua source (and embedded secrets) on Windows via an NTFS alternate-stream filename trick

Algernon picks its file handler from filepath.Ext(), which doesn't recognize NTFS alternate-data-stream suffixes like x.lua::$DATA as equivalent to .lua — so on a Windows host, appending that suffix to any public server-side script URL returns the raw source instead of executed output, including embedded database credentials and the cookie secret. Linux and macOS hosts aren't affected. If you run Algernon on Windows with public-facing .lua/.tl/.po2/.amber scripts, that's your exposure until you patch.

Three Rust JPEG XL decoder crates patch overflow bugs from the same audit pass — jxl-grid, jxl-oxide, jxl-modular

Three sibling crates in the Rust JPEG XL decoder stack fixed integer-overflow bugs together: jxl-grid has an out-of-bounds write on 32-bit targets from an unchecked width×height multiplication; jxl-oxide's FrameBuffer::new can size an undersized buffer the same way; and jxl-modular panics on integer subtraction overflow while decoding a crafted Modular-image MA tree. All three are DoS — no memory corruption reachable outside 32-bit unsafe paths — but any service that decodes untrusted JXL uploads should update jxl-grid, jxl-oxide, and jxl-modular together rather than patching piecemeal.

@nuxt/ui's SSR form markup has no method attribute — a pre-hydration submit leaks passwords into a GET request

@nuxt/ui's UForm and UAuthForm server-render a <form> with no method or action, relying entirely on a post-hydration @submit.prevent handler to intercept submission — so a submit that beats hydration (slow network, CSP blocking the bundle, autofill plus Enter) falls back to the browser default: a GET request with every field, password inputs included, serialized into the URL and landing in server access logs and browser history. One-line fix (add method="post") but easy to miss unless you specifically test pre-hydration submission.

Kaspersky names a new APT, Armored Likho, running BusySnake-stealer campaigns against government and power-sector targets

Kaspersky has attributed a previously undocumented threat actor, Armored Likho, to campaigns against government agencies and the electric power sector across Russia, Brazil, and Kazakhstan using a stealer they've codenamed BusySnake, blending financially-motivated intrusions with targeted espionage. Not a supply-chain compromise itself, but the same critical-infrastructure-plus-credential-theft shape as this morning's stealer coverage — worth tracking as context, not yet an action item.

06:00 ET · Morning Watch

CISA KEV adds two Ubiquiti UniFi OS bugs — improper input validation and a path traversal, both confirmed exploited

CISA added CVE-2026-34910 and CVE-2026-34909 to the KEV catalog on June 23 — an improper input validation bug and a path traversal in Ubiquiti UniFi OS — and both are only now surfacing in this pipeline's 30-day backfill window. Ransomware use is listed as unknown, but KEV inclusion means CISA has independent confirmation of in-the-wild exploitation. If you run self-hosted UniFi OS controllers, Cloud Keys, or Dream Machines, patch per Ubiquiti's advisory and check whether the management interface is reachable from the internet — these consoles routinely are.

9router's MCP-gateway RCE gets a second bypass — and a third route was never protected at all

9router — the npm MCP/agent-gateway proxy already patched once this year for unauthenticated RCE (CVE-2026-46339) — has two new advisories: the local-only access gate added by that fix determines "local" from the Host/Origin headers instead of the TCP source, so it's bypassable behind a reverse proxy, Cloudflare Tunnel, or DNS rebinding; separately, /api/tunnel/tailscale-install was never added to the middleware matcher at all, so an unauthenticated POST with a sudoPassword field pipes straight into `sudo -S sh` — root RCE on any deployment where the Node process runs as root, which is the default in most node:* Docker images. This continues yesterday's MCP/agent-gateway trust-boundary theme. Upgrade past 0.4.55, and add a USER directive to any container running 9router regardless of patch status.

Mautic 7 patches a CVSS 9.9 campaign-import path traversal to RCE, plus four sibling CVEs in the same release

The worst of five Mautic 7 CVEs patched together: a flaw in ZIP-extraction validation during campaign import lets a user holding only campaign:imports:create escape the temp directory and write arbitrary PHP into the webroot — RCE as the web server user. The same release also closes an API v2 authorization bypass (owner-scope viewown/editown checks aren't enforced, letting low-privilege API users read or modify other users' contacts and reports), two stored-XSS bugs, and an SSRF in the Focus URL-preview feature. Upgrade to 7.1.2 (5.2.11/6.0.9/4.4.20 for older branches); if you can't patch today, revoke campaign:imports:create from non-admins first.

Zcash's Rust node Zebra ships 12 advisories at once, headlined by a consensus-divergence bug that can fork the chain

Zebra (the Zcash Foundation's Rust full node) disclosed 12 advisories in one coordinated batch. The critical one: the P2SH sigop counter's pure-Rust path silently undercounts sigops behind a disabled opcode, so Zebra accepts blocks the reference zcashd implementation rejects on the block-wide sigop limit — a chain split reachable by broadcasting crafted P2SH transactions, no mining power needed. The other eleven are mostly node-availability bugs (mempool leaks, sync-restart poisoning, address-book aborts) plus one on-disk corruption issue in Sapling/Orchard subtree roots. If you run zebrad on mainnet or testnet, upgrade past 4.4.1 for the consensus bug before touching anything else in the batch.

New macOS stealer PamStealer poses as the open-source Maccy clipboard manager to harvest credentials

PamStealer is a new macOS infostealer distributed as a compiled AppleScript (.scpt) impersonating Maccy, a legitimate open-source clipboard manager, via lookalike download sites. It runs PAM checks post-install to time credential theft around the user's real login flow — the same fake-open-source-utility bait pattern seen repeatedly this year. If you or your team grab small utility apps from search results rather than GitHub/homebrew directly, that habit is the exposure; verify installer source and checksum before running anything claiming to be Maccy.

Steeltoe's actuator sanitizer misses .NET connection strings, leaking plaintext DB passwords over /actuator/env

Six Steeltoe advisories landed together; two are operationally urgent. The env-actuator sanitizer redacts by key-name suffix but never learned .NET's ConnectionStrings:* or Steeltoe Connectors' pattern, so /actuator/env returns full connection strings — embedded passwords included — in plaintext to anyone who can reach the endpoint. Separately, an unrecognized Eureka DataCenterInfo.Name value (the spec-valid "Netflix" string, which any Java/Spring service in a mixed mesh can legitimately send) throws inside registry deserialization and silently poisons the local service registry for every Steeltoe Eureka client sharing it. The rest — actuator permission gaps, JWKS cache invalidation, TLS keys left world-readable in /tmp, an OAEP/PKCS1v1.5 padding mixup — are lower urgency. Patch the actuator sanitizer and Eureka client first, especially on Cloud Foundry where /cloudfoundryapplication/env is reachable by any Space Auditor.

SimpleSAMLphp SP can bind a signed response from the wrong trusted IdP to another IdP's login state

SimpleSAMLphp shipped two SAML2 fixes: an XPath-transform DoS (unbounded transform chains in a crafted signed message), and a more interesting SP-side bug — the ACS endpoint logs but doesn't reject a response from an unexpected IdP, and combined with the library's tolerance for an unsigned InResponseTo when the signed assertion omits SubjectConfirmationData's own copy, a signed assertion from any trusted lower-assurance IdP can satisfy SP state created expecting a different, higher-trust IdP. That matters most in multi-IdP deployments where authorization logic depends on which IdP a user actually authenticated through. Upgrade both simplesamlphp/saml2 and simplesamlphp/simplesamlphp.

A tiny npm test-assertion package fixes arbitrary file write and ReDoS bugs in the same release

@asymmetric-effort/nogginlessdom, a small npm test-assertion library, fixed two independent bugs at once: matchFileSnapshot() took a filePath straight from test input with no traversal check, so snapshot-update mode (UPDATE_SNAPSHOTS=1) could be steered into writing attacker-controlled content to any path the test process can reach; and checkValidity() built a RegExp from an HTML pattern attribute with no backtracking guard, a straightforward ReDoS. Neither fires without a test suite processing untrusted fixtures or page content, but that's exactly the CI shape a lot of snapshot-testing pipelines have. Upgrade past 0.0.21 and check whether any CI job runs this package against externally-sourced test data.

Craft CMS's bulk-duplicate action checks the wrong id field, letting users overwrite entries they don't own

Craft CMS's element controller blocks a top-level id in the request body to stop ID tampering, but the bulk-duplicate action reads a second, unvalidated id through the newAttributes parameter and passes it straight to the duplication service — a user who can only duplicate their own entry can target another user's entry ID and overwrite it instead of creating a copy. Classic mass-assignment shape: the guard covers the wrong field. Upgrade past 5.9.21; until then, restrict bulk-duplicate permissions to trusted roles.

golang.org/x/image's TIFF decoder has no PackBits size cap — a kilobyte file can decompress to gigabytes

The TIFF decoder in golang.org/x/image doesn't cap the size of PackBits-decompressed output, so a small, unremarkable-looking TIFF can force the decoder to expand into gigabytes of memory — a classic decompression-bomb DoS in any Go service that thumbnails or previews user-uploaded images. Upgrade to 0.41.0 or later.

Anubis ransomware affiliates chain Citrix Bleed 2 with RMM tooling and supply-chain credential theft for initial access

Anubis-affiliated ransomware operators are using Citrix Bleed 2 (CVE-2025-5777) for initial access, then blending in with legitimate remote management and monitoring tools and harvested supply-chain credentials for lateral movement — living-off-the-land rather than novel malware. If Citrix Bleed 2 is unpatched anywhere in your estate, that's the immediate gap to close; separately, audit your RMM tool inventory for anything installed outside your provisioning process.