v vanemmerik.ai / SUPPLY-CHAIN
Supply Chain · Watch Wednesday · 22 July 2026 End-of-day synthesis 4 watches · 135 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 — Late escalation at 21:00 ET: a fourth disclosure wave — 50 more advisories spanning a second n8n batch plus first-time appearances from Next.js, Eclipse Jetty, JupyterLab, and LiteLLM — landed within 75 minutes of the day's 18:00 synthesis, pushing the day's total past 135 items and its high-severity count past 55.

Today's shape locked at 18:00 with three coordinated-disclosure batches — Gitea, n8n, Netty — and two new CISA KEV entries. Late escalation at 21:00 ET: a fourth wave landed within 75 minutes of that synthesis, adding 50 more GHSA advisories across six projects before the day was done.

n8n absorbed a second batch on top of this morning's eleven — 24 more items including a full Git-node remote-code-execution variant (crafted repo hooks running as the n8n process user), an expression-sandbox escape reaching system commands through arrow-function bodies, and three separate unparameterized-SQL-injection bugs across its MySQL, Postgres Trigger, and Snowflake nodes. Next.js, Eclipse Jetty, JupyterLab, and LiteLLM each had their first appearance of the day: Jetty's Digest authentication silently accepts a substituted password for any non-Latin-1 credential, JupyterLab's image viewer can escalate a crafted image into server-side code execution, and LiteLLM's MCP auth handler falls back to an authenticated session object on key-validation failure — letting an unauthenticated caller reach any configured MCP tool.

→ Operational priority for the night none of the 50 late items clears GHSA's critical bar and CISA added nothing new to KEV, so Friday's SharePoint and Check Point deadlines are still the top priority — but treat tonight's wave as equal-weight to this afternoon's batch, not an afterthought, and patch the LiteLLM MCP auth bypass and the second n8n Git-node RCE first, since both need only a fabricated header or a crafted local repo to reach unauthenticated-adjacent impact.

21:00 ET · Last Watch

n8n: Git Node fetch/pull/pushTags Operations Bypass Sandbox Path Restriction

The Git node's fetch, pull, and push-tags operations skip the repository-path containment check that clone and push already enforce, so an allowlisted remote value pointed at a local path outside the sandbox lets an authenticated user pull an arbitrary local git repo into the workspace and read its files and history. This opens tonight's second n8n disclosure batch — a fresh round on top of the one already covered in today's First Watch — and pairs with a full Git-node code-execution bug disclosed minutes later in this same batch. Patch to 1.123.67/2.31.5/2.32.1, or disable the node via NODES_EXCLUDE=n8n-nodes-base.git.

n8n: Authenticated code execution in the n8n Git node

Under default git security settings, the Git node lets an authenticated workflow author stage a crafted local repository whose hooks run as the n8n process user, giving full code execution on the host. This is the second Git-node bug in tonight's batch after the sandbox-path bypass above — same node, worse outcome, and it works on both self-hosted and cloud instances. Patch to 1.123.67/2.31.5/2.32.1, or disable the node via NODES_EXCLUDE=n8n-nodes-base.git.

n8n: Send Email Node Arbitrary File Read and SSRF via Nodemailer Content-Object Type Confusion

The Send Email node doesn't enforce that message fields are strings, so a crafted non-string value from a workflow expression gets treated by the underlying Nodemailer library as a file path or URL, disclosing local files on the host. Exploitation needs a pre-existing unauthenticated webhook wired to untrusted input in the body field plus configured SMTP credentials, so it's not a default configuration, but it's a real pattern across n8n's mail-adjacent nodes. Audit workflows for untrusted data mapped into Send Email body fields, then patch to 1.123.67/2.31.5/2.32.1.

n8n: Expression sandbox escape via arrow-function bodies enabling command execution

Crafted expressions using arrow-function bodies bypass n8n's expression sandbox and trigger unintended system command execution on the host. Third distinct RCE-class primitive in tonight's n8n batch alongside the two Git-node bugs above — workflow-edit permission is becoming the real trust boundary in this disclosure round, not the sandbox. Upgrade to 2.31.5/2.32.1 and restrict workflow creation/editing to trusted users in the meantime.

n8n: Credential Authorization Bypass via Expression in HTTP Request Node `genericAuthType`

The pre-execution permission check on the HTTP Request node compares the unresolved genericAuthType expression instead of the real credential type, so a shared-workflow editor can reference another user's credential through an expression and have it load at execution time, skipping the ownership check entirely. First of two credential-exfiltration-via-expression bugs in tonight's batch — the inline sub-workflow JSON variant follows immediately after. Patch to 1.123.67/2.31.5/2.32.1 and audit who can see credential IDs in shared workflows.

n8n: Shared-Workflow Editor Can Exfiltrate Credentials via Inline Sub-Workflow JSON

n8n's credential-access checks only validate a node's top-level credentials, not credentials referenced inside an Execute Sub-workflow node's inline JSON, so an editor on a shared workflow can slot in a credential ID they were never granted and have it resolve in the parent workflow's project context. Same authorization-check-misses-a-nested-path shape as the HTTP node bug just above — two variants of the same root cause disclosed back to back tonight. Patch to 1.123.67/2.31.5/2.32.1 and review shared workflows' Execute Sub-workflow nodes with Source=Parameter for unexpected credential references.

n8n: Edit Image Node Format Injection Allows Arbitrary File Write

The Edit Image node passes its output format to the underlying image library unvalidated, so a crafted format value writes bytes outside the node's working directory — arbitrary file write for any user who can run workflows. Patch to 1.123.67/2.31.5/2.32.1, or disable the node via NODES_EXCLUDE=n8n-nodes-base.editImage in the meantime.

n8n: Prototype Pollution via Dot-Notation Field Names Leads To Instance-Wide Denial of Service

The Edit Fields (Set) node's dot-notation path setter doesn't restrict field names, so naming a field after an inherited built-in method path corrupts a shared global in the main Node.js process — and because that global sits on the request-authentication path, every authenticated request on the instance starts failing until the process restarts. First of two prototype-pollution DoS bugs in tonight's batch; the VM expression-engine variant follows two entries later. Patch to 1.123.67/2.31.5/2.32.1 and watch for unexplained instance-wide HTTP 500s.

LiteLLM: MCP Authentication Bypass via OAuth2 Passthrough Fallback

LiteLLM's MCP auth handler falls back to an empty UserAPIKeyAuth() object when key validation fails during OAuth2 passthrough, so an unauthenticated attacker with a fabricated Authorization header can establish an authenticated MCP session and list or call any configured MCP tool. The most severe of tonight's four LiteLLM bugs — full unauthenticated access to whatever services are wired up via MCP. Patch to 1.84.0, or block /mcp/ routes at the gateway until then.

Eclipse Jetty Digest Authentication: ISO-8859-1 lossy encoding allows authentication bypass via character substitution

DigestAuthentication.apply() hashes the password with ISO-8859-1, which silently collapses any character above U+00FF (CJK, Cyrillic, Arabic, emoji) to a single '?' byte, so an attacker who knows a victim's username can authenticate by replacing every non-Latin-1 character in the real password with '?' and producing an identical MD5 digest. Opens tonight's five-item Jetty cluster, and it doubles as a functional-correctness bug — any user with a non-ASCII password may never be able to Digest-auth successfully even legitimately. Patch when a fixed version is published; treat any Digest-auth deployment with non-Latin-1 passwords as currently unsound.

Eclipse Jetty: DoS attack triggering OutOfMemory with 100-Continue requests

Any request with a body where a body-read ends up reading zero bytes leaks a buffer — most reliably triggered via 100-Continue requests or slow networks — leading to unbounded memory growth and eventual OOM. Highest-severity of tonight's five Jetty bugs and affects only the already-EOL 10.0/11.0 branches (fixed in 10.0.23/11.0.23); no workaround exists besides upgrading, so EOL branches running this code have no mitigation path.

