v vanemmerik.ai / SUPPLY-CHAIN
Supply Chain · Watch Thursday · 03 September 2026 End-of-day synthesis 4 watches · 11 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 — SiYuan's publish-mode disclosures kept escalating after First Watch and capped the night with an unauthenticated, stored SQL injection reachable from a saved document title.

Morning and midday were routine — an SVG-sanitizer XSS in SiYuan, a cache-poisoning bug in a niche MCP server, another jump in the Shai-Hulud worm's credential-scanning surface. The afternoon batch rewrote the day's shape twice over, and a third wave after First Watch rewrote it again.

Orval jumped from three RCE advisories to twelve in two days, all one bug pattern — OpenAPI spec text dropped unescaped into JS template literals and object keys, executing the moment a generated client, mock, or zod schema is built or imported. SiYuan's publish-sharing feature was the bigger story: an SVG-sanitizer XSS this morning became unauthenticated SQL execution by evening, and eighteen more advisories — fourteen of them after the 18:00 synthesis — turned up before bed. Late escalation at 21:00 ET: CVE-2026-72811, a SQL injection in backlink/mention search, is reachable not just from a raw client keyword but from a previously-stored document title breaking out of its query context on the live read-write database, no password required. Five more highs (a WebSocket edit-feed leak, a localhost-admin bypass reachable through the fixed-port proxy, an SSTI-to-SQL escalation, a graph-endpoint password-tier skip, and encrypted-notebook key material handed to anonymous readers) and eight mediums — all the same missing-publish-filter shape — round out the count. A full-read SSRF in unstructured, the URL-ingestion library underneath most LangChain and LlamaIndex RAG pipelines, is the other critical of the day. The one relief: none of these show evidence of active exploitation yet, and CISA's KEV catalog added nothing new — for once the researchers are ahead of the attackers.

→ Operational priority for the night if you run SiYuan's publish feature facing the internet, take it offline now — don't wait for a per-advisory patch, the pattern across twenty-plus advisories today is that every publish-mode endpoint is unauthenticated-reachable by design.

21:00 ET · Last Watch

SiYuan's publish-mode SQL injection is unauthenticated and stored: a client keyword or a saved document title both reach raw SQL

A third wave of SiYuan publish-mode advisories landed within the hour, and the SQL injection in backlink/mention search (CVE-2026-72811) is worse than this afternoon's searchEmbedBlock bug: it's reachable two ways — a raw client-supplied search keyword, or a previously-stored document title that breaks out of its query context the moment another reader triggers a mention lookup — both landing on the same read-write siyuan.db handle with no publish-password gate. Five companion highs round out the wave: a WebSocket broadcast leaks a live unfiltered edit feed to anonymous readers (GHSA-mw8r), a localhost-trust check on auth-gated admin endpoints is reachable through the fixed-port proxy (GHSA-3mp7), a second-order SSTI in attribute-view template columns escalates to arbitrary SQL when a malicious package is imported (GHSA-x67c), graph endpoints skip the publish-password tier entirely (GHSA-vpjw), and encrypted-notebook key-derivation material leaks to anonymous readers, enabling offline master-password cracking (GHSA-8x84). If you haven't already pulled internet-facing SiYuan publish instances offline tonight per the 18:00 advisory, this is the confirmation to do it now — assume every publish-mode endpoint is unauthenticated-reachable until SiYuan ships a comprehensive fix, not a per-advisory patch.

Eight more SiYuan publish-mode endpoints found missing the same access-filter check

The rest of tonight's SiYuan wave is one repeated bug shape: an endpoint checks CheckAuth but never the publish-access/password filter that gates the primary getDoc path, so a reader token — sometimes an anonymous one — gets attribute-view schema and block-ID enumeration (GHSA-5fhr), PDF annotations (GHSA-v7ph), block attributes and custom fields (GHSA-qvq9), breadcrumb/reference metadata (GHSA-67x2), database rows without the record password (GHSA-6mcf), document title/root info (GHSA-pm3w), absolute filesystem paths and OS usernames via resolveAssetPath (GHSA-jv8v), and unauthenticated write amplification via refreshBacklink (GHSA-wgwx). None of these is independently exciting, but eight advisories confirming the same missing-filter pattern across eight endpoints means the fix needs to be structural — a shared publish-access check applied at the router level — not eight one-off patches. Treat any SiYuan publish deployment as fully exposed until that structural fix lands.

