v vanemmerik.ai / SUPPLY-CHAIN
Supply Chain · Watch Tuesday · 28 July 2026 End-of-day synthesis 4 watches · 57 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 — The day's headline event stayed datamodel-code-generator's eleven-advisory pile-up, but a late batch after First Watch pushed goshs to five separate advisories in one day and added an unrelated critical SQL injection in @hypequery/clickhouse — 21:00 didn't mean the day was done.

Two CISA KEV criticals carried over from yesterday continue to anchor the week: Arista VeloCloud Orchestrator's unauthenticated command injection (CVSS 10, three attacker IPs published, due July 30) and a FortiOS symlink-persistence patch bypass for anyone who thinks a prior Fortinet incident is fully closed (due August 10). Neither escalated further today, but neither is done either.

The day's real news is volume, not a single blast: datamodel-code-generator shipped eleven advisories in about a forty-minute publishing window this evening, covering code injection via default_factory, x-python-import, x-python-type, and validator fields, two carriage-return comment-escape variants, three separate SSRF paths (including a DNS-rebinding bypass of the SSRF guard itself), and arbitrary local file reads via both JSON-Schema $ref and XSD schemaLocation. Every one of them reduces to the same lesson: this tool was never designed to run against a schema you don't trust, and a lot of "paste your OpenAPI spec" tooling does exactly that.

Elsewhere, two Ruby OAuth gems both had redirect-target trust bugs land the same day, and Fission racked up four separate boundary-check failures (Zip Slip, a lexical path check that wasn't a path check, an incomplete capability denylist, and a CLI-only validation gap) in one CRD. goshs turned into the day's real repeat offender — five advisories total, each patching the route someone thought of and leaving the next one open: SFTP empty-password reuse, bulk-download ACL bypass, a trailing-slash filename mismatch that defeats the ACL file itself, an upload filename ".." that escapes the served tree, and a WebDAV MOVE verb that ignores --no-delete entirely.

Late escalation at 21:00 ET: the goshs MOVE bypass (CVSS 9.1) landed twelve minutes after First Watch synthesized the day, followed sixteen minutes later by an unrelated critical — @hypequery/clickhouse's parameter escaper fails to neutralize a trailing backslash, reopening SQL injection (CVSS 9.8) for anyone passing user-controlled values as ClickHouse query parameters. Neither shows signs of active exploitation, but both are now live, and Socket, Phylum, and Aikido stayed quiet through the last watch too — no active campaign activity surfaced today, which remains the one piece of good news in an otherwise high-volume day.

→ Operational priority for the night if you run goshs anywhere network-reachable, treat today as a full-audit day, not a single-patch day — SFTP, bulk-download, sendFile, upload, and WebDAV MOVE are all confirmed-affected surfaces; and if anything in your stack runs datamodel-code-generator against a schema submitted by a user, a partner, or any process outside your own repo, pin it to 0.60.2 or later before that pipeline runs again.

21:00 ET · Last Watch

@hypequery/clickhouse's parameter escaper fails to neutralize a trailing backslash, reopening SQL injection

escapeValue() escapes the closing quote but not a preceding backslash, so a parameter value ending in \ cancels the escape and reopens SQL context — classic incomplete-escaping SQLi, CVSS 9.8. Any app passing user-controlled input as ClickHouse query parameters through this library is directly exploitable, no chaining required. Upgrade to 2.0.2; the advisory explicitly warns against hand-rolled escaping as a substitute.

goshs's --no-delete flag never checks the WebDAV MOVE verb — files still deletable and overwritable unauthenticated

The --no-delete guard blocks DELETE but MOVE lives in the write-only branch gated solely by --read-only, and MOVE both deletes the source on rename and RemoveAll()s the destination under Overwrite:T — so an operator running -w --no-delete to keep files immutable still has them destroyable via MOVE. Fifth goshs advisory today, same pattern as the other four: a fix that closes the route someone thought of, not the boundary itself. If you run goshs with --no-delete, block the MOVE verb at a reverse proxy until upstream fixes the guard for real.

style-dictionary's convertTokenData() lets a crafted token key pollute Object.prototype globally

A token array entry like `{ key: '{__proto__.foo}', value: 'malicious' }` interpolates straight into object construction, polluting Object.prototype for the whole process — reachable directly, via the Expand API, or automatically after any transform lifecycle run. Worst case is style-dictionary running server-side in NodeJS against externally influenced tokens; upgrade to 5.4.4.

openhole-server forwards the URL-decoded path to tunnel clients, letting percent-encoded traversal reach files outside the web root

Go's ServeMux rejects literal ../ paths, but openhole-server decodes the request path before forwarding it to tunnel clients, so percent-encoded sequences (%2e%2e, %2f) survive and arrive as working traversal — unauthenticated, against any tunneled service that doesn't canonicalize paths itself. Upgrade both openhole-server and the openhole CLI to 0.1.2.

gotd/td allocates a buffer from an attacker-controlled length field before validating it against the actual packet size

UnencryptedMessage.Decode reads a 32-bit dataLen and immediately make()s a buffer of that size before checking the buffer actually holds that many bytes, so a 20-byte packet declaring a ~1.75GB payload forces a multi-gigabyte allocation during the unauthenticated MTProto handshake. Upgrade to 0.145.1; no in-process workaround exists short of not exposing the handshake path to untrusted peers.

goshs's sendFile derives the served filename from the raw request path, so a trailing slash defeats the ACL-file protection and block list

sendFile takes the filename from the raw (undecoded) request path while opening the file from the cleaned path; a trailing slash empties the derived name, and both the never-serve rule for the .goshs ACL file and the block list key off that name — so GET /blocked/.goshs/ returns the ACL file itself, hashes included. Authentication on protected directories still holds; only the block list and ACL-file protection are defeated. Fourth goshs advisory today — patch when a fix ships, and don't rely on the block list alone.

Pagy's I18n locale setter flows unsanitized into a YAML.load_file path, giving a file-existence oracle for arbitrary .yml paths

Pagy::I18n.locale= (commonly assigned from params[:locale]) is used verbatim as a path component when loading a dictionary file, so a value like ../../../config/database lets an attacker probe for the existence and readability of arbitrary .yml files on the host — contents aren't returned, but the file is read into the process during the attempt. Only apps that assign untrusted input directly to the locale setter are affected; upgrade to 43.5.6 or validate against a BCP-47 pattern first.

skilo add follows symlinks during install, letting a malicious skill source exfiltrate files like SSH keys into the installed skill directory

skilo's copy_dir_all classifies entries with file_type() (doesn't follow symlinks) but copies with fs::copy() (does), so a skill containing reference.txt -> ~/.ssh/id_rsa gets installed as a plain file holding the key's contents — readable by anyone who later opens, shares, or syncs the installed skill. Only install skilo skills from trusted sources; patched in 0.11.1.