Next.js: Denial of Service in App Router using Server Actions

Crafted requests against App Router apps with at least one Server Action can drive excessive CPU usage that blocks further request processing in the same worker process. First of nine entirely-new Next.js disclosures tonight — a separate project from the n8n/Jetty/Dompdf batches above, not a continuation of anything from earlier today. No workaround besides upgrading to 15.5.21/16.2.11; Pages Router apps and apps without Server Actions aren't affected.

Next.js: Middleware / Proxy bypass in App Router applications using Turbopack and single locale

App Router apps built with Turbopack and a single entry in config.i18n.locales can have their middleware/proxy-based authentication bypassed via crafted requests. Second Next.js bug in tonight's batch and the most directly dangerous — anyone relying on middleware alone for auth on an affected build should treat it as bypassed now. Patch to 16.2.11, or move authorization into the page's server-side data path rather than middleware.

Next.js: Server-Side Request Forgery in rewrites via attacker-controlled destination hostname

A rewrites() or redirects() rule that builds its destination hostname from a request-controlled dynamic segment (a path param or a has capture) can be pointed at an arbitrary hostname — Next.js proxies the request there and serves the response from the app's own origin, giving SSRF on rewrites and open redirect on redirects. Second SSRF-class bug in tonight's Next.js batch, alongside the Server Actions SSRF further down. Patch to 15.5.21/16.2.11, or constrain dynamic hostname segments to a hostname-safe character class.

Next.js: Server-Side Request Forgery in Server Actions on custom servers

When a Server Action forwards or redirects a request on a custom server where the incoming Host header isn't pinned, an attacker who controls Host-associated headers can steer the server's outbound request to a malicious host, and in some configurations weaken middleware/proxy authorization along the way. Managed hosting and next start/standalone from 14.2+ already pin the host and aren't affected — this is specifically a custom-server gap, and the third SSRF-flavored bug in tonight's nine-item Next.js batch. Patch to 15.5.21/16.2.11, or pin Host/X-Forwarded-Host at your edge and set __NEXT_PRIVATE_ORIGIN.

JupyterLab: Image viewer allows XSS when opening malicious image in new browser tab

A specially-crafted image opened through JupyterLab's image viewer and then opened in a new browser tab triggers XSS, which JupyterLab's own advisory says can escalate to remote code execution on the server. Highest-severity of tonight's five JupyterLab bugs. Patch to 4.6.2/4.5.10, or disable the image viewer plugin (jupyter labextension disable @jupyterlab/imageviewer-extension:plugin) in the meantime.

JupyterLab: Cross-site scripting (XSS) via crafted settings file (`overrides.json`)

A crafted overrides.json settings file, imported via the Settings Editor's Import button or planted on a shared multi-tenant filesystem where JupyterLab auto-loads it at startup, can embed instructions that execute as code instead of just changing a display preference — reading/modifying the victim's notebooks and running code against any connected kernel. Second high-severity JupyterLab bug in tonight's batch alongside the image-viewer XSS; both hinge on content that looks inert (an image, a settings file) actually being executable. No workaround — patch to 4.6.2/4.5.10, and on shared filesystems lock down write permissions on the settings directory.

n8n: SSRF Protection Bypass via MCP Client Node

With SSRF protection enabled, the MCP Client node sends requests to a user-supplied endpoint without routing through that protection or pinning the resolved address, so a workflow author can reach internal or blocked hosts and read the response back through the workflow. First of several SSRF-adjacent bypasses in tonight's n8n batch — the GraphQL node and computer-use path-confinement bugs later in this same drop share the pattern of a protection that exists but doesn't cover every node. Upgrade to 2.31.5/2.32.1 or exclude the MCP Client node via NODES_EXCLUDE.

n8n: Prototype Pollution via VM Expression Engine Sandbox Escape Leads to Denial of Service

The VM expression engine's array-element access can be abused to obtain a reference to a host built-in and pollute its prototype in the main process, crashing the instance for all users. Second prototype-pollution DoS in tonight's n8n batch, same blast radius as the Set-node variant above but reached through the expression engine instead of a node. Patch to 1.123.67/2.31.5/2.32.1, or disable the VM expression engine if an alternative is configured.

n8n: Path-Confinement Bypass in computer-use search_files Allows Reading Files Outside the Base Directory

The @n8n/computer-use file-search tool's base-directory confinement check can be bypassed with a crafted search pattern, letting the tool return names and contents of files anywhere the daemon's OS user can read. Only affects deployments running the computer-use package with AI agent workflows; disable it or run n8n under a dedicated low-privilege user until 2.31.5/2.32.1 lands.

n8n: External Secrets Permission Bypass via Expression Parser Mismatch

A mismatch between the static credential-form validator and the runtime expression engine lets a user with credential create/update rights but no externalSecret:list scope embed external-secret references in forms the validator misses, which then resolve in plaintext at execution time. First of two external-secrets exposure bugs in tonight's batch — the sibling issue below skips validation from a different angle entirely. Only affects instances with an external secrets provider and Advanced Permissions configured; patch to 1.123.61/2.27.4/2.28.1.

n8n: MySQL v1 Node executeQuery Operation Allows SQL Injection via Unparameterized Expression Interpolation

The legacy MySQL v1 node's executeQuery operation substitutes evaluated {{ }} expression values directly into the raw SQL string with no parameterization, so a workflow wired to an externally-reachable trigger gives attacker-controlled input a direct SQL-injection path with the configured credential's privileges. First of three SQL-injection disclosures in tonight's n8n batch — Postgres Trigger and Snowflake variants follow later. Migrate to the parameterized MySQL v2 node, or patch to 1.123.61/2.27.4/2.28.1.

n8n: External Secrets Accessible via Workflow Expressions Outside Credentials

External secrets resolve inside workflow node expressions even though they're only meant to be reachable through credentials, so a project editor can read a secret's plaintext value just by referencing it in a node expression, no secrets-access permission required. Second external-secrets bug in this batch alongside the permission-bypass issue above — between them, the external-secrets access model is getting a real workout tonight. Patch to 2.27.4/2.28.1.

n8n: Improper Authorization Allows Authenticated Users to Assign Workflows to Folders in Other Projects

A crafted workflow-creation request payload lets a user bypass project/folder authorization boundaries and associate their new workflow with a folder belonging to a project they don't have access to; the workflow stays in the attacker's own project and no cross-project data is exposed. Low-impact — a logical integrity violation of folder structure at the DB level, not a disclosure. Patch to 2.28.0.

n8n: Authenticated Users Can Exhaust Temporary Disk Storage via Data-Table File Uploads

Repeated uploads to the data-table upload endpoint bypass the per-request quota check, which doesn't account for files already written to the shared temp directory, so files accumulate until the periodic cleanup runs and can exhaust disk on the host. No patched version listed yet — set uploadMaxFileSize low and alert on temp-directory disk usage in the meantime.

n8n: computer-use Shell Sandbox Not Enforced on Linux and Windows

The @n8n/computer-use shell tool only applies its sandbox restrictions on macOS — on Linux and Windows, shell commands from the agent process run with unrestricted filesystem and network access. Second computer-use package bug in tonight's batch after the path-confinement issue above; this package is having a rough disclosure round. Patch to 2.29.8/2.30.1, which adds bubblewrap enforcement on Linux and disables the shell tool if sandboxing can't be established.

n8n: Member-Level Users Can Execute Other Users' MCP Server Trigger Workflows via Missing OAuth Authorization Check

The OAuth 2.1 consent flow for MCP Server Trigger workflows never checks that the authenticated user actually has access to the workflow being used as the OAuth resource, so a member-level user can self-approve consent for another user's workflow and get a token that runs it in the owner's project context with the owner's credentials. Breaks user/project isolation outright — the attacker sets tool inputs and reads outputs from the owner's connected integrations, and the resulting executions show up under the owner's account. Patch to 2.29.8/2.30.1.