18:00 ET · First Watch

Orval: nine new RCE advisories in one day — every unescaped OpenAPI text field the generator touches is a code-execution sink

Same root cause, nine sinks: Orval's code generator emits OpenAPI-supplied strings straight into JS template literals and object-literal keys without escaping backticks, `${...}`, or quote characters, so a spec's path, `servers[].url`, schema/array/header/enum defaults, or property and parameter names can inject a live JS expression that runs either when the generated request function is called or, for the zod-schema cases, the moment the generated module is imported. That's nine distinct advisories published today (GHSA-fg9p, -88f2, -w727, -2h9g, -8j6p, -2w86, -3575, -653q, -6437), on top of three more from yesterday (GHSA-p4cg, -6mr6, -cxq5) — a dozen CVEs against Orval in two days, all verified on 8.19.0. If you generate an Orval client, mock, or zod schema from any OpenAPI spec you don't fully control — a partner's API, an aggregator, a marketplace catalog — treat that codegen step as untrusted-input execution until Orval ships a comprehensive escaping fix, not a per-advisory patch.

SiYuan publish mode escalates from XSS to unauthenticated arbitrary SQL execution — six more advisories same day

This morning's SiYuan batch was an SVG-sanitizer XSS and a path-traversal gap; six more advisories landed this afternoon and the ceiling is now unauthenticated SQL execution. searchEmbedBlock (CVE-2026-69084) accepts a full client-supplied SQL statement verbatim on the main read-write siyuan.db handle with no single-statement guard, and fullTextSearchAssetContent (CVE-2026-69083) has both a raw-SQL method and an unescaped REGEXP-injection method on the asset-content DB — both reachable by the publish RoleReader token and by anonymous requests whenever Publish.Auth.Enable is false. Four companion advisories (auth-bypass via getHeadingChildrenDOM, cross-boundary disclosure via getBacklinkDoc, full-content leaks via the heading-transaction endpoints, and a storage/av/ path traversal) all share the same shape: content- and mutation-adjacent endpoints gated by CheckAuth only, never by the publish-access filter the primary getDoc path enforces. If you run SiYuan's publish feature facing the internet, disable it or force Publish.Auth.Enable until a fix lands — every one of these is anonymous-reachable by design, not by misconfiguration.

unstructured: full-read SSRF in URL-based partitioning, verified 0.22.26

The `url=` argument to `partition()`, `partition_html()`, and `partition_md()` is fetched with `requests.get()` and no host validation, and the raw response body comes back as element text — a complete SSRF read primitive against loopback admin APIs, internal services, and cloud metadata endpoints. `unstructured` backs LangChain's `UnstructuredURLLoader`, LlamaIndex's `UnstructuredReader`, Chainlit, and most RAG/agent pipelines that ingest a URL, so the vulnerable default sits underneath a lot of code that never expected to be doing raw SSRF. If any agent or ingestion pipeline you run passes a user- or tool-supplied URL into unstructured's partitioners, treat it as `169.254.169.254`-reachable today and add your own allowlist in front of it.

toml-node: unbounded-recursion crash and a __proto__ desync bypass Object.create(null) protection

A Peggy-generated recursive-descent parser with no depth limit means a ~5-6KB deeply-nested-array payload reliably crashes any Node process parsing untrusted TOML — cheap DoS against a package with ~47M monthly downloads. The companion bug is more interesting: the compiler builds tables with `Object.create(null)` specifically to block a direct `[__proto__]` write, but a path that routes through a scalar value first (`a.b.y.__proto__.__proto__`, where `a.b.y` is a number) desyncs the duplicate-key tracking strings from the real traversal path and lands the write on the real `Object.prototype` anyway. If you parse TOML from any source you don't control — config files, plugin manifests, CI definitions — pin past the fix and don't rely on `Object.create(null)` alone as your pollution defense elsewhere.