goshs's multipart upload filename fix splits on path separators but never rejects a bare "..", still escaping the upload folder

The earlier fix for the multipart filename bug splits on the separator but doesn't reject ".." itself, so uploading with filename=".." makes goshs os.Create() against the parent of the upload folder — outside the served tree, unauthenticated, default config. Reject any resolved destination path that doesn't stay under the upload root, not just the raw filename string.

18:00 ET · First Watch

goshs SFTP mode accepts any password when only a username is configured — the empty-password mirror of an already-patched empty-username bug

CVE-2026-40884 fixed the `-b ':pass'` (empty-username) SFTP auth bypass in April by AND-ing username and password checks, but the mirror case — `-b 'admin:' -sftp` with no `-fkf` — was never covered, so any operator who set only a username with SFTP enabled has SFTP silently accepting unauthenticated connections. If you run goshs with SFTP and only a username configured, add a password or disable SFTP until a full fix lands; the same conditional-boundary mistake surviving a partial patch is worth grepping your own auth code for.

Poweradmin trusts the HTTP Host header to build OIDC/SAML callback URLs — unauthenticated full account takeover

Poweradmin 4.3.2 builds its OIDC redirect_uri, SAML ACS/SLO URLs, and logout redirects straight from the attacker-controlled HTTP_HOST header with no validation, so poisoning that header redirects the IdP's authorization code to an attacker-controlled server — no credentials needed, full account takeover. Three independent code paths hit the same unvalidated-Host pattern; if you run Poweradmin with OIDC or SAML, pin Host validation at the reverse-proxy layer immediately and patch when a fix ships.