n8n: GraphQL Node Bypasses "Allowed HTTP Request Domains" Restriction

Unlike the HTTP Request node, the GraphQL node never enforces the "Allowed HTTP Request Domains" restriction on HTTP-based credentials, so a workflow author can point its endpoint at a server they control and exfiltrate credentials that were supposed to be domain-locked. Second SSRF/domain-restriction-adjacent bypass in tonight's n8n batch, after the MCP Client SSRF issue near the top. Patch to 1.123.64/2.29.8/2.30.1.

n8n: Unauthenticated Endpoint Allows Cancellation of Any User's Active Test Webhook

DELETE /test-webhook/:id is registered before the auth middleware runs, so any unauthenticated caller who knows a workflow ID can cancel that workflow's active test webhook. Impact is limited to disrupting in-progress test sessions — production webhooks and stored data aren't touched. No patched version listed yet; restrict network access to the instance in the meantime.

LiteLLM: Arbitrary file write via path traversal in Skills archive extraction

LiteLLM's Skills archive extraction doesn't validate paths inside uploaded ZIP archives, so an authenticated user with skills-route access can upload a crafted archive whose path-traversal entries write outside the intended staging directory when the skill is processed — arbitrary file write, and potentially code execution depending on what's writable. First of four LiteLLM disclosures tonight, all proxy-side. Patch to 1.83.7-stable, or block POST /v1/skills at the gateway.

Dompdf: Uncontrolled resource consumption based on declared BMP dimensions

Dompdf trusts a BMP's declared header width/height with no pixel-count bound before allocating the canvas through GD, so a 58-byte crafted BMP inlined as a data: URI in attacker HTML can drive ~400MB of native memory and 5 seconds of CPU per request — and because the allocation happens in GD's native allocator, PHP's memory_limit doesn't cap it. First of three new Dompdf resource-exhaustion/disclosure bugs tonight, a second wave for this library on top of the Dompdf items already covered earlier today. Patch to 3.1.6.

Dompdf: Denial of Service (DoS) via Resource Exhaustion using Oversized Image Bitmaps

A high-entropy 30,000×30,000 noise image, base64-inlined in HTML, defeats Dompdf's dimension safeguards and forces ~1.2GB of allocation and CPU saturation during rendering, crashing the PHP process. Second Dompdf DoS in tonight's batch alongside the BMP bug above — both share the same root gap of trusting declared/apparent image cost over actual decode cost. Patch to 3.1.6.

Dompdf: Embedded SVG images can leak existence of files and directories within the filesystem

An embedded SVG's <image href="file:///..."> reference renders differently depending on whether the referenced file or directory exists on the server, giving an attacker who controls HTML rendered by Dompdf a filesystem existence oracle. Third Dompdf disclosure tonight — lower severity than the two DoS bugs above, but the same root cause of trusting attacker-supplied paths into image processing. Patch to 3.1.6.

n8n: Custom Header Credential Values Leaked in Plaintext into LLM Node Execution Data

Custom HTTP headers configured on LLM sub-node credentials (OpenAI, Anthropic, Lemonade) are masked in the UI but written to execution data in plaintext, so any authenticated user with access to a workflow's execution data can read the API keys stored there — and since execution data persists and exports, exposure outlives the run. Rotate any keys stored as custom headers on LLM credentials and patch to 1.123.64/2.29.8/2.30.1.

Eclipse Jetty: Cross-Request Leakage for trailers on HTTP/1.1 keep-alive connections

HttpConnection never resets its connection-scoped _trailers field between requests on the same HTTP/1.1 keep-alive connection, so trailers from request N (e.g. a checksum header) leak into request N+1, and app logic that branches on getTrailers() != null gets stale data — including a TOCTOU shape where a trailer-gated check passes based on the wrong request. Don't rely on request trailers for security-sensitive logic until patched, or disable persistent connections.

Eclipse Jetty: HTTP Authority/Host mismatch

Jetty checks that the HTTP/1.1 Host header matches the :authority pseudo-header, but the equivalent check is missing on the HTTP/2 and HTTP/3 paths, so a single request can carry two conflicting host identities through the server — one that HttpURI-based logic sees, another that raw-header logic sees. Second host/identity-confusion bug in tonight's Jetty batch; anything doing host-based ACLs, virtual-host isolation, or redirect/callback construction over H2/H3 should treat those checks as bypassable until fixed. No patched version listed yet.

Eclipse Jetty: Path parameter traversal

URIUtil.canonicalPath() mishandles a semicolon path-parameter marker followed by a dot-segment (e.g. /public;/../admin/secret) — a stale local variable means the following '../' isn't flagged as non-normal, so the raw non-normalized path reaches SecurityHandler.PathMapped and slips past a protected /admin/* prefix constraint unauthenticated. Third Jetty bug in tonight's batch and the most directly exploitable — a straight path-based ACL bypass, not just an information mismatch. No patched version listed yet; audit any PathMapped security constraints for equivalent bypass strings.

Next.js: Unauthenticated disclosure of internal Server Function endpoints

Server Action and use cache endpoint IDs get disclosed to unauthenticated users through publicly served static chunks, bypassing whatever auth normally gates the pages that reference them. By itself it's a recon/enumeration primitive, but it compounds with other weaknesses — never assume auth at the use cache/use server boundary, always authenticate inside it. Patch to 15.5.21/16.2.11.

Next.js: Denial of Service in the Image Optimization API using SVGs

When self-hosting Next.js with remotePatterns configured, malicious remotely-hosted images optimized through /_next/image can cause CPU exhaustion. Only remotePatterns-configured deployments are affected — unoptimized: true, a custom loader, or Vercel hosting are all unaffected. Patch to 15.5.21/16.2.11, or set experimental.imgOptSkipMetadata: true as a stopgap.

Next.js: Unbounded Server Action payload in Edge runtime

Server Actions running on the Edge runtime don't bound request body size, so a crafted request causes excessive memory consumption. Only affects Server Actions specifically configured for the Edge runtime. Patch to 15.5.21/16.2.11, or have your hosting provider cap request body size at 5 MiB as a stopgap.

Next.js: Cache confusion of response bodies for requests with bodies containing invalid UTF-8 byte sequences

A server-side fetch with a non-UTF-8 request body (e.g. UTF-16) can return a cached response body from a different request to the same URL, leaking one caller's response data to another. First of two nearly-identical fetch-cache-confusion bugs disclosed back to back in tonight's Next.js batch — this one keyed on body encoding, the next on differing fetch init. Patch to 15.5.21/16.2.11; Pages Router apps aren't affected.

Next.js: Cache confusion of response bodies for requests with bodies

The same POST-response cache-leak shape as the encoding variant above, but triggered when fetch(new Request(init), aDifferentInit) is called with mismatched init objects — the cached response body from one request can be served for another. No workaround besides upgrading to 15.5.21/16.2.11; Pages Router apps aren't affected.

JupyterLab PluginManager lock-rule enforcement bypass

Direct requests to /lab/api/plugins let an authenticated user re-enable or disable plugins an administrator locked, for both child plugins of multi-plugin extensions and a "lock all" directive — the enforcement gap is server-side, not just missing in the UI. Any hardening implemented via locked plugins (download/upload limits, etc.) is circumventable on unpatched instances. Patch to 4.6.2/4.5.10.

JupyterLab: PyPI extension blocklist package-name canonicalization bypass

The PyPI extension manager's blocklist comparison uses weaker name-normalization than PyPI's actual package-name canonicalization, so a blocklisted package like jupyterlab-git can still be installed under an equivalent spelling such as JupyterLab.Git that pip resolves to the same package. Second plugin/extension-control bypass in tonight's JupyterLab batch alongside the lock-rule issue above — both defeat an admin-configured allowlist/blocklist rather than granting new access the user didn't already have. Patch to 4.6.2/4.5.10.

n8n: Cross-Tenant Module-Cache Poisoning in the JS Task Runner