Claude Code Templates: unauthenticated command injection in the --studio local server

`npx claude-code-templates --studio` starts an Express server on port 3444 that binds to `0.0.0.0`, sets `Access-Control-Allow-Origin: *`, and requires no auth; two POST endpoints pass request-body fields straight into `child_process.spawn(..., { shell: true })`, so shell metacharacters in those fields execute. Anyone who can reach the port — a malicious page the developer's browser visits, or another host on the same LAN/Wi-Fi — gets arbitrary command execution with no credentials, the classic shape of a dev-convenience server that assumed localhost-only threat model and got a public bind address instead. If your team uses this tool's Studio mode, don't run it on a shared or untrusted network until it's patched, and check whether it's still running in the background — CORS wildcard plus a startup default of all-interfaces is an easy one to forget about.

Semaphore UI: manager-to-owner role escalation via slug collision, plus unprotected password-change CSRF

A project `manager` can call the custom-role creation endpoint they already have permission to use, name the new role `manager` (built-in slugs aren't reserved), and assign it the full permission bitmask — since role resolution matches by slug and overwrites the built-in bitmask with whatever the matched row holds, that self-authored role now carries owner-level rights. A second, unrelated advisory found the password-change endpoint has no CSRF token, no current-password confirmation, and a session cookie with no SameSite enforcement, so a malicious page can silently change any logged-in user's password including the admin's. Neither needs anything beyond a low-privilege account or a lured click; patch both before your next CI-runner permissions review.

12:00 ET · Forenoon Watch

SiYuan: SVG sanitizer HTML/XML parser mismatch enables stored+reflected XSS; separate path-traversal gap in /export/temp

SiYuan's SVG sanitizer parses uploaded SVGs as HTML before the file is served as XML, and the two parsers disagree on raw-text elements — wrapping a <script> inside <desc><style> survives the cleaner untouched and executes as a real script node once a browser opens the file as SVG, reachable both reflected (GET /api/icon/getDynamicIcon) and stored (a planted .svg asset), with no CSP to backstop it. A second advisory on the same kernel found the /export/temp/ short-circuit route was never wired into the IsSubPath/IsSensitivePath checks added for last month's export-disclosure fix (GHSA-6865-qjcf-286f), reopening arbitrary file read through a sibling code path the original patch missed. Same lesson twice in one day — a guard added to the main branch of a handler but not its short-circuit sibling; patch past 2026-07-14 and re-check any other handler in SiYuan with a similar branch structure.

Shai-Hulud infostealer worm variant now scans 469 credential locations, up from 189

GitGuardian's research shows the current Shai-Hulud npm-worm variant scanning 469 distinct credential locations across developer machines, CI/CD tooling, cloud configs, and AI tool configs — more than double the 189 paths earlier variants checked. The worm's self-propagating shape hasn't changed (compromise a maintainer's publish pipeline, harvest, republish into every package that maintainer controls, as seen again in the @7nohe/openapi-react-query-codegen compromise on Aug 28), but the wider credential surface means past incident-response sweeps that checked the old 189-path list should be re-run against the expanded set. If you've handled a Shai-Hulud-adjacent compromise since this worm's debut, re-scan affected hosts against the current 469-location list rather than assuming the earlier sweep still covers it.

CKAN MCP Server: cache-key collision enables response cache poisoning; companion advisory reflects upstream errors verbatim

Third and fourth advisories against @aborruso/ckan-mcp-server this cycle (after the allowlist-bypass CVE-2026-73845 on Sept 2): the response cache derives its key from an unescaped join of request parameters, so {q:"budget",rows:10} and {q:"budget&rows=10"} canonicalize to the same key, letting an attacker prime a colliding entry and hand a victim's distinct query the attacker's cached response on any shared deployment. A lower-severity companion bug reflects raw upstream bodies and internal exception text — including internal IPs like 169.254.169.254 — back to callers, turning the project's already-known SSRF findings into a semi-blind read channel. This server keeps surfacing the same shape of gap — attacker input crossing a trust boundary unsanitized; if it's deployed, pin to 0.4.112+ and treat the whole advisory thread as live, not just today's two.