datamodel-code-generator: attacker-controlled default_factory schema field runs as raw Python at import time

First of an eleven-advisory batch published today against the same tool: a schema's "default_factory" key is interpolated verbatim into the generated Field(default_factory=...) call, which Python evaluates the moment the generated module is imported — so an attacker who controls the input schema controls code execution in the consumer's process. Any service that codegens Python models from an externally submitted OpenAPI/JSON-Schema document (self-serve API tooling, multi-tenant codegen platforms, CI that ingests a submitted spec) is a remote-code-execution vector, not just a linter finding. Upgrade to datamodel-code-generator 0.60.2+; the fix now validates default_factory against an allowlist of dict/list/set.

datamodel-code-generator: x-python-import / customTypePath extensions inject arbitrary import-time Python

Same batch, same root cause: the x-python-import and customTypePath schema extensions flow unsanitized into the generated `from … import …` line, so a newline in the extension value breaks out and injects an attacker-controlled statement that runs at import time. No --extra-template-data flag needed — a plain malicious OpenAPI/JSON-Schema doc is enough. Treat any datamodel-codegen run over an untrusted schema as untrusted code execution until you're on the patched release.

datamodel-code-generator: unescaped validators entries in --extra-template-data break out into arbitrary decorator code

Same batch: in Pydantic v2 output mode, field names from a --extra-template-data validators array are interpolated into a @field_validator(...) decorator wrapped in unescaped single quotes, so a stray quote breaks out and injects an arbitrary positional expression that runs at class-definition time. Anyone who lets a schema or its extra-template-data come from outside the trust boundary is exposed the moment the generated file is imported.

datamodel-code-generator: literal carriage return in --extra-template-data comment escapes the Python # comment it's rendered into

Same batch, different delivery: a bare \r in the comment field survives escaping (only \n is handled) and Python's tokenizer treats a lone CR as a physical-line terminator, so text after it parses as live Python rather than a comment. Same import-time execution outcome as the rest of the batch — the pattern here is "line-terminator handling assumed \n-only" recurring across multiple of today's eleven advisories.

datamodel-code-generator: same carriage-return comment escape, reachable via a GraphQL Union type description

Same batch, same CR-vs-comment bug, this time reachable through GraphQL schema input rather than JSON-Schema/OpenAPI — confirms the CR-escaping gap sits in a shared Jinja2 filter used across input formats, not a one-off. If you patch the OpenAPI-facing entry points but still accept attacker-controlled GraphQL schemas, you're still exposed until the shared filter is fixed upstream.

datamodel-code-generator: x-python-type JSON-Schema extension forwards attacker Python straight into the field annotation

Same batch: the x-python-type extension overrides a field's generated Python type, and its value is forwarded verbatim into the field annotation past a single trivially-bypassed sanitization pass — no --extra-template-data or special flags required, a plain schema is enough. Eleven advisories in one day against one tool all reduce to the same lesson: never run datamodel-codegen against a schema you didn't author yourself until this wave of fixes lands.

datamodel-code-generator: JSON-Schema $ref resolves file:// URIs and ../ traversal, bypassing --no-allow-remote-refs

Rounding out the batch's non-RCE half: $ref targets aren't restricted to the input/base directory and the remote-reference security flag doesn't cover local-filesystem refs, so a crafted schema reads arbitrary files the process user can access and folds the contents into generated source — a real information-disclosure path for any "paste your schema" codegen service.

datamodel-code-generator: xs:include/xs:import schemaLocation path traversal reads arbitrary local files, with no remote-ref gate at all

Same file-read class as the $ref bug, ported to XML-Schema input — xs:include/xs:import/xs:redefine/xs:override resolve schemaLocation with no base-directory restriction, and unlike the JSON-Schema path there's no allow_remote_refs-style gate to disable. If you accept XSD input, this one has no flag-based mitigation; pin the version until patched.