n8n's JavaScript task runner shares one module cache across all users' Code-node executions, so a user running a Code node can poison a cached module and alter other users' executions on the same runner — a cross-user isolation break, not a sandbox escape or RCE. Affects any multi-user instance running the JS task runner with built-in or external modules enabled. Patch to 1.123.67/2.31.5/2.32.1, or unset NODE_FUNCTION_ALLOW_BUILTIN/EXTERNAL to remove the poisonable surface.

n8n: PostgresTrigger Node SQL Injection Allows Authenticated Users to Execute Arbitrary SQL on Connected PostgreSQL Instances

The Postgres Trigger node interpolates user-supplied channel, function, and trigger-name parameters straight into SQL without escaping, giving an authenticated user full read/write on the connected PostgreSQL database via the configured credential's privileges. Second of tonight's three n8n SQL-injection disclosures, following the MySQL v1 executeQuery bug earlier in this batch. Patch to 1.123.67/2.31.5/2.32.1 and make sure Postgres credentials aren't running as SUPERUSER.

n8n: Snowflake Node executeQuery Operation Allows SQL Injection via Unparameterized Expression Interpolation

The Snowflake node's Execute Query operation interpolates expression values directly into the SQL string — the same unparameterized-interpolation shape as tonight's MySQL and Postgres Trigger bugs, and the third SQL injection in this single n8n batch. Requires a workflow author to have already embedded untrusted expression data in a raw query. Patch to 1.123.67/2.31.5/2.32.1, which adds a parameterized Query Parameters field as the fix.

LiteLLM: Local file read via request-supplied OIDC file references

The /health/test_connection endpoint resolves request-supplied oidc/file/ references in litellm_params, letting a proxy admin or other privileged caller read arbitrary local files. Treated as defense-in-depth since it already requires privileged proxy access. Patch to 1.83.10-stable, or restrict test_connection to trusted admins.

LiteLLM: Custom Code Guardrails production endpoints bypass code safety checks

The production create/update paths for Custom Code Guardrails skip the sandboxing and validation the test endpoint applies, so a privileged user can submit Python that executes directly in the proxy container — and in deployments without a configured master key, any caller may be treated as an admin, making this reachable without real authorization. Set LITELLM_MASTER_KEY and restrict guardrail management to trusted admins; patch to 1.82.0-stable.

JupyterLab: Allowlist/blocklist check in `PyPIExtensionManager.install()` not enforced for direct callers (missing `await`)

PyPIExtensionManager.install() never awaits its own allowlist/blocklist coroutine, so the check silently no-ops for any custom extension or downstream integration that calls install() directly — the stock HTTP handler is unaffected since it performs its own separately-awaited check first. Low impact, narrow blast radius: only bites deployments combining a custom install()-calling integration, a configured allowlist, and kernels/terminals disabled. Patch to jupyterlab 4.6.2/4.5.10.

18:00 ET · First Watch

CISA Adds Microsoft SharePoint Deserialization RCE to KEV

CISA added CVE-2026-50522 to the Known Exploited Vulnerabilities catalog today — an unauthenticated deserialization bug in SharePoint that gives remote code execution over the network, with a three-day remediation deadline (2026-07-25) under BOD 26-04. SharePoint deserialization RCEs have a track record of turning into mass-exploitation events within days of a KEV listing; patch internet-facing SharePoint now and don't wait for the deadline.

CISA Adds Check Point SmartConsole Authentication Bypass to KEV

The second KEV add today: an unauthenticated remote attacker can obtain a SmartConsole login token and authenticate with full administrative privileges over a firewall management console. Same due date as the SharePoint entry above (2026-07-25) — if SmartConsole is reachable from anywhere untrusted, treat this as the higher-priority of the two, since it's a management-plane compromise of your perimeter rather than an app-layer one.

n8n: Token Exchange JWTs Get Full Public API Scope Regardless of Role

Token Exchange issues JWTs with every Public API scope attached, so a low-privileged user with a trusted external JWT can call admin-only endpoints — role escalation, user creation, user deletion. Only bites instances running Token Exchange plus the Public API; if that's you, patch to 2.29.8/2.30.1 before anything else in this batch.

n8n: Cross-Issuer Token Exchange Binds Different Users to the Same Account by Subject Claim Alone

With more than one trusted token-exchange issuer configured, n8n resolves identity from the JWT's sub claim only — ignoring iss — so two issuers emitting the same subject value collide into one local account. An attacker holding a token from any trusted issuer with a matching sub authenticates as that victim. Reduce to a single trusted issuer until you're on 2.28.1.

n8n: AI Agents MCP Connector Bypasses Credential Domain Restrictions

The AI Agents module doesn't enforce a shared credential's 'Allowed HTTP Request Domains' restriction, so a member with use-only access can point an MCP tool at a server they control and exfiltrate the credential secret. Only relevant if N8N_ENABLED_MODULES=agents is set and domain-restricted credentials are shared with members — disable the agents module or restrict sharing until 2.27.4/2.28.1.

n8n: Prototype Pollution via Workflow Credentials Leads to Unauthenticated Enumeration and Auth Bypass

Any user with the default workflow:create permission can pollute Object.prototype through a crafted saved or imported workflow, which cascades into treating unauthenticated requests as privileged and exposing every account's email, role, and MFA status plus all project listings — and can corrupt global state until the instance restarts. This is the sharpest of today's n8n batch: a normal-permission user gets unauthenticated data disclosure across the whole instance. Patch to 1.123.61/2.27.4/2.28.1 now.

n8n: Pagination Expressions Leak Shared Credential Headers

A use-only editor on a shared workflow can read a credential's Authorization header through $request.headers inside an HTTP Request node's pagination expression, then copy it into item data and exfiltrate it via a later node — bypassing the credential's own domain restriction since the secret leaves through item data, not the credential's request path. Only bites N8N_EXPRESSION_ENGINE=vm instances with shared paginated-request workflows; patch to 1.123.61/2.27.4/2.28.1.

n8n: Stored XSS via Resource Locator cachedResultUrl

The Resource Locator passes a workflow-persisted cachedResultUrl straight to window.open() with no scheme validation, so a crafted workflow runs script in the victim's browser when they interact with the link. Patch to 1.123.64/2.29.8/2.30.1; audit existing workflows for non-HTTP(S) cachedResultUrl values in the meantime.

n8n: Unsandboxed iframe srcdoc in HTML Preview Allows Same-Origin Script Execution

The HTML/binary preview renders execution output into an iframe srcdoc without a sandbox attribute, so a sanitizer bypass executes script same-origin with the editor and can call authenticated APIs as the victim. Reachable by any global:member account; patch to 1.123.64/2.29.8/2.30.1 or set a CSP blocking inline scripts as a stopgap.

n8n: TOCTOU Race in Git Clone Node Yields Remote Code Execution

An authenticated user can swap a directory for a symlink between the Git node's path validation and the actual clone, planting a crafted repo in the community node directory that n8n loads as a custom node on next restart — and nodes execute JavaScript, so this is full RCE on the server. Both self-hosted and cloud are affected wherever the Git node is enabled; disable it via NODES_EXCLUDE=n8n-nodes-base.git until a patched version ships, since none is listed in the advisory yet.

n8n: Project Viewer Escalates to Node Execution via AI Agent Tool Chat

The AI Agents node-execution tool checks only the agent:execute scope, not whether the requesting user can execute nodes or access the project's credentials — so a read-only Project Viewer who chats with an agent that has node tools enabled can run arbitrary tool nodes with the project's credentials. On instances with a command- or file-capable tool node (Execute Command, SSH) enabled, this extends to host command execution. Patch to 2.29.8/2.30.1. Eleven n8n advisories landed in this one clustered publish — treat it the way this watch treated the Gitea batch and patch the whole set together rather than cherry-picking.

Netty: Malformed Bzip2 Stream Hangs the Event-Loop Thread Forever

A crafted bzip2 stream drives Bzip2BlockDecompressor's RLE state machine into an infinite loop that permanently captures the event-loop thread — since Netty multiplexes many connections per event loop, one bad stream can stall everything sharing that loop, not just its own connection. Anyone decompressing untrusted bzip2 input through Netty should treat this as a priority patch; the DoS blast radius is wider than a typical single-connection hang.

Netty: TOCTOU in OCSP Server-Certificate Validator Lets Data Flow Before Revocation Check Completes

OcspServerCertificateValidator fires the TLS handshake-complete event before its own async OCSP query resolves, so downstream handlers start sending application data immediately — if the OCSP response later comes back REVOKED, the channel closes, but requests already sent to the revoked server got through. First of three related OCSP validator bugs disclosed together; see the stale-response and CertificateID findings below.

Netty: Expired OCSP Responses Still Validate as GOOD

The freshness check in OcspServerCertificateValidator is missing a return statement, so an out-of-date GOOD response still fires a VALID event instead of failing closed — and since nonce validation is off by default, freshness was the only replay defense in place. Combined with the TOCTOU bug above, an on-path attacker gets a real window to replay a stale GOOD response against a since-revoked certificate.

Netty: OcspClient Never Checks the Response's CertificateID Matches the Request

OcspClient verifies an OCSP response's signature but never confirms the CertificateID inside it matches the certificate being validated — so a GOOD response for any other certificate from the same CA can be replayed to vouch for a revoked one. Third and most direct of this batch's OCSP findings: the signature check, the freshness check, and this identity check all need to be right together, or the individual patches don't add up to real revocation checking.

Netty XML: XmlDecoder Instantiates Parser with DTD and External Entities Enabled

XmlDecoder hands DOCTYPE-bearing XML to a parser with no security hardening; whether entities actually resolve depends on Aalto XML's async-parser behavior, making this a confirmed misconfiguration with conditional exploitability rather than a guaranteed XXE. Anyone piping untrusted XML through Netty's XmlDecoder should harden the underlying parser explicitly rather than rely on upstream defaults.

Netty: Unbounded Buffering of HTTP/3 Reserved Frame Types Exhausts Memory

Http3FrameCodec trusts a wire-supplied payload length up to Integer.MAX_VALUE for reserved frame types with no cap, so a peer opening multiple streams with oversized reserved frames drives the server toward OOM. Anyone running Netty's HTTP/3 support in production should treat this as a priority patch — QUIC/HTTP3 deployments tend to be newer and less hardened against this class of amplification.

Netty: SPDY Decoder Leaks Pooled Memory on RST_STREAM

SpdyHttpDecoder allocates a pooled ByteBuf per SYN_STREAM and never releases it when the stream is reset or exceeds maxContentLength — the map entry is removed but the buffer isn't, so repeated RST_STREAM traffic permanently leaks native memory. SPDY is legacy at this point; if you're not actively serving it, disable the codec rather than patch around it.

Netty: Signed-Byte Bug Traps HAProxy Decoder in an Unbounded Buffering Loop

HAProxyMessageDecoder reads the protocol version byte as a signed Java byte without masking; a PROXY protocol v2 prefix followed by version byte 0xFF sign-extends to -1, colliding with the decoder's own 'need more data' sentinel. The decoder never advances, never enforces header size limits, and ByteToMessageDecoder accumulates every subsequent byte into an unbounded buffer until direct memory is exhausted — a single crafted 13-byte prefix is enough to trigger it.

Netty: SPDY zlib Header Decoding Keeps Inflating After maxHeaderSize Truncation

A 12KB compressed SPDY header block can declare a 12MiB header-name field, and Netty keeps inflating it even after the raw parser has already marked the frame truncated by maxHeaderSize — compression-amplified decode work the size limit was supposed to prevent. Legacy-codec DoS in the same family as the SETTINGS and RST_STREAM SPDY bugs in this batch; disable the SPDY codec if you're not using it.

Netty: SPDY SETTINGS Frame Materializes a 262,144-Entry Map from One Frame

The SPDY SETTINGS decoder accepts a peer-declared entry count up to the 24-bit frame-length limit with no implementation-side cap, so one roughly 2MiB SETTINGS frame forces 262,144 map-entry insertions. Third SPDY-codec DoS disclosed in this batch alongside the RST_STREAM leak and zlib-expansion bugs above — if SPDY is enabled anywhere in your stack for legacy-client compatibility, this is a good day to turn it off instead of patching three separate bugs in a protocol nobody's shipping new clients for.

n8n: Authenticated SSRF via Dynamic Node Parameters Endpoints

/rest/dynamic-node-parameters/ skipped authorization scopes entirely and let a caller override a node's declared baseURL with an absolute URL, reaching arbitrary internal targets when N8N_SSRF_PROTECTION_ENABLED is off (the default). Upgrade to 1.123.64 / 2.29.8 / 2.30.1, or set N8N_SSRF_PROTECTION_ENABLED=true as a stopgap.

n8n: Google Service Account Private Key Leaked in JWT Header

n8n placed the full PEM private key in a JWT's kid field instead of a key identifier — Base64-encoded, not encrypted, so anything that logs or inspects the JWT recovers the key and can impersonate the service account against Google Cloud. Rotate any Google Service Account key used with an affected instance and patch to 1.123.64/2.29.8/2.30.1.

Netty: CRLF Injection via Multipart Filename in HttpPostRequestEncoder

HttpPostRequestEncoder writes a multipart upload's filename into the Content-Disposition header without CRLF sanitization, so an attacker who controls a filename can inject headers or spoof Content-Type on the server assembling the request (CVSS 3.1 8.1 per the researcher's report, though GHSA lists it medium). First of a large same-day Netty disclosure batch — see the related SPDY, HAProxy, and STOMP findings below; all trace to the same class of unsanitized-header-write bug across different codecs.

Netty: STOMP CONNECT Frame Header Injection

StompSubframeEncoder writes header values into CONNECT frames without CRLF neutralization, letting a value with embedded CRLFs inject additional STOMP headers. Same injection root cause as the multipart-filename and HAProxy findings in this batch — anything building STOMP frames from user input needs a sanitization pass, not just Netty's fix.

Netty: HAProxy V1 Protocol CRLF Injection via AF_UNIX Address

HAProxyMessageEncoder writes source/destination addresses straight into the PROXY protocol v1 line without CRLF validation, and the AF_UNIX address path only checks length, not content — a crafted AF_UNIX address injects a fabricated PROXY line and spoofs the client IP the backend sees. Relevant to anyone terminating PROXY protocol behind Netty; same 'encoder trusts the input' shape as this batch's other CRLF findings.

Netty: Duplicate Host Headers Survive HTTP/2-to-HTTP/1.x Translation

When an HTTP/2 client sends both :authority and a literal host header with different values, Netty's translation layer maps both through instead of deduplicating, producing an HttpRequest with two conflicting Host headers. Anything downstream that trusts the first (or last) Host header for routing decisions can be steered to the wrong backend — audit reverse-proxy configs sitting behind Netty's HTTP/2 front end.

Netty: HttpContentEncoder's Unbounded Queue Enables Pipelining DoS

HttpContentCompressor's underlying acceptEncodingQueue grows without a size limit on the I/O thread for every inbound request and only drains on response; an attacker pipelining HTTP/1.1 requests faster than the application answers exhausts memory. Any Netty-based server that compresses responses and allows pipelining is exposed — cap concurrent pipelined requests per connection as a mitigation.

Netty: WebSocket V07/V08 Handshaker Skips Connection/Upgrade Header Validation

Sending Sec-WebSocket-Version: 7 with no Connection: Upgrade or Upgrade: websocket header still completes a protocol switch through the lax V07/V08 handshaker — a proxy in front won't recognize it as an Upgrade request, opening the door to request smuggling and protocol-confusion attacks against whatever sits between client and Netty.

Netty: CorsHandler's shortCircuit() Protection Bypassed by Origin: null