datamodel-code-generator: HTTP(S) $ref targets are silently dereferenced by default — the safety flag only warns, it doesn't block

The batch's SSRF half: --allow-remote-refs defaults to None, which just logs a deprecation warning and fetches the URL anyway — only an explicit --allow-remote-refs=false blocks it. Combined with no host/IP allowlist and unconditional redirect-following, any schema with an http(s) $ref reaches whatever the codegen host can reach, including internal services, and reflects the response into generated source.

datamodel-code-generator: --url fetcher has zero host/IP validation and follows redirects unconditionally

Same SSRF class, this time in the built-in --url fetcher itself rather than $ref resolution: no allowlist, no denylist, no IP validation, loopback and RFC1918 and the 169.254.169.254 metadata endpoint are all reachable, and the fetched body gets parsed as a schema and reflected into generated source — useful for exfiltrating whatever that internal endpoint returns.

datamodel-code-generator's anti-SSRF guard validates a resolved IP once, then lets httpx re-resolve DNS independently at connect time

Closes out the batch: the SSRF guard checks the resolved IP once but never pins it, so a hostname that resolves public at validation time and private at connect time (classic DNS rebinding) sails past the guard even with allow_private_network=False set. Applies on top of the other two SSRF entries in this batch — fixing --allow-remote-refs without fixing this rebinding gap still leaves the door open.

goshs's ?bulk zip-download route reads any file protected by a .goshs ACL, unauthenticated — the earlier ACL fix never touched this route

A prior advisory fixed the .goshs per-folder ACL bypass on the write routes and claimed the read path was already safe — but the ?bulk zip-download handler streams requested files without ever calling the ACL check the normal read path uses, so any file behind a documented .goshs ACL is readable unauthenticated via ?bulk. Second goshs advisory today built on the same theme: a security fix that covers the routes someone thought of, not all of them. Audit alternate read routes (the advisory also flags ?cbDown) for the same gap.

Fission's PodSpec safety validation denylists six Linux capabilities but forgot CAP_SYS_TIME — tenants can corrupt shared-node wall clocks

Fission 1.24.0 added an admission webhook denylisting SYS_ADMIN, NET_ADMIN, SYS_PTRACE, SYS_MODULE, DAC_READ_SEARCH, and DAC_OVERRIDE for tenant Functions, but a fixed denylist is inherently incomplete — CAP_SYS_TIME wasn't on the list, letting one tenant on a shared node skew the wall clock for every co-tenant's functions. Classic allowlist-vs-denylist lesson: switch to a capability allowlist rather than trying to enumerate every dangerous one.

Fission's package fetcher writes archive entries outside the destination directory — textbook Zip Slip

Unarchive() joins each zip entry name onto the destination directory via filepath.Join without checking the resolved path stays inside it, so a `../../tmp/evil`-named entry in a Package.Spec.Source.URL or Deployment.URL archive writes wherever the fetcher sidecar's filesystem permissions allow. Validate every extracted path stays under the destination root before writing — the fix is a few lines, the bug class is decades old.

pytonapi's TonapiWebhookDispatcher never validates bearer tokens for webhook handlers registered on a custom path

Bearer tokens are stored only against the default suffix paths (e.g. /hook/account-tx); a handler registered with the documented path= argument never gets an entry in the token map, so the lookup on the custom path returns nothing and the auth check is effectively skipped. If you registered any pytonapi webhook handler with a custom path, that endpoint is currently accepting requests with no token validation — upgrade or switch back to default paths until patched.

One malformed UDP packet on SIPSorcery's RTP/ICE socket kills the media session — reachable pre-DTLS handshake

The RTP/ICE receive handler indexes packet and STUN-attribute bytes without sufficient length checks, throws on malformed input, and the UDP receive loop turns that exception into a channel Close rather than dropping the bad packet — so one small unauthenticated packet during ICE connectivity checks ends an active call. If you run SIPSorcery-based WebRTC/VoIP infra, this is pre-auth and trivially exploitable for call disruption; patch when available and consider bounds-checking at the network edge in the meantime.

QTINeon's relay forwards every RECONNECT_REQUEST to the host with no dedup or cap — spoofed-source amplification against the host