A logical-operator error in CorsHandler's origin evaluation means a request with Origin: null slips past the shortCircuit() rejection meant to stop unauthorized cross-origin requests before they reach the backend. If you rely on shortCircuit as an access-control layer rather than just a CORS-header convenience, it currently isn't one — patch or add origin validation ahead of Netty.

Dompdf: SVG data-URI Images Bypass chroot to Read Arbitrary Local Files

dompdf blocks direct file:// references outside its chroot, but an SVG image embedded as a data-URI reaches Options::validateLocalUri() through a different path that doesn't apply the same restriction, letting attacker-controlled HTML read arbitrary server files in the default configuration. Exploitable out of the box wherever dompdf renders untrusted HTML — patch immediately, this is the highest-impact of today's three dompdf findings.

Dompdf: @font-face file:// References Leak File Existence via Memory-Exhaustion Timing

Repeated file:// references in a CSS @font-face declaration exhaust PHP's memory limit only when the target file exists — the absence case fails fast — turning the crash/no-crash difference into a file-existence oracle that works regardless of chroot. Low severity alone, but combine it with the chroot bypass above and an attacker can both enumerate and read files.

Dompdf: chroot Check Uses Unanchored Prefix Match, Letting /root_secret Pass for /root

validateLocalUri() compares realpath()'d paths with strpos() and no trailing separator, so a chroot of /var/www/root incorrectly allows /var/www/root_secret/file.html through. Third dompdf finding today and the likely structural reason the SVG bypass above works — patch this one alongside the SVG-specific bypass, since that path probably reaches this same weak check.

12:00 ET · Forenoon Watch

Gitea: Public-Only Repository Tokens Can Update Private PR Head Branches

A public-only,write:repository token can update a private pull request's head branch by going through the public base repository's route — Gitea checks the token restriction against the base repo (public), but UpdatePullRequest() then authorizes the head repo with ordinary RBAC and never re-checks the public-only flag. This is the sharpest of today's public-only-scope bugs: it's a write, not a read, into a repo the token was explicitly restricted from touching. Patch immediately if you issue public-only tokens to any automation.

Gitea Actions Artifacts V4 Signed URL HMAC Ambiguity Allows Cross-Repository Artifact Read and Cross-Task Upload-State Write

Signed upload/download URLs for Gitea Actions Artifacts V4 can be rewritten to point at a different task and repository while keeping the original HMAC valid — an attacker with permission to run one Actions job can read artifacts from another task's context, including a private repo, or write into another task's upload staging area. Anyone running Actions with shared runners across repos of different sensitivity should treat this as urgent — it's a cross-tenant break in a shared-runner model, not a self-contained bug.

fast-uri: Host Confusion via Literal Backslash Authority Delimiter

fast-uri (through v4.1.0) doesn't treat a literal backslash as an authority delimiter, so `http://evil.com\@allowed.com` parses to host allowed.com in fast-uri but host evil.com in Node's native WHATWG URL/fetch — a classic double-parser confusion. Any allowlist, redirect validator, or SSRF filter built on fast-uri and then handed to fetch()/undici sees a different host than it validated. Upgrade to 4.1.1 / 3.1.4 / 2.4.3; there's no workaround.

sharp: Inherited libvips Vulnerabilities (CVE-2026-33327, -33328, -35590, -35591)

sharp inherits four libvips CVEs, two rated High under CVSSv4, for anything processing untrusted images before v0.35.0. Upgrade sharp to 0.35.3 (bundles libvips 8.18.3), or update a system-installed libvips directly if you're not on sharp's prebuilt binaries.

fast-xml-parser: Repeated DOCTYPE Declarations Reset Entity Expansion Limits

fast-xml-parser resets its entity-expansion counters on every DOCTYPE declaration it processes, so a document with repeated DOCTYPEs blows past the expansion limits it's supposed to enforce — a billion-laughs variant that survives the existing guard. Patch if you parse untrusted XML with this library; expect CPU/memory exhaustion, not RCE.

GitPython: Environment-Variable Exfiltration via os.path.expandvars() on Repo.clone_from() URL

Repo.clone_from() runs the caller-supplied URL through os.path.expandvars() before handing it to git clone, so a URL containing $SECRET_ENV expands server-side and ships the value out over the network. This hits exactly the CI servers and git-hosting mirrors that clone from user-submitted URLs — audit any 'import repo from URL' feature for this pattern before you patch.

gRPC-Go: xDS RBAC and HTTP/2 Vulnerabilities

Three distinct bugs in one advisory: xDS RBAC policies with Metadata/RequestedServerName fields fail open instead of denying, an HTTP/2 Rapid Reset mitigation can be bypassed for CPU-exhaustion DoS, and malformed RBAC NOT rules can panic the server. If you use xDS-based authorization anywhere, the fail-open bug is the priority — it silently drops your access control.

jackson-core: Async Parser maxNumberLength Bypass via Chunked Digit Accumulation (Incomplete Fix for GHSA-72hv-8253-57qq)

February's fix for jackson-core's async-parser number-length bypass wired the length check into every place a number's integer portion gets decided on completion, but missed the more attacker-relevant 'ran out of buffer mid-digit, chunk again' path — an attacker can still accumulate an oversized number across chunks. Second incomplete-fix disclosure today (Gitea's ClearRepoWatches bug below is the other); if you patched the February CVE and called it done, you didn't.

Gitea: TOTP TOCTOU Race on Web 2FA Paths + Missing Replay Check on Basic-Auth X-Gitea-OTP Surface

Two related one-time-use defects survive the 2018 TOTP fix: a TOCTOU race lets two parallel submissions of the same passcode both pass the in-memory equality check, and the Basic-Auth X-Gitea-OTP header path never enforces replay protection at all. Don't treat 2FA-gated web logins as a hard single-use control until patched, and check whether your instance exposes the OTP header surface.

Gitea: Improper Authorization on OAuth Sign-In Callback Silently Re-Enables Administrator-Disabled Accounts

Signing in through a linked external IdP unconditionally re-enables a locally-disabled account and issues a fresh session, silently undoing an admin's Disable Account action. Once a user has linked any external IdP, disabling them is non-binding — check for this before relying on account-disable as an offboarding control.

Gitea: Notification API Leaks Private Issue Metadata After Access Revocation

CVE-2026-20800 fixed notification-API access after repo access revocation, but the subject field on existing notification threads still exposes private issue/PR metadata to users who've since lost access. Second incomplete fix targeting the same original CVE's blast radius — re-audit anything you closed against CVE-2026-20800 specifically.

Gitea: Unauthorized Access to Labels of Private Organizations

GET /orgs/{org}/labels and /labels/{id} don't enforce organization-visibility restrictions, so a user with no access to a private org can still read its label metadata. Read-only exposure — no label modification observed — but another org-visibility gap in a batch full of them.

Gitea: Cached Per-Branch Permission Check in Pre-Receive Hook Allows Full Repository Write

The pre-receive hook caches a per-branch permission check that isn't invalidated when branch protection or collaborator permissions change mid-session, so a user who briefly had write access can keep pushing to a protected branch after that access is revoked. Highest-CVSS item in today's non-critical batch — if you rotate collaborator permissions as an incident-response step, this cache can undo it.

Gitea: Fork Synchronization Continues After Parent Repository Changes from Public to Private

merge-upstream keeps syncing commits from a parent repo into a fork even after the parent goes private, so content added during the private period leaks back out through the fork. If you've ever made a repo private specifically to pull sensitive commits out of public view, check whether any forks re-synced afterward.

Gitea: Two SSRF Findings

A researcher-supplied PoC harness demonstrates two separate SSRF paths bypassing Gitea's hostmatcher dial-level protection, touching modules/hostmatcher/hostmatcher.go and modules/auth/openid/openid.go. Third and fourth SSRF disclosures today after the migration/restore-repo pair this morning and the asset-download bug above — the pattern is a systemic gap in how consistently hostmatcher gets applied, not isolated bugs.