Unlike the connect flow, which caps pending connections via maxPendingConnections, the reconnect handler has no equivalent guard: an attacker who knows a valid session ID can spray RECONNECT_REQUEST packets from spoofed source addresses and each one that passes the session lookup gets forwarded to the host as a new reconnect attempt. Amplification DoS against the host is possible without ever authenticating; rate-limit or cap pendingReconnects the same way the connect path is capped.

OAuth2::Client#request resolves a protocol-relative redirect Location as same-authority, leaking bearer Authorization to an attacker host

A malicious or compromised authorization server returns `Location: //attacker.example/leak`; per RFC 3986 a leading `//` is a network-path reference that replaces the authority, but OAuth2::Client#request's merge logic treats it as staying on the trusted host and follows it, Authorization header and all. Any app using OAuth2::Client/OAuth2::AccessToken against a server you don't fully control should treat this as a credential-leak path until patched — don't auto-follow redirects on token-bearing requests without re-validating the target host.

OAuth::Consumer#token_request follows cross-host redirects and can mutate the consumer's configured site to the redirect target

Same-day pairing with the OAuth2::Client bug above: OAuth::Consumer's request/access-token flow parses and recursively follows 300-399 redirects, and when the redirect points at a different host it can overwrite the consumer's configured `site`, exposing signed request metadata to that host. Two independent OAuth gems, two variants of "don't trust the redirect target as if it were the configured endpoint" landing the same day — worth an audit pass across any OAuth client library you depend on for exactly this pattern.

CVE-2026-32203: .NET's EncryptedXml (System.Security.Cryptography.Xml) has a buffer-overflow DoS

Microsoft's own advisory for a buffer overflow in the EncryptedXml class used for XML encryption/decryption — exploitable for denial of service against any .NET/Visual Studio app that processes untrusted encrypted-XML input. Apply the .NET/Visual Studio update per Microsoft's guidance; this is a vendor-patch-and-move-on item, not one with a workaround.

Fission HTTPTrigger's RelativeURL/Prefix fields were validated only in the CLI — kubectl apply skips the check entirely

The CRD-modernization webhook retirement moved validation to API-server CEL rules, but neither the retired webhook nor the new CEL rules ever covered RelativeURL/Prefix — those were checked only client-side in the fission CLI. Anyone applying HTTPTriggers via kubectl or the Kubernetes REST API directly bypasses validation entirely; don't rely on CLI-only checks for anything security-relevant in a CRD.

Cosmos-Server's Constellation-tunnel bypass returns to the upstream handler before stripping x-cosmos-user/-role headers

tokenMiddleware's Constellation-tunnel branch skips ahead to the proxied backend before the code that strips x-cosmos-user, x-cosmos-role, x-cosmos-user-role, and x-cosmos-mfa headers runs, and before the admin-only gate checks anything — so any holder of a valid Constellation device API key can send x-cosmos-user: admin straight through to a proxied backend that trusts forward-auth headers. Audit any backend behind Cosmos-Server's Constellation tunnel that trusts these headers without its own verification.

Cosmos-Server's public-devices endpoint strips "Bearer " from the Authorization header but never validates what's left

GET /cosmos/api/constellation/public-devices discloses Constellation device metadata to any request carrying a non-empty Authorization header — the token is never checked against anything or used in the database query, confirmed with a fabricated `Bearer not-a-real-token`. Same Constellation-tunnel component as the header-smuggling bug above; worth reviewing the whole forward-auth integration together.

NocoBase's checkSQL() keyword blacklist doesn't cover PostgreSQL system catalog tables like pg_shadow and pg_roles

The SQL Collection feature's guard blocks a set of dangerous PostgreSQL functions by keyword but never restricts access to system catalogs, so a query against pg_shadow or pg_roles sails through and can expose password hashes and role metadata. Blacklists of this shape keep losing to enumeration — if you run NocoBase with SQL Collection enabled for less-trusted users, restrict DB-level grants on system catalogs rather than relying on the application-level filter.

GoPacket's sFlow ExtendedGatewayFlow decoder allocates before it reads — a 104-byte UDP packet can request 16 GiB

The decoder does `make([]uint32, n)` with an attacker-controlled 32-bit `n` before the loop that would actually consume the corresponding bytes runs, so a single small crafted sFlow datagram forces a multi-gigabyte allocation and OOM-kills any service parsing sFlow with gopacket. Unauthenticated remote DoS against network-telemetry pipelines; validate `n` against the remaining buffer length before allocating.

GoPacket's Diameter AVP decoder underflows a uint32 length subtraction into a ~4 GiB allocation request

Same-batch companion to the sFlow allocation bug: `dataLength := avp.Length - uint32(headerSize)` underflows when the Vendor flag is set (headerSize 12) and Length is 8-11, since the only upstream guard only rejects Length < 8 — the underflowed value feeds straight into `make([]byte, dataLength)`. Two unauthenticated allocation-DoS bugs in the same decoder library the same day; if you run gopacket against untrusted network input, pin length validation before this ships upstream.

datamodel-code-generator forwards Authorization headers to cross-origin redirect targets when fetching remote schemas

Twelfth item in today's datamodel-code-generator wave but lower stakes: redirect-following re-sends the original Authorization header even when the redirect changes host, so credentials scoped to a trusted schema host leak to whatever the redirect points at. Low severity on its own, but if you're already auditing this tool today for the other eleven advisories, check this one too.

Fission's SanitizeFilePath used a lexical HasPrefix check instead of a real path-boundary check

`/packages-extra/evil` lexically starts with `/packages`, so HasPrefix passed it as safe with no path-separator boundary enforced — a sibling directory sharing a name prefix escapes the intended sandbox. Low severity alone, but it's the same category of bug as the Zip Slip and capability-denylist issues in this same Fission batch: boundary checks that were never actually boundary checks.

sqlite3-ruby: calling a custom aggregate function on a statement after the database was explicitly closed segfaults on a use-after-free

Low-severity per the maintainers — needs a specific misuse pattern (open statement + closed database + aggregate callback) rather than attacker-controlled input. Upgrade to sqlite3 gem 2.9.5+, or avoid calling aggregate functions after closing the database as a workaround.

12:00 ET · Forenoon Watch

lettre's boring-tls backend has hostname verification inverted — silent MITM on "strict" config

lettre passes its accept_invalid_hostnames flag straight through to boring's set_verify_hostname without negating it, so the two libraries' opposite-sense booleans cancel out: asking lettre for strict verification (the default) actually disables boring's hostname check, and opting into "accept invalid hostnames" enforces it instead. Any lettre user on the boring-tls feature with default-strict config is silently exposed to on-path SMTP interception — an attacker with any chain-valid cert for a domain they own can intercept STARTTLS sessions, including AUTH credentials and message bodies. Only boring-tls is affected (native-tls and rustls are fine); a two-line patch exists but hadn't shipped as of this advisory, so audit Cargo.lock for the boring-tls feature and pin to native-tls or rustls until a fixed release lands.

Pterodactyl Wings accepts any panel-signed JWT for file upload, letting subusers bypass file.create permission

Wings' /upload/file endpoint validates only that a JWT is panel-signed and carries server_uuid/user_uuid/unique_id — it doesn't check what the token was actually issued for, so a subuser can reuse a websocket or file-download token to upload arbitrary files without file.create permission. Any Pterodactyl-hosted game/app server where subusers are scoped to console-or-download-only access is exposed to unauthorized file writes on that server. Patch to panel 1.12.3 / wings 1.12.2.

Pterodactyl's shared global login rate-limit key lets one attacker lock out the entire panel

The authentication rate limiter on Pterodactyl's login and 2FA-checkpoint endpoints resolves to a single global cache key instead of one keyed per IP, because the fall-through Limit::perMinute(10) omits ->by($request->ip()). About 10 requests a minute from one unauthenticated attacker exhausts the shared bucket and 429s every user's login and 2FA attempts panel-wide, admins included, for as long as the burst repeats. No patched version was listed yet — front the login/checkpoint routes with your own per-IP rate limit at the reverse proxy until upstream ships the ->by($request->ip()) fix.