Gitea: ParseAcceptLanguage Quadratic-Time DoS via Locale Middleware on Unauthenticated Requests

The Locale middleware runs golang.org/x/text/language.ParseAcceptLanguage on every unauthenticated request's raw Accept-Language header; the CVE-2022-32149 guard caps dashes at 1000 but not underscores, which the parser also aliases to dashes — one crafted header triggers quadratic-time parsing pre-auth. Put a header-length limit in front of Gitea if you can't patch immediately; this is unauthenticated and hits every request.

Gitea: Repository Visibility Manipulation via Git Push Options

Undocumented git push options -o repo.private and -o repo.template let any owner/admin-level collaborator flip a repo's visibility or template flag through the post-receive hook, bypassing whatever visibility-change approval or audit process runs at the UI/API layer. If repo visibility changes are supposed to go through review, push options are an unmonitored side channel — grep your hook logs for these two flags.

Gitea: OAuth2 Sign-In Reactivates an Administrator-Deactivated Account on Auth Sources Without Refresh Tokens (Incomplete Fix of #38009)

PR #38009 tried to gate account reactivation on OAuth sign-in behind 'stored refresh token is empty,' but for auth sources that never issue refresh tokens — GitHub, or OIDC without offline_access — an empty refresh token is every user's normal state, so the gate can't tell a legitimately-disabled user from a never-refreshed one. Same root problem as the OAuth-reactivation bug above (GHSA-g9g6-qhrc-p3qc), different incomplete fix; if your IdP doesn't issue refresh tokens, disabling a user via Gitea's admin panel currently doesn't stick.

Gitea: Internal API HTTP Client Hardcodes InsecureSkipVerify:true with No Config Override

Gitea's internal API HTTP client hardcodes InsecureSkipVerify: true with no config override — the only outbound TLS client in the codebase that can't be made to verify its peer, unlike the webhook, migration, MinIO, LDAP, SMTP, Redis, and incoming-mail clients, which all default secure. Only matters if you run LOCAL_ROOT_URL over HTTPS to a non-loopback target in a split-host topology, but if you do, that internal channel is MITM-able by design right now.

Gitea: Permanent Fork PR Workflow Approval Gate Bypass

The fork-PR approval gate introduced in 2023 (#22803) to require maintainer approval before running Actions on a fork PR has a bypass that's shipped unchanged since — and once bypassed, it's permanent for that PR, not a one-shot evasion. If you rely on the approval gate as your only control against malicious fork-PR workflows, add a second one: restrict runner permissions or gate on branch protection for required checks.

Gitea: LFS Authentication Bypass via Malformed SSH Sub-Verb Allows Unauthorized Read Access to Private Repositories

getAccessMode falls through to an unrestricted branch when an LFS SSH sub-verb is neither upload nor download, letting any authenticated SSH user mint valid LFS credentials for any repository on the instance, private ones included. Same 'missing else branch defaults to permissive' shape as several scope bugs in this batch — audit switch statements over access-mode enums for a default case, not just this one.

Gitea: Unauthenticated ReDoS via CODEOWNERS Pattern Matching Allows Denial of Service

CODEOWNERS patterns go straight into regexp2.Compile with no sanitization and no match timeout, so any signed-up user can commit a CODEOWNERS file with a pattern crafted to backtrack exponentially against a matching file path. Low bar to trigger — normal signup plus one file — for full DoS impact; patch or wrap the regex call with a timeout if you can't upgrade immediately.

Rails HTML Sanitizers: Possible XSS via SVG href Attribute

rails-html-sanitizer's SVG local-reference restriction — mirroring the Loofah bug below — only checks xlink:href, missing the plain href alternative SVG2 also allows, so same-origin SVG content with embedded scripts can execute in the sanitized document's context. Patch to 1.7.1 if your sanitizer config permits <use> or similar SVG reference elements.

Node.js Adapter for Hono: Unauthenticated Memory-Leak DoS via Aborted WebSocket Handshake

An aborted WebSocket handshake — missing or malformed Sec-WebSocket-Key — leaks the IncomingMessage and a never-settled promise in Hono's Node adapter, reachable pre-auth. An unauthenticated flood gradually exhausts memory; patch on your normal cadence if you run upgradeWebSocket routes at the edge.

Loofah: SVG href Attribute Bypasses Local-Reference Restriction

Loofah restricts xlink:href on SVG reference elements to same-document targets but not the plain href alternative SVG2 also allows, so <use> can pull in and execute external SVG content. Same root cause the Rails HTML Sanitizers advisory above inherits — patch both together if you use either.

jackson-databind: @JsonView Bypassed for @JsonUnwrapped Container Properties on Deserialization

UnwrappedPropertyHandler.processUnwrapped() replays buffered JSON for @JsonUnwrapped properties without the @JsonView visibility guard that the sibling creator-property path already got in the #5971 fix — a property gated behind a privileged view still deserializes from attacker JSON when it's also @JsonUnwrapped. If you use @JsonView for field-level access control near any @JsonUnwrapped property, audit it now.

TypeORM: migration:generate Template-Literal Code Injection

typeorm migration:generate embeds introspected schema metadata into JS/TS template literals, escaping backticks but not ${...} — anyone who can write a column comment, default, or view definition gets code execution on whatever loads the generated migration file. Treat schema metadata as untrusted before running migration:generate against a database you don't fully control.

Gitea: Public-Only Personal Access Tokens Scope Bypass in Organization and Permission Endpoints

A public-only-scoped token can't hit GET /orgs/{org} directly for a private org, but /user/orgs and /users/{u}/orgs/{org}/permissions leak the same membership and permission data through a side door. First of several public-only-scope bypasses in today's batch — see the team-route and member-list variants below; if scoped tokens are your access boundary, audit every endpoint that echoes org data, not just the obvious one.

Gitea: SSRF via Migration Asset Downloads Bypasses hostmatcher — Reads Internal Files and Cloud Metadata

Three code paths call Go's raw http.Get() instead of the hostmatcher.NewDialContext()-wrapped client that Gitea's webhook and migration-clone SSRF protection depends on — migration asset downloads bypass the allowlist entirely and can reach internal services or read local files via file://. Same missing-validation shape as this morning's restore-repo SSRF; the fix needs to be centralized in modules/uri, not patched path by path.

Gitea: Cross-Repo Information Disclosure via Org-Level Actions Run/Job APIs

Org-level Actions run/job endpoints check org membership but not per-repo permission, so any org member can read Actions run and job data for private repos in the org they can't otherwise access. Audit who has bare org membership versus actual repo access if you rely on repo-level Actions confidentiality.

Gitea: ClearRepoWatches Fix (GHSA-8fwc-qjw5-rvgp) Not Applied to API EditRepo Path

The ClearRepoWatches fix for stale-watch notification leaks only patched the UI path (MakeRepoPrivate); the API path (PATCH /repos/{owner}/{repo}, i.e. updateRepository) still calls ClearRepoStars only and leaves watchers subscribed after public→private. If you flip repo visibility via the API rather than the UI, re-check who's still watching.

Gitea: Public-Only API Token Restriction Not Enforced on Team API Routes

Team API routes load ctx.Org.Team but skip ctx.Org.Organization, so the public-only-token middleware has nothing to check against and lets the request through — private team repo metadata and activity leak to a token that's supposed to be public-only. Same scope-enforcement gap as the org endpoints above; this batch is telling you public-only tokens aren't a reliable boundary yet.

Gitea: Private Org Member List Leaked via /members API Endpoint (Incomplete Fix for PR #38145)

PR #38145 fixed ListPublicMembers and IsPublicMember but missed ListMembers — any authenticated user can still enumerate the full membership of a private org through that one endpoint. Incomplete-fix pattern again; if you already applied #38145 and considered this closed, it isn't.

Gitea SSH Key Parser Denial of Service

SSH key normalization for RFC 4716 (SSH2)-format keys uses an O(N²) string-concatenation loop with no size limit, so one oversized key submission via POST /user/keys can exhaust CPU and memory. Authenticated-only, but any signup-open instance should cap key submission size.

Loofah: `allowed_uri?` Misses javascript: URIs Split by Numeric Character References Without Semicolons

Loofah's allowed_uri? misses javascript: URIs when the scheme is split by a numeric character reference with no trailing semicolon — browsers still decode and execute it, Loofah just doesn't catch it. Second bypass of the original fix (GHSA-46fp-8f5p-pf2m); worth patching even at low severity if you rely on Loofah for URI scheme filtering.

Gitea: Webhook Authorization Header Returned in Plaintext via API

ToHook() decrypts a webhook's stored authorization header before serializing it into the API response, so any repo admin can read another admin's webhook bearer tokens or basic-auth credentials in plaintext. Rotate webhook credentials that other admins may have viewed via the API; low severity but a real secret leak.

Tyro's CISO: Being the "Einstein of Cybersecurity" Isn't Enough if Developers Don't Trust You

Aikido's writeup on Tyro's CISO frames developer trust as a finite resource that supply-chain incidents burn down fast — relevant for anyone deciding how to roll out new dependency-scanning or token-scope controls without engineers routing around them out of frustration. Not a disclosure, but it rhymes with today's theme: the two dozen Gitea token-scope bugs above only get fixed in practice if the people enforcing them stay credible with the people affected by them.

06:00 ET · Morning Watch

Trojanized Newtonsoft.Json NuGet Fork Rigs Live Betting Results at Digitain

"Newtonsoftt.Json.Net" — a double-t typosquat of Newtonsoft.Json — has shipped seven versions to NuGet (11.0.4–11.0.11, ~1,200 downloads) that behave as a fully working JSON library for every consumer except one: the trojan only activates when JsonConvert.DefaultSettings is assigned and only patches a method present in Digitain's FG-Crash betting backend, where it rigs live game results and later versions exfiltrate them as fake telemetry. This is a narrower-target attack shape than the usual credential-stealer typosquat — a payload that stays dormant unless it recognizes its specific victim's code is much harder for a dependency scanner to flag. Grep .NET codebases for any reference to "Newtonsoftt" (note the double t) and remove it now; the package is unlisted by its publisher but the seven versions remain downloadable from the registry.

Gitea LFS Deploy-Key Privilege Escalation

Gitea's LFS server derives the authorization identity from the JWT's UserID, but deploy-key auth sets that field to repo.OwnerID instead of a scoped deploy-key identity — so a write deploy key for one repo mints a JWT Gitea honors as the repo owner everywhere. Rotate any deploy key that shouldn't imply owner-level trust and patch to 1.27.0; if the owner is a site admin, every private LFS object on the instance was reachable through this.

Gitea: Local File Inclusion via file:// URI in Migration Restore

restore-repo passes a release.yml DownloadURL straight to uri.Open() without scheme validation, so a crafted archive using file:// exfiltrates arbitrary server files as a release attachment. Same missing-validation shape as the restore-repo SSRF disclosed alongside it — audit every URL field restore-repo trusts from imported YAML, not just the ones already patched.

Gitea: OIDC userinfo Endpoint Returns Identity Claims Without Enforcing API Token Scopes

/login/oauth/userinfo accepts Gitea API tokens as bearer credentials but skips scope enforcement, so a token scoped only to read:misc — correctly denied on user-identity REST endpoints — still returns full identity claims through the OIDC path. Fourth token-scope-confinement bypass disclosed in this Gitea round; if scoped tokens are your access boundary, this batch is telling you it has more holes than the original 21-advisory drop covered.

Gitea: REST API Exposes Organization Membership of Private Organizations

/orgs/{org}/public_members/{username} confirms org membership for any authenticated caller regardless of the organization's private-visibility setting. Treat private-org membership as no longer confidential on unpatched instances — this is a direct oracle, not an inference.

Gitea: RSS/Atom Feed Handlers Bypass API-Token Scope (Incomplete Fix of #37698)

Feed routes accept token Basic-auth but never enforce scope or public-only confinement the way the sibling raw/media/archive routes do since #37698 — a confined token that's blocked everywhere else still pulls private content through the feed URL. This is the second incomplete-fix disclosure in two days across two different codebases (jackson-core yesterday, Gitea today) — the same partial-patch shape keeps recurring, worth a standing check whenever a scope fix ships.

Gitea: Fork-PR Actions Task Can Read a Third Private Repository (Missing Fork-PR Guard)

GetActionsUserRepoPermission enforces a fork-PR discriminator on every cross-repo branch except the collaborative-owner one, so a malicious fork-PR workflow whose base repo shares a collaborative owner with a third private repo inherits code-read on that repo. Instances that lean on Actions across collaborative-owner relationships should audit those relationships before assuming fork PRs are sandboxed.

Gitea: Denial of Service via Unbounded io.ReadAll in NPM Package Tag Endpoint

The NPM package tag endpoint reads the entire request body into memory with no size limit, so one oversized authenticated request OOM-kills the process — and the crash survives automatic restarts under repeat requests. Put a body-size limit in front of package endpoints now; this is a persistent DoS from any authenticated npm-registry user, not a one-shot crash.

Gitea: Personal Access Token Scope Bypass on Repository Home Page Discloses Private Contents

repo.Home serves a private repo's README, file tree, description, and release info to tokens that are correctly rejected by the neighboring archive/raw/feed routes. This is the third time this exact source-to-sink pattern has been fixed piecemeal, after CVE-2026-20706 and CVE-2026-27761 — if you already audited those two, re-check the home-page route specifically.

Gitea: Repository Migration SSRF via Multi-Answer DNS Allow-List Bypass

Migration validation accepts a hostname if any resolved IP is allow-listed, but the later git clone re-resolves the same name outside that check — a DNS name returning one public and one internal IP walks straight past the filter into internal-only git services. Any user who can create repo migrations can pivot into internal-network-reachable infrastructure; second SSRF in this Gitea round after yesterday's webhook/migration pair.

Gitea: SSRF in restore-repo via Unsanitized pull_request.yml Head.CloneURL

restore-repo's pull_request.yml parser feeds Head.CloneURL into a git remote/fetch with no validation because the guard function is called with an empty base URL, silently disabling it — a different root cause from the already-patched DownloadURL/PatchURL path-traversal bug in the same command. A malicious dump archive can trigger SSRF or read local files via file://; restore-repo needs one consistent validation path instead of per-field patches.

Gitea: Null Pointer Dereference in AddTime API

The AddTime API keeps executing after GetUserByName() errors on a bad username, then dereferences the nil result and panics. Authenticated, single-request DoS of the handler only — low severity, worth the one-line fix while you're already patching this batch.

Gitea: Private Repository Metadata Remains Accessible After Access Revocation

Removing a collaborator correctly blocks direct repo access, but /api/v1/user/starred keeps serving that repo's metadata — live-updated — if the ex-collaborator had starred it first. Audit offboarding automation that assumes revoked access means zero visibility.

Gitea: Cross-Repository Label-ID Enumeration Oracle via Unscoped DeleteIssueLabel

DeleteIssueLabel does a global unscoped lookup and returns a different status code depending on whether a label ID exists anywhere on the instance, turning delete into a cross-repo enumeration oracle. Low-impact — only ID existence leaks, no names or repo association — but it's the same unscoped-lookup shape as the starred-repo and org-membership leaks disclosed in this same batch.

Gitea: Cross-Repository IDOR in Issue-Dependency Removal

RemoveDependency accepts a global numeric issue ID with no repository or permission check, unlike its sibling AddDependency which validates cross-repo access correctly. An attacker can strip dependency links on and leave an attributed comment on private-repo issues they can't otherwise reach — low severity, but another instance of a sibling function missing the guard its counterpart has.