WordPress Coding Standards sniff eval()s attacker-controlled PHP during CI lint runs

The WordPress.WP.EnqueuedResourceParameters sniff reconstructs a function argument and runs it through eval() to test falsiness — so a crafted $ver argument like `'system'('id')` in third-party PHP executes on the scanning host the moment PHPCS lints it. Any CI pipeline that runs WordPressCS over external pull requests or untrusted plugin/theme code is a remote-code-execution vector, not just a linter false positive. Upgrade to WordPressCS 3.4.1, or exclude WordPress.WP.EnqueuedResourceParameters from your ruleset if you can't patch immediately.

Appium java-client's directConnect blindly follows server-supplied redirect host — network pivot to internal services

When directConnect(true) is set, java-client takes directConnectHost/Port/Path straight from the server's NEW_SESSION response and redirects all session traffic there — only the https scheme is checked, the destination host is never allowlisted. A rogue or compromised Appium server can point the client at 127.0.0.1, an internal RFC1918 host, or 169.254.169.254 and harvest cloud credentials via the instance-metadata endpoint; the advisory calls out CI/CD as the worst case since directConnect(true) is often set in a shared base config. If your test infrastructure points java-client at a server you don't fully trust, add an allowlist for directConnect targets or disable the feature until a patched release ships.

Pocket ID OIDC refresh tokens outlive authorization revocation, account disabling, and group removal

createTokenFromRefreshToken verifies the refresh token's signature and lookup but never re-checks whether the user's authorization still exists, whether the account is disabled, or whether group-based access restrictions still apply — so revoking a client's access, disabling a fired employee's account, or removing someone from an allowed group does nothing to a refresh token issued before the change. Each refresh rotates in a fresh 30-day token, so this is a real off-boarding gap: session-based access is correctly blocked by auth middleware, but the OIDC refresh path bypasses it entirely, meaning terminated employees keep working access to anything gated behind Pocket ID. If you use Pocket ID for OIDC, manually revoke or rotate downstream client secrets when disabling a user until upstream re-validates authorization state on every refresh.

Pocket ID reauthentication bypass yields full OIDC tokens without any passkey ceremony

Pocket ID's WebAuthn reauthentication fallback checks only that an access token's IssuedAt claim is under 60 seconds old — not how the user actually authenticated — and the accompanying session-cookie check accepts any arbitrary cookie value. An attacker who obtains a one-time access token (e.g. via email compromise) can exchange it, set a fake session cookie, and get a reauthentication token with zero passkey interaction, then use it to authorize an OIDC client explicitly configured to require passkey step-up — walking away with a 30-day renewable refresh token. GHSA rates this medium but the verified PoC shows full persistent impersonation of a passkey-gated client, so it's triaged here as high; if you gate sensitive OIDC clients behind Pocket ID's RequiresReauthentication, treat that protection as ineffective until upstream removes the access-token fallback or binds it to an auth_method claim.

@wakaru/cli arbitrary file write via crafted bundle during --unpack

wakaru's bundle unpacker sanitizes module filenames before writing, but overlapping traversal sequences like `....//` survive sanitization and normalize back into `../`, letting a crafted JS bundle write files outside the chosen output directory. This is the reverse-engineering-tool version of a path-traversal bug — anyone running `wakaru --unpack` against an untrusted bundle (malware analysis, dependency auditing) is the target audience most likely to hit it. Upgrade to @wakaru/cli 1.4.0 before unpacking anything you don't already trust.

GitHub MCP Server crashes on malformed completion/complete request — unauthenticated DoS

CompletionsHandler dereferences params.Ref without a nil check, so any client — no auth, no token validation required — that sends a completion/complete request with a missing or empty ref field panics the process and kills the server. Automated fuzzing found an 11.7% crash rate across 925 test cases, which says as much about how little malformed-input testing MCP servers get in general as it does about this bug specifically. If you run github-mcp-server exposed to any untrusted client, upgrade to 1.1.0; until then, don't put it on a network boundary you don't control.

Novu's SSRF guard misses the CGNAT range, exposing cloud metadata endpoints via Workflow HTTP step and webhook filters

Novu's shared validateUrlSsrf guard blocklists RFC1918/loopback/link-local but omits 100.64.0.0/10 (CGNAT shared address space), so a workflow HTTP-request step or webhook filter condition can still reach cloud-internal endpoints like Alibaba Cloud's 100.100.100.200 metadata service. It's a classic incomplete-denylist SSRF — the durable fix is CIDR-aware allow-only logic, not another range added to the regex. If you self-host Novu with user-configurable webhook/HTTP steps, treat it as SSRF-exposed until @novu/application-generic ships a fix past 3.17.0.

Cedar-Java's EntityIdentifier.equals() has inverted null/self-comparison logic

EntityIdentifier.equals() has its null-check and self-reference branches swapped, returning true for null comparisons and false for self-comparisons. Cedar's actual authorization decisions are computed in Rust from JSON and don't touch this Java method, so GHSA's high/8.8 rating overstates the real blast radius here — the risk is scoped to integrators who roll their own entity-identity equality checks on top of CedarJava. If you do that kind of comparison, upgrade to CedarJava 4.9+ and don't rely on .equals() for security-sensitive dedup until then.

nono-cli pack verification fails open when both trust bundle and lockfile entry are missing

nono's registry pack verifier fails closed when a trust bundle exists without a matching lockfile entry, but fails open — loads the pack anyway — when both are deleted, because the guard only covers the partial-removal case. Session hooks from a nono pack run on the host outside any sandbox, so this collapses provenance verification into "delete the right two files" for anything that executes with host privileges. If you use nono-installed packs for hooks or automation, audit ~/.config/nono/packages/ for any pack whose lockfile entry or trust bundle is missing and treat it as unverified until a patched nono-cli ships.

Nimbus Manticore (Iranian APT) deploys new NightLedger backdoor and WebSocket tunnelers against Middle East/Africa/South Asia targets

Nimbus Manticore (aka Mirage Kitten / UNC1549), the Iranian state-backed group, is running a fresh campaign with a previously undocumented Windows backdoor (NightLedger) and two custom WebSocket tunnelers against targets across the Middle East, Africa, and South Asia. Not a software-supply-chain compromise itself, but this is the same APT-grade tooling investment that increasingly shows up as the delivery stage for supply-chain-adjacent campaigns — worth tracking the group, no action needed today.

06:00 ET · Morning Watch

CISA KEV adds Arista VeloCloud Orchestrator command injection (CVE-2026-16812) — CVSS 10, actively exploited

Unauthenticated OS command injection (CWE-78) in the on-prem VeloCloud Orchestrator web interface — no auth, no user interaction, full host compromise, CVSS 10 on both v3.1 and v4.0. Arista confirms active exploitation and has published three attacker source IPs (8.19.75.217, 206.72.242.124, 206.72.242.162); a compromised VCO can pivot into the Edge devices it manages. If you run on-prem VCO (not Broadcom-hosted), patch to 5.2.3.14 / 6.1.3.4 / 6.4.2.4 / 7.0.0.1 now, block those IOCs, and audit web/backend logs for encoded URL patterns or unexpected command execution before CISA's July 30 due date.

CISA KEV adds FortiOS symlink-persistence patch bypass (CVE-2025-68686)

A crafted-HTTP-request bug lets an attacker who already has filesystem-level access from a separate prior FortiOS compromise bypass Fortinet's earlier fix for the symlink-based persistence technique — CVSS only 5.3, but CISA's KEV add means it's confirmed exploited in the wild as a re-persistence step, not a theoretical one. This matters most to anyone who thinks they already remediated a past FortiOS incident: patching per FG-IR-25-934 doesn't retroactively catch prior symlink persistence, so pair the patch with a forensic check for stale symlinks before the August 10 due date.

org.xwiki.contrib:discussions-server CSRF allows forged message deletion

The XWiki Discussions extension's message-delete endpoint doesn't validate CSRF tokens, so a crafted request from an authenticated user's browser can delete arbitrary discussion messages. Low blast radius — data loss, not takeover — but it's a one-liner CSRF-guard omission; upgrade to Discussion Extension 2.0-rc-1 if you run XWiki with this contrib module.