GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration
Common Weakness Enumeration

CWE-436

Allowed-with-Review

Interpretation Conflict

Abstraction: Class · Status: Incomplete

Product A handles inputs or steps differently than Product B, which causes A to perform incorrect actions based on its perception of B's state.

243 vulnerabilities reference this CWE, most recent first.

GHSA-C2W2-PRH8-QM98

Vulnerability from github – Published: 2026-07-21 18:35 – Updated: 2026-07-21 18:35
VLAI
Summary
guzzlehttp/psr7: Host Confusion via Weak URI Host Validation
Details

Impact

guzzlehttp/psr7 did not reject URI host components containing authority delimiters (/, ?, #, @, or \), an embedded port such as host:8080, or IPv6 brackets that do not frame the host (such as [::1 or ::1]). Uri::assertValidHost() rejected only control characters, so these malformed hosts were accepted both when parsing a URI string — including through new Uri(), an absolute-form request target passed to Message::parseRequest(), and the synthetic SERVER_NAME or SERVER_ADDR fallback used by ServerRequest::fromGlobals() — and when setting a host with Uri::withHost(). Because the stored host was not validated, Uri::getHost() could return a value that does not agree with the URI's authority or with the host that is actually used on the wire. For example, Uri::withHost('good.com@evil.com') is accepted, and new Uri('http://[gggg::1]/') produces a getHost() of '[gggg:' while getAuthority() returns '[gggg::1'.

You are affected if your application builds a Uri or calls Uri::withHost() with host data that is wholly or partly attacker-controlled and then relies on Uri::getHost() for a security or routing decision, such as host allowlisting or denylisting, an SSRF guard, cookie scoping, or proxy-bypass selection. You are also affected if you parse, forward, proxy, or re-serialize URIs that come from untrusted raw HTTP messages or from synthetic $_SERVER values. Because getHost() can then disagree with the real connection target, the concrete impact depends on how your application and any downstream HTTP/1.x component use the URI, and may include host-based access-control bypass, server-side request forgery, routing to an unintended host, or Host header confusion. You are not affected if every host you place into a Uri is already trusted and well formed.

Applications using guzzlehttp/guzzle are affected in the same way through Guzzle's use of PSR-7. Guzzle derives the request Host header from the request URI, and its cookie matching and no_proxy proxy-bypass matching both read Uri::getHost(). An application that builds a Guzzle request URI from attacker-controlled host input can therefore have its Host header, cookie scope, or proxy-bypass decision computed against a host that differs from the one Guzzle connects to. This is not the normal request-sending path, and an application that passes only trusted, well-formed URIs to Guzzle and never builds a request URI from attacker-controlled host input is not affected through Guzzle's standard client APIs.

Patches

The issue is patched in 2.12.3 and later. Starting in that release, guzzlehttp/psr7 rejects URI host components that contain authority delimiters, an embedded port, or IPv6 brackets that do not frame the host, both when parsing a URI and via Uri::withHost(), so Uri::getHost() agrees with the URI authority. A framed bracketed literal whose contents are not a valid IPv6 address is preserved rather than rejected, so getHost() still agrees with the authority.

Workarounds

If you cannot upgrade immediately, validate and normalize host values before you build or modify a Uri from untrusted input, and do not treat Uri::getHost() as a trust boundary for a host you have not independently checked. Before passing a host to Uri, reject any value that contains /, ?, #, @, or \, that contains a colon outside a bracketed IPv6 literal, or that has unbalanced brackets. Applications that parse, forward, replay, or re-serialize raw HTTP messages, or that run with attacker-controlled $_SERVER values, should validate the host before calling Message::parseRequest() or ServerRequest::fromGlobals(), and should avoid reparsing untrusted input.

References

  • https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2
  • https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.3
  • https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.3
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "guzzlehttp/psr7"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2.12.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-59882"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-20",
      "CWE-436"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-21T18:35:25Z",
    "nvd_published_at": "2026-07-08T17:17:26Z",
    "severity": "MODERATE"
  },
  "details": "### Impact\n\n`guzzlehttp/psr7` did not reject URI host components containing authority delimiters (`/`, `?`, `#`, `@`, or `\\`), an embedded port such as `host:8080`, or IPv6 brackets that do not frame the host (such as `[::1` or `::1]`). `Uri::assertValidHost()` rejected only control characters, so these malformed hosts were accepted both when parsing a URI string \u2014 including through `new Uri()`, an absolute-form request target passed to `Message::parseRequest()`, and the synthetic `SERVER_NAME` or `SERVER_ADDR` fallback used by `ServerRequest::fromGlobals()` \u2014 and when setting a host with `Uri::withHost()`. Because the stored host was not validated, `Uri::getHost()` could return a value that does not agree with the URI\u0027s authority or with the host that is actually used on the wire. For example, `Uri::withHost(\u0027good.com@evil.com\u0027)` is accepted, and `new Uri(\u0027http://[gggg::1]/\u0027)` produces a `getHost()` of `\u0027[gggg:\u0027` while `getAuthority()` returns `\u0027[gggg::1\u0027`.\n\nYou are affected if your application builds a `Uri` or calls `Uri::withHost()` with host data that is wholly or partly attacker-controlled and then relies on `Uri::getHost()` for a security or routing decision, such as host allowlisting or denylisting, an SSRF guard, cookie scoping, or proxy-bypass selection. You are also affected if you parse, forward, proxy, or re-serialize URIs that come from untrusted raw HTTP messages or from synthetic `$_SERVER` values. Because `getHost()` can then disagree with the real connection target, the concrete impact depends on how your application and any downstream HTTP/1.x component use the URI, and may include host-based access-control bypass, server-side request forgery, routing to an unintended host, or `Host` header confusion. You are not affected if every host you place into a `Uri` is already trusted and well formed.\n\nApplications using `guzzlehttp/guzzle` are affected in the same way through Guzzle\u0027s use of PSR-7. Guzzle derives the request `Host` header from the request URI, and its cookie matching and `no_proxy` proxy-bypass matching both read `Uri::getHost()`. An application that builds a Guzzle request URI from attacker-controlled host input can therefore have its `Host` header, cookie scope, or proxy-bypass decision computed against a host that differs from the one Guzzle connects to. This is not the normal request-sending path, and an application that passes only trusted, well-formed URIs to Guzzle and never builds a request URI from attacker-controlled host input is not affected through Guzzle\u0027s standard client APIs.\n\n### Patches\n\nThe issue is patched in `2.12.3` and later. Starting in that release, `guzzlehttp/psr7` rejects URI host components that contain authority delimiters, an embedded port, or IPv6 brackets that do not frame the host, both when parsing a URI and via `Uri::withHost()`, so `Uri::getHost()` agrees with the URI authority. A framed bracketed literal whose contents are not a valid IPv6 address is preserved rather than rejected, so `getHost()` still agrees with the authority.\n\n### Workarounds\n\nIf you cannot upgrade immediately, validate and normalize host values before you build or modify a `Uri` from untrusted input, and do not treat `Uri::getHost()` as a trust boundary for a host you have not independently checked. Before passing a host to `Uri`, reject any value that contains `/`, `?`, `#`, `@`, or `\\`, that contains a colon outside a bracketed IPv6 literal, or that has unbalanced brackets. Applications that parse, forward, replay, or re-serialize raw HTTP messages, or that run with attacker-controlled `$_SERVER` values, should validate the host before calling `Message::parseRequest()` or `ServerRequest::fromGlobals()`, and should avoid reparsing untrusted input.\n\n### References\n\n* https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2\n* https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.3\n* https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.3",
  "id": "GHSA-c2w2-prh8-qm98",
  "modified": "2026-07-21T18:35:25Z",
  "published": "2026-07-21T18:35:25Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/guzzle/psr7/security/advisories/GHSA-c2w2-prh8-qm98"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-59882"
    },
    {
      "type": "WEB",
      "url": "https://github.com/guzzle/psr7/pull/811"
    },
    {
      "type": "WEB",
      "url": "https://github.com/guzzle/psr7/commit/ddd64f17d4cc1f7e5ffe6fd2c989ec7221712580"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/guzzle/psr7"
    },
    {
      "type": "WEB",
      "url": "https://github.com/guzzle/psr7/releases/tag/2.12.3"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "guzzlehttp/psr7: Host Confusion via Weak URI Host Validation"
}

GHSA-C8FJ-4PM8-MP2C

Vulnerability from github – Published: 2022-08-30 20:54 – Updated: 2022-08-30 20:54
VLAI
Summary
Broken Authorization in ZITADEL Actions
Details

Impact

Actions, introduced in ZITADEL 1.42.0 on the API and 1.56.0 for Console, is a feature, where users with role ORG_OWNER are able to create Javascript Code, which is invoked by the system at certain points during the login. Actions, for example, allow creating authorizations (user grants) on newly created users programmatically. Due to a missing authorization check, Actions were able to grant authorizations for projects that belong to other organisations inside the same Instance. Granting authorizations via API and Console is not affected by this vulnerability.

Patches

2.x versions are fixed on >= 2.2.0 1.x versions are fixed on >= 1.87.1

ZITADEL recommends upgrading to the latest versions available in due course.

Workarounds

There is no workaround since a patch is already available.

Who did disclose this

During our recurring white box penetration test our external security consultant found this issue. The full report will be made public after the complete review.

References

https://docs.zitadel.com/docs/guides/manage/customize/behavior https://docs.zitadel.com/docs/apis/actions https://zitadel.com/blog/pentest-results-h1-2021

Questions

If you have any questions or comments about this advisory: * Email us at security@zitadel.com

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/zitadel/zitadel"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.0.0"
            },
            {
              "fixed": "2.2.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/zitadel/zitadel"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.42.0"
            },
            {
              "fixed": "1.87.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2022-36051"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-436",
      "CWE-863"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2022-08-30T20:54:28Z",
    "nvd_published_at": "2022-08-31T23:15:00Z",
    "severity": "HIGH"
  },
  "details": "### Impact\n\n**Actions**, introduced in ZITADEL **1.42.0** on the API and **1.56.0** for Console, is a feature, where users with role `ORG_OWNER` are able to create Javascript Code, which is invoked by the system at certain points during the login.\n**Actions**, for example, allow creating authorizations (user grants) on newly created users programmatically.\nDue to a missing authorization check, **Actions** were able to grant authorizations for projects that belong to other organisations inside the same Instance. Granting authorizations via API and Console is not affected by this vulnerability.\n\n### Patches\n\n2.x versions are fixed on \u003e= [2.2.0](https://github.com/zitadel/zitadel/releases/tag/v2.2.0)\n1.x versions are fixed on \u003e= [1.87.1](https://github.com/zitadel/zitadel/releases/tag/v1.87.1)\n\nZITADEL recommends upgrading to the latest versions available in due course.\n\n### Workarounds\n\nThere is no workaround since a patch is already available.\n\n### Who did disclose this\n\nDuring our recurring white box penetration test our external security consultant found this issue.\nThe full report will be made public after the complete review.\n\n### References\n\nhttps://docs.zitadel.com/docs/guides/manage/customize/behavior\nhttps://docs.zitadel.com/docs/apis/actions\nhttps://zitadel.com/blog/pentest-results-h1-2021\n\n### Questions\n\nIf you have any questions or comments about this advisory:\n* Email us at [security@zitadel.com](mailto:security@zitadel.com)\n",
  "id": "GHSA-c8fj-4pm8-mp2c",
  "modified": "2022-08-30T20:54:28Z",
  "published": "2022-08-30T20:54:28Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/zitadel/zitadel/security/advisories/GHSA-c8fj-4pm8-mp2c"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-36051"
    },
    {
      "type": "WEB",
      "url": "https://github.com/zitadel/zitadel/pull/4237"
    },
    {
      "type": "WEB",
      "url": "https://github.com/zitadel/zitadel/pull/4238"
    },
    {
      "type": "WEB",
      "url": "https://github.com/zitadel/zitadel/releases/tag/v1.87.1"
    },
    {
      "type": "WEB",
      "url": "https://github.com/zitadel/zitadel/releases/tag/v2.2.0"
    },
    {
      "type": "PACKAGE",
      "url": "github.com/zitadel/zitadel"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Broken Authorization in ZITADEL Actions"
}

GHSA-CC9R-2J5M-2M83

Vulnerability from github – Published: 2026-09-08 21:32 – Updated: 2026-09-08 21:32
VLAI
Summary
Nodemailer: Recipient-domain validation bypass via RFC 5322 comment mis-parsing leads to email delivery to an attacker-controlled domain
Details

Summary

Nodemailer's email-address parser treats an RFC 5322 comment ( ... ) inside the domain as a point to concatenate the surrounding text, rather than as folding whitespace (CFWS) that terminates the domain. Consequently a recipient address such as user@good-corp.com(x)evil.com is parsed and delivered to good-corp.comevil.com (registrable domain comevil.com, attacker‑controlled), while a conformant RFC 5322 parser terminates the domain at the comment and reads good-corp.com.

An application that decides whether it is allowed to email a recipient by parsing/validating the recipient's domain — with a strict RFC 5322 parser (used without inspecting parse defects) or with a naive prefix/substring allow‑list — and then hands the raw address to Nodemailer for delivery, can be induced to send mail to a domain the attacker controls. This is an Interpretation Conflict (CWE‑436), the same class as CVE‑2025‑13033, reached through the RFC 5322 comment construct (the "Comments" technique in PortSwigger's Splitting the email atom research, which produced a Postfix fix).

Severity is Moderate: exploitation requires the app's domain check to disagree with Nodemailer (see Impact for exactly which parsers do and do not). Verified end‑to‑end against a real RFC 5321 SMTP server (nodemailer 9.0.6 → aiosmtpd).

Details

Root cause is in lib/addressparser/index.js.

  1. The tokenizer registers the comment as an operator pair (Tokenizer.operators): js '(': ')', // line ~331
  2. When the closing ) is immediately followed by a non‑break character (anything other than space / tab / CR / LF / , / ;), the tokenizer marks that operator token with noBreak = true: js // Tokenizer.checkChar, lines ~398-399 if (nextChr && ![' ', '\t', '\r', '\n', ',', ';'].includes(nextChr)) { this.node.noBreak = true; }
  3. _handleAddress then glues the token that follows the comment onto the token that preceded it (dropping the comment): js // _handleAddress, lines ~187-188 if (prevToken && prevToken.noBreak && data[state].length) { data[state][data[state].length - 1] += token.value; // <-- concatenation }

For the input user@good-corp.com(x)evil.com the tokens are text:"user@good-corp.com", op:"(", text:"x", op:")" (flagged noBreak), text:"evil.com". Step 3 appends evil.com onto user@good-corp.com, producing the single domain good-corp.comevil.com. The comment content (x) is discarded into the display‑name field.

RFC 5322 defines a comment as CFWS — semantically folding whitespace — and it may not appear inside a dot-atom. A comment therefore separates tokens and terminates the domain; the conformant reading of good-corp.com(x)evil.com is the domain good-corp.com (with the trailing evil.com being invalid/ignored). Nodemailer instead concatenates the two atoms across the removed comment, yielding a different, attacker‑registrable domain.

Nodemailer uses the parsed address for both the SMTP envelope (getEnvelope()RCPT TO) and the emitted To:/From: headers, so the entire message is routed to the concatenated domain.

Related grammar defect (bonus, lower impact): nested comments are legal in RFC 5322, but the tokenizer closes the comment at the first ) (chr === this.operatorExpecting, line ~392), so a valid nested comment such as user@x.com(a(b)c) is mis‑balanced and mangled to x.comc). That particular output contains a stray ) and is rejected by a conformant MTA (501) — a bounce/robustness issue, not a misroute.

Suggested fix: treat a comment as folding whitespace that terminates the current token — i.e. do not propagate noBreak across a comment‑closing ) (restrict the noBreak optimization to quoted‑string closes), and support nested comments per RFC 5322. Equivalently, never emit a domain formed by concatenating two atoms that were separated only by a comment.

PoC

Environment: Node.js ≥ 18 and the published nodemailer@9.0.6. No special transport configuration is required; the discrepancy is in address parsing.

poc-comment.js:

'use strict';
const net = require('net');
const nodemailer = require('nodemailer'); // 9.0.6

const TRUSTED   = 'good-corp.com';
const RECIPIENT = 'user@good-corp.com(x)evil.com'; // RFC 5322 comment (x) between two domains

// tiny SMTP sink that prints the literal RCPT TO nodemailer transmits
const server = net.createServer(sock => {
  let buf = ''; sock.write('220 sink\r\n');
  sock.on('data', d => { buf += d; let i;
    while ((i = buf.indexOf('\r\n')) >= 0) { const line = buf.slice(0, i); buf = buf.slice(i + 2);
      const u = line.toUpperCase();
      if (u.startsWith('EHLO')) sock.write('250-sink\r\n250 8BITMIME\r\n');
      else if (u.startsWith('RCPT')) { console.log('nodemailer transmits :', line); sock.write('250 ok\r\n'); }
      else if (u.startsWith('DATA')) sock.write('354 go\r\n');
      else if (line === '.') sock.write('250 ok\r\n');
      else if (u.startsWith('QUIT')) { sock.write('221 bye\r\n'); sock.end(); }
      else sock.write('250 ok\r\n'); } });
});
server.listen(0, '127.0.0.1', async () => {
  const t = nodemailer.createTransport({ host: '127.0.0.1', port: server.address().port, secure: false });
  await t.sendMail({ from: 'app@good-corp.com', to: RECIPIENT, subject: 'hi', text: 'x' });
  t.close(); server.close();
});

Run:

npm init -y && npm install nodemailer@9.0.6
node poc-comment.js

Actual output (nodemailer 9.0.6):

nodemailer transmits : RCPT TO:<user@good-corp.comevil.com>

The application asked to mail user@good-corp.com(x)evil.com; Nodemailer delivers to good-corp.comevil.com — registrable domain comevil.com, which an attacker can register.

Verified against a real RFC 5321 server (containerized lab included with this report — docker compose up --build, case R8_comment_glue, receiver = aiosmtpd):

wire RCPT TO                     : RCPT TO:<user@good-corp.comevil.com>
real server                      : ACCEPTED (250)
recipient parsed by real server  : user@good-corp.comevil.com   (domain good-corp.comevil.com)
delivered To header              : x <user@good-corp.comevil.com>

Which parser sees what (the crux of exploitability):

Parser used by the application to gate/route Domain it reads from user@good-corp.com(x)evil.com Deceived?
Python email.policy.default (strict RFC 5322) good-corp.com (flags InvalidHeaderDefect) Yes, if defects are not checked
Naive prefix / substring allow‑list (startsWith/includes('@good-corp.com')) good-corp.com Yes
Nodemailer's own addressparser good-corp.comevil.com No
Python email.utils.getaddresses good-corp.comevil.com No
WHATWG url.domainToASCII good-corp.com(x)evil.com No

Impact

  • Who is impacted: applications that make a security or routing decision on the recipient domain using a parser that terminates the domain at the comment, while relying on Nodemailer for delivery — specifically those that validate with a strict RFC 5322 parser without inspecting parse defects, or with a prefix/substring/allow‑list check (e.g. "only send to @good-corp.com", employee‑only flows, "same‑tenant" routing). Applications that validate with Nodemailer's own addressparser, email.utils.getaddresses, or url.domainToASCII are not affected, which is why this is rated below the IDN/Punycode issue.

Patched in 9.1.0

Fixed in 902b63e.

Not propagating noBreak across the closing ) on its own breaks valid addresses, because CFWS is legal on either side of the @: user@(x)good-corp.com and user(x)@good-corp.com both come out mangled. A comment now joins what it separates only when one side carries the @, so those keep resolving while user@good-corp.com(x)evil.com terminates at good-corp.com.

Quoted-string and angle-address joining are unchanged. Nested comments are still not modelled, but the misroute is gone: user@x.com(a(b)c) now yields user@x.com.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "nodemailer"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "6.9.16"
            },
            {
              "fixed": "9.1.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-20",
      "CWE-436"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-09-08T21:32:51Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "### Summary\n\nNodemailer\u0027s email-address parser treats an **RFC 5322 comment** `( ... )` inside the domain as a point to **concatenate** the surrounding text, rather than as folding whitespace (CFWS) that **terminates** the domain. Consequently a recipient address such as `user@good-corp.com(x)evil.com` is parsed and **delivered to `good-corp.comevil.com`** (registrable domain `comevil.com`, attacker\u2011controlled), while a conformant RFC 5322 parser terminates the domain at the comment and reads `good-corp.com`.\n\nAn application that decides *whether it is allowed to email a recipient* by parsing/validating the recipient\u0027s domain \u2014 with a strict RFC 5322 parser (used without inspecting parse defects) or with a naive prefix/substring allow\u2011list \u2014 and then hands the raw address to Nodemailer for delivery, can be induced to send mail to a domain the attacker controls. This is an **Interpretation Conflict (CWE\u2011436)**, the same class as CVE\u20112025\u201113033, reached through the RFC 5322 *comment* construct (the \"Comments\" technique in PortSwigger\u0027s *Splitting the email atom* research, which produced a Postfix fix).\n\nSeverity is **Moderate**: exploitation requires the app\u0027s domain check to disagree with Nodemailer (see **Impact** for exactly which parsers do and do not). Verified end\u2011to\u2011end against a real RFC 5321 SMTP server (nodemailer 9.0.6 \u2192 `aiosmtpd`).\n\n### Details\n\nRoot cause is in `lib/addressparser/index.js`.\n\n1. The tokenizer registers the comment as an operator pair (`Tokenizer.operators`):\n   ```js\n   \u0027(\u0027: \u0027)\u0027,            // line ~331\n   ```\n2. When the **closing** `)` is immediately followed by a non\u2011break character (anything other than space / tab / CR / LF / `,` / `;`), the tokenizer marks that operator token with `noBreak = true`:\n   ```js\n   // Tokenizer.checkChar, lines ~398-399\n   if (nextChr \u0026\u0026 ![\u0027 \u0027, \u0027\\t\u0027, \u0027\\r\u0027, \u0027\\n\u0027, \u0027,\u0027, \u0027;\u0027].includes(nextChr)) {\n       this.node.noBreak = true;\n   }\n   ```\n3. `_handleAddress` then **glues** the token that follows the comment onto the token that preceded it (dropping the comment):\n   ```js\n   // _handleAddress, lines ~187-188\n   if (prevToken \u0026\u0026 prevToken.noBreak \u0026\u0026 data[state].length) {\n       data[state][data[state].length - 1] += token.value;   // \u003c-- concatenation\n   }\n   ```\n\nFor the input `user@good-corp.com(x)evil.com` the tokens are `text:\"user@good-corp.com\"`, `op:\"(\"`, `text:\"x\"`, `op:\")\"` (flagged `noBreak`), `text:\"evil.com\"`. Step 3 appends `evil.com` onto `user@good-corp.com`, producing the single domain **`good-corp.comevil.com`**. The comment content (`x`) is discarded into the display\u2011name field.\n\nRFC 5322 defines a comment as CFWS \u2014 semantically folding whitespace \u2014 and it may **not** appear inside a `dot-atom`. A comment therefore *separates* tokens and terminates the domain; the conformant reading of `good-corp.com(x)evil.com` is the domain `good-corp.com` (with the trailing `evil.com` being invalid/ignored). Nodemailer instead concatenates the two atoms across the removed comment, yielding a different, attacker\u2011registrable domain.\n\nNodemailer uses the parsed address for **both** the SMTP envelope (`getEnvelope()` \u2192 `RCPT TO`) and the emitted `To:`/`From:` headers, so the entire message is routed to the concatenated domain.\n\n**Related grammar defect (bonus, lower impact):** nested comments are legal in RFC 5322, but the tokenizer closes the comment at the *first* `)` (`chr === this.operatorExpecting`, line ~392), so a valid nested comment such as `user@x.com(a(b)c)` is mis\u2011balanced and mangled to `x.comc)`. That particular output contains a stray `)` and is **rejected** by a conformant MTA (501) \u2014 a bounce/robustness issue, not a misroute.\n\n**Suggested fix:** treat a comment as folding whitespace that terminates the current token \u2014 i.e. do **not** propagate `noBreak` across a comment\u2011closing `)` (restrict the `noBreak` optimization to quoted\u2011string closes), and support nested comments per RFC 5322. Equivalently, never emit a domain formed by concatenating two atoms that were separated only by a comment.\n\n### PoC\n\nEnvironment: Node.js \u2265 18 and the published `nodemailer@9.0.6`. No special transport configuration is required; the discrepancy is in address parsing.\n\n`poc-comment.js`:\n```js\n\u0027use strict\u0027;\nconst net = require(\u0027net\u0027);\nconst nodemailer = require(\u0027nodemailer\u0027); // 9.0.6\n\nconst TRUSTED   = \u0027good-corp.com\u0027;\nconst RECIPIENT = \u0027user@good-corp.com(x)evil.com\u0027; // RFC 5322 comment (x) between two domains\n\n// tiny SMTP sink that prints the literal RCPT TO nodemailer transmits\nconst server = net.createServer(sock =\u003e {\n  let buf = \u0027\u0027; sock.write(\u0027220 sink\\r\\n\u0027);\n  sock.on(\u0027data\u0027, d =\u003e { buf += d; let i;\n    while ((i = buf.indexOf(\u0027\\r\\n\u0027)) \u003e= 0) { const line = buf.slice(0, i); buf = buf.slice(i + 2);\n      const u = line.toUpperCase();\n      if (u.startsWith(\u0027EHLO\u0027)) sock.write(\u0027250-sink\\r\\n250 8BITMIME\\r\\n\u0027);\n      else if (u.startsWith(\u0027RCPT\u0027)) { console.log(\u0027nodemailer transmits :\u0027, line); sock.write(\u0027250 ok\\r\\n\u0027); }\n      else if (u.startsWith(\u0027DATA\u0027)) sock.write(\u0027354 go\\r\\n\u0027);\n      else if (line === \u0027.\u0027) sock.write(\u0027250 ok\\r\\n\u0027);\n      else if (u.startsWith(\u0027QUIT\u0027)) { sock.write(\u0027221 bye\\r\\n\u0027); sock.end(); }\n      else sock.write(\u0027250 ok\\r\\n\u0027); } });\n});\nserver.listen(0, \u0027127.0.0.1\u0027, async () =\u003e {\n  const t = nodemailer.createTransport({ host: \u0027127.0.0.1\u0027, port: server.address().port, secure: false });\n  await t.sendMail({ from: \u0027app@good-corp.com\u0027, to: RECIPIENT, subject: \u0027hi\u0027, text: \u0027x\u0027 });\n  t.close(); server.close();\n});\n```\n\nRun:\n```\nnpm init -y \u0026\u0026 npm install nodemailer@9.0.6\nnode poc-comment.js\n```\n\nActual output (nodemailer 9.0.6):\n```\nnodemailer transmits : RCPT TO:\u003cuser@good-corp.comevil.com\u003e\n```\n\nThe application asked to mail `user@good-corp.com(x)evil.com`; Nodemailer delivers to `good-corp.comevil.com` \u2014 registrable domain `comevil.com`, which an attacker can register.\n\n**Verified against a real RFC 5321 server** (containerized lab included with this report \u2014 `docker compose up --build`, case `R8_comment_glue`, receiver = `aiosmtpd`):\n```\nwire RCPT TO                     : RCPT TO:\u003cuser@good-corp.comevil.com\u003e\nreal server                      : ACCEPTED (250)\nrecipient parsed by real server  : user@good-corp.comevil.com   (domain good-corp.comevil.com)\ndelivered To header              : x \u003cuser@good-corp.comevil.com\u003e\n```\n\n**Which parser sees what** (the crux of exploitability):\n\n| Parser used by the application to gate/route | Domain it reads from `user@good-corp.com(x)evil.com` | Deceived? |\n|---|---|---|\n| Python `email.policy.default` (strict RFC 5322) | `good-corp.com` *(flags `InvalidHeaderDefect`)* | Yes, if defects are not checked |\n| Naive prefix / substring allow\u2011list (`startsWith`/`includes(\u0027@good-corp.com\u0027)`) | `good-corp.com` | Yes |\n| Nodemailer\u0027s own `addressparser` | `good-corp.comevil.com` | No |\n| Python `email.utils.getaddresses` | `good-corp.comevil.com` | No |\n| WHATWG `url.domainToASCII` | `good-corp.com(x)evil.com` | No |\n\n### Impact\n\n\n\n* **Who is impacted:** applications that make a security or routing decision on the recipient **domain** using a parser that terminates the domain at the comment, while relying on Nodemailer for delivery \u2014 specifically those that validate with a strict RFC 5322 parser **without inspecting parse defects**, or with a **prefix/substring/allow\u2011list** check (e.g. \"only send to `@good-corp.com`\", employee\u2011only flows, \"same\u2011tenant\" routing). Applications that validate with Nodemailer\u0027s own `addressparser`, `email.utils.getaddresses`, or `url.domainToASCII` are **not** affected, which is why this is rated below the IDN/Punycode issue.\n\n## Patched in 9.1.0\n\nFixed in [902b63e](https://github.com/nodemailer/nodemailer/commit/902b63e).\n\nNot propagating `noBreak` across the closing `)` on its own breaks valid addresses, because CFWS is legal on either side of the `@`: `user@(x)good-corp.com` and `user(x)@good-corp.com` both come out mangled. A comment now joins what it separates only when one side carries the `@`, so those keep resolving while `user@good-corp.com(x)evil.com` terminates at `good-corp.com`.\n\nQuoted-string and angle-address joining are unchanged. Nested comments are still not modelled, but the misroute is gone: `user@x.com(a(b)c)` now yields `user@x.com`.",
  "id": "GHSA-cc9r-2j5m-2m83",
  "modified": "2026-09-08T21:32:52Z",
  "published": "2026-09-08T21:32:51Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/nodemailer/nodemailer/security/advisories/GHSA-cc9r-2j5m-2m83"
    },
    {
      "type": "WEB",
      "url": "https://github.com/nodemailer/nodemailer/pull/1848"
    },
    {
      "type": "WEB",
      "url": "https://github.com/nodemailer/nodemailer/commit/902b63e935435c30f4025901c0902dce64cd8880"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/nodemailer/nodemailer"
    },
    {
      "type": "WEB",
      "url": "https://github.com/nodemailer/nodemailer/releases/tag/v9.1.0"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:L/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Nodemailer: Recipient-domain validation bypass via RFC 5322 comment mis-parsing leads to email delivery to an attacker-controlled domain"
}

GHSA-F2M2-CC3F-H4J2

Vulnerability from github – Published: 2026-07-28 15:32 – Updated: 2026-09-03 15:32
VLAI
Details

A flaw was found in openshift/oauth-proxy. The proxy sets authenticated identity headers using only dash-variant keys (X-Forwarded-User) but does not strip underscore-variant keys (X_Forwarded_User) from incoming requests. WSGI and PHP frameworks normalize both variants to the same variable, allowing an authenticated low-privilege user to smuggle a forged identity that may override the legitimate authenticated identity in the upstream application.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-49332"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-436"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-07-28T13:18:46Z",
    "severity": "HIGH"
  },
  "details": "A flaw was found in openshift/oauth-proxy. The proxy sets authenticated identity headers using only dash-variant keys (X-Forwarded-User) but does not strip underscore-variant keys (X_Forwarded_User) from incoming requests. WSGI and PHP frameworks normalize both variants to the same variable, allowing an authenticated low-privilege user to smuggle a forged identity that may override the legitimate authenticated identity in the upstream application.",
  "id": "GHSA-f2m2-cc3f-h4j2",
  "modified": "2026-09-03T15:32:01Z",
  "published": "2026-07-28T15:32:17Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-49332"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:50681"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:50758"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:51007"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:51013"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:51022"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:51025"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:51038"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:54188"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:54206"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:56912"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2026:60023"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/security/cve/CVE-2026-49332"
    },
    {
      "type": "WEB",
      "url": "https://bugzilla.redhat.com/show_bug.cgi?id=2483253"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-F4C7-7CMX-Q7FX

Vulnerability from github – Published: 2022-05-24 19:02 – Updated: 2022-07-13 00:01
VLAI
Details

Microsoft SharePoint Server Remote Code Execution Vulnerability

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2021-28474"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-436",
      "CWE-77"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2021-05-11T19:15:00Z",
    "severity": "HIGH"
  },
  "details": "Microsoft SharePoint Server Remote Code Execution Vulnerability",
  "id": "GHSA-f4c7-7cmx-q7fx",
  "modified": "2022-07-13T00:01:14Z",
  "published": "2022-05-24T19:02:04Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-28474"
    },
    {
      "type": "WEB",
      "url": "https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2021-28474"
    },
    {
      "type": "WEB",
      "url": "https://www.zerodayinitiative.com/advisories/ZDI-21-574"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-F7J2-6V4C-HJXW

Vulnerability from github – Published: 2022-05-24 17:09 – Updated: 2022-05-24 17:09
VLAI
Details

The Quick Heal AV parsing engine (November 2019) allows virus-detection bypass via a crafted GPFLAG in a ZIP archive. This affects Total Security, Home Security, Total Security Multi-Device, Internet Security, Total Security for Mac, AntiVirus Pro, AntiVirus for Server, and Total Security for Android.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2020-9362"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-20",
      "CWE-436"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2020-02-24T16:15:00Z",
    "severity": "MODERATE"
  },
  "details": "The Quick Heal AV parsing engine (November 2019) allows virus-detection bypass via a crafted GPFLAG in a ZIP archive. This affects Total Security, Home Security, Total Security Multi-Device, Internet Security, Total Security for Mac, AntiVirus Pro, AntiVirus for Server, and Total Security for Android.",
  "id": "GHSA-f7j2-6v4c-hjxw",
  "modified": "2022-05-24T17:09:35Z",
  "published": "2022-05-24T17:09:35Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-9362"
    },
    {
      "type": "WEB",
      "url": "https://blog.zoller.lu/p/from-low-hanging-fruit-department_24.html"
    },
    {
      "type": "WEB",
      "url": "https://blog.zoller.lu/p/tzo-20-2020-quickheal-malformed-archive.html"
    },
    {
      "type": "WEB",
      "url": "http://packetstormsecurity.com/files/156580/QuickHeal-Generic-Malformed-Archive-Bypass.html"
    },
    {
      "type": "WEB",
      "url": "http://seclists.org/fulldisclosure/2020/Mar/14"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-F8F7-69V5-W4VX

Vulnerability from github – Published: 2023-07-11 21:30 – Updated: 2023-11-25 12:30
VLAI
Details

The HTTP/1 client does not fully validate the contents of the Host header. A maliciously crafted Host header can inject additional headers or entire requests. With fix, the HTTP/1 client now refuses to send requests containing an invalid Request.Host or Request.URL.Host value.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2023-29406"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-113",
      "CWE-436"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2023-07-11T20:15:10Z",
    "severity": "MODERATE"
  },
  "details": "The HTTP/1 client does not fully validate the contents of the Host header. A maliciously crafted Host header can inject additional headers or entire requests. With fix, the HTTP/1 client now refuses to send requests containing an invalid Request.Host or Request.URL.Host value.",
  "id": "GHSA-f8f7-69v5-w4vx",
  "modified": "2023-11-25T12:30:22Z",
  "published": "2023-07-11T21:30:58Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-29406"
    },
    {
      "type": "WEB",
      "url": "https://go.dev/cl/506996"
    },
    {
      "type": "WEB",
      "url": "https://go.dev/issue/60374"
    },
    {
      "type": "WEB",
      "url": "https://groups.google.com/g/golang-announce/c/2q13H6LEEx0"
    },
    {
      "type": "WEB",
      "url": "https://pkg.go.dev/vuln/GO-2023-1878"
    },
    {
      "type": "WEB",
      "url": "https://security.gentoo.org/glsa/202311-09"
    },
    {
      "type": "WEB",
      "url": "https://security.netapp.com/advisory/ntap-20230814-0002"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-FF7Q-6VWH-V9M4

Vulnerability from github – Published: 2024-06-28 00:33 – Updated: 2024-06-28 18:57
VLAI
Summary
Name confusion in x509 Subject Alternative Name fields
Details

In phpseclib before 1.0.22, 2.x before 2.0.46, and 3.x before 3.0.33, some characters in Subject Alternative Name fields in TLS certificates are incorrectly allowed to have a special meaning in regular expressions (such as a + wildcard), leading to name confusion in X.509 certificate host verification.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "phpseclib/phpseclib"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "1.0.22"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "phpseclib/phpseclib"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.0.0"
            },
            {
              "fixed": "2.0.46"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "phpseclib/phpseclib"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "3.0.0"
            },
            {
              "fixed": "3.0.33"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2023-52892"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-436"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2024-06-28T18:57:31Z",
    "nvd_published_at": "2024-06-27T22:15:10Z",
    "severity": "HIGH"
  },
  "details": "In phpseclib before 1.0.22, 2.x before 2.0.46, and 3.x before 3.0.33, some characters in Subject Alternative Name fields in TLS certificates are incorrectly allowed to have a special meaning in regular expressions (such as a + wildcard), leading to name confusion in X.509 certificate host verification.",
  "id": "GHSA-ff7q-6vwh-v9m4",
  "modified": "2024-06-28T18:57:31Z",
  "published": "2024-06-28T00:33:31Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-52892"
    },
    {
      "type": "WEB",
      "url": "https://github.com/phpseclib/phpseclib/issues/1943"
    },
    {
      "type": "WEB",
      "url": "https://github.com/phpseclib/phpseclib/commit/6cd6e8ceab9f2b55c8cd81d2192bf98cbeaf4627"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/phpseclib/phpseclib"
    },
    {
      "type": "WEB",
      "url": "https://github.com/phpseclib/phpseclib/releases/tag/3.0.33"
    },
    {
      "type": "WEB",
      "url": "https://github.com/x509-name-testing/name_testing_artifacts"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Name confusion in x509 Subject Alternative Name fields"
}

GHSA-FM3M-JRGM-5PPG

Vulnerability from github – Published: 2025-08-04 20:46 – Updated: 2025-08-06 14:12
VLAI
Summary
RatPanel can perform remote command execution without authorization
Details

Summary

  • When an attacker obtains the backend login path of RatPanel (including but not limited to weak default paths, brute-force cracking, etc.), they can execute system commands or take over hosts managed by the panel without logging in.
  • In addition to this remote code execution (RCE) vulnerability, the flawed code also leads to unauthorized access.

Details

In Go, r.URL.Path retrieves the part of the URL that comes after the port and before the query parameters or anchor symbols. For example, in the URL http://localhost:8080/api/ws/ssh?id=1, the retrieved path would be /api/ws/ssh.

However, if the request is made to http://localhost:8080//api/ws/ssh?id=1, the parsed r.URL.Path would be //api/ws/ssh.

RatPanel uses the CleanPath middleware provided by github.com/go-chi/chi package to clean URLs, The route path inside the chi router will be cleaned to /api/ws/ssh, but this middleware does not process r.URL.Path, so the path is still //api/ws/ssh.

image

In the must_login middleware, RatPanel uses r.URL.Path to match the hard-coded prefix whitelist, because /api/ws does not match //api/ws. The must_login middleware will allow the request, but //api/ws has been cleaned to /api/ws in the chi router. This inconsistency leads to authentication bypass and accessing the dangerous interfaces such as /api/ws/exec and /api/ws/ssh.

image-20250706193354738

But there are some limitations. Before exploiting this interface, the attacker must first identify the correct backend address of ratpanel to activate session legitimacy—specifically, to ensure sess.Put("verify_entrance", true). That said, accessing /api/ws only requires activating the session and does not require completing further authentication or login steps. Therefore, this is assessed to be a remotely exploitable command execution vulnerability with moderate severity.

PoC

I first carried session=......, accessed the backend login page normally(without completing the authentication process), activated the session, and then used the _wsdump.py script provided by the Python websocket-client library to complete the authentication and exploit the vulnerability.

image-20250706202209133 image-20250706202330056 image-20250706202450433

Because of the authorization code

// internal/http/middleware/must_login.go
if slices.Contains(whiteList, r.URL.Path) || !strings.HasPrefix(r.URL.Path, "/api") {
    next.ServeHTTP(w, r)
    return
}

This vulnerability affects the authorization mechanism across all APIs, for example

image-20250706204411739 image-20250706204429581

This authentication vulnerability appears to affect versions v2.3.19 to v2.5.5.


Data packet

GET //api/...... HTTP/2
Host: IP:PORT
Cookie: session=XXXXXX
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/json; charset=UTF-8
Connection: close


python _wsdump.py wss://ip:port//api/ws/exec --headers "Cookie: session=xxxxxx" -n

Impact

Users running Ratpanel versions v2.3.19 to v2.5.5—especially those who have exposed their admin panel login URL or use weak login URL paths—are vulnerable to unauthorized access. Additionally, versions v2.5.1 to v2.5.5 are susceptible to server and hosted machine takeover.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/tnborg/panel"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.3.19"
            },
            {
              "fixed": "2.5.6"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/tnborg/panel"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0.0.0-20241111062800-91ecd04c2700"
            },
            {
              "fixed": "0.0.0-20250707071915-4985eb2e1f38"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2025-53534"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22",
      "CWE-305",
      "CWE-436"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2025-08-04T20:46:32Z",
    "nvd_published_at": "2025-08-05T21:15:38Z",
    "severity": "HIGH"
  },
  "details": "### Summary\n\n* When an attacker obtains the backend login path of RatPanel (including but not limited to weak default paths, brute-force cracking, etc.), they can execute system commands or take over hosts managed by the panel **without logging in**.\n* In addition to this **remote code execution (RCE) vulnerability**, the flawed code also leads to **unauthorized access**.\n\n### Details\n\nIn Go, `r.URL.Path` retrieves the part of the URL that comes after the port and before the query parameters or anchor symbols. For example, in the URL `http://localhost:8080/api/ws/ssh?id=1`, the retrieved path would be `/api/ws/ssh`.\n\nHowever, if the request is made to `http://localhost:8080//api/ws/ssh?id=1`, the parsed `r.URL.Path` would be `//api/ws/ssh`. \n\nRatPanel uses the `CleanPath` middleware provided by `github.com/go-chi/chi` package to clean URLs, The route path inside the chi router will be cleaned to `/api/ws/ssh`, but this middleware does not process `r.URL.Path`, so the path is still `//api/ws/ssh`.\n\n![image](https://github.com/user-attachments/assets/788a7263-38f6-4b74-aa4a-b935239362f7)\n\nIn the `must_login` middleware, RatPanel uses `r.URL.Path` to match the hard-coded prefix whitelist, because `/api/ws` does not match `//api/ws`. The `must_login` middleware will allow the request, but `//api/ws` has been cleaned to `/api/ws` in the chi router. This inconsistency leads to authentication bypass and accessing the dangerous interfaces such as `/api/ws/exec` and `/api/ws/ssh`.\n\n![image-20250706193354738](https://github.com/user-attachments/assets/a0be46a5-9e82-4623-9b21-7247798a3c98)\n\nBut there are some limitations. Before exploiting this interface, the attacker must first identify the correct backend address of ratpanel to activate session legitimacy\u2014specifically, to ensure `sess.Put(\"verify_entrance\", true)`. That said, accessing `/api/ws` only requires activating the session and does not require completing further authentication or login steps. Therefore, this is assessed to be a remotely exploitable command execution vulnerability with moderate severity.\n\n\n### PoC\n\nI first carried `session=......`, accessed the backend login page normally` (without completing the authentication process)`, activated the session, and then used the [_wsdump.py](https://github.com/websocket-client/websocket-client/blob/master/websocket/_wsdump.py) script provided by the Python websocket-client library to complete the authentication and exploit the vulnerability.\n\n![image-20250706202209133](https://github.com/user-attachments/assets/89849095-8d90-465b-8d67-91b49e61c7bf)\n![image-20250706202330056](https://github.com/user-attachments/assets/6188f519-13f7-4ca9-84ef-f743bda55ae2)\n![image-20250706202450433](https://github.com/user-attachments/assets/76e4f8f3-ad67-4295-ab83-6ec910f7449d)\n\nBecause of the authorization code\n\n```golang\n// internal/http/middleware/must_login.go\nif slices.Contains(whiteList, r.URL.Path) || !strings.HasPrefix(r.URL.Path, \"/api\") {\n    next.ServeHTTP(w, r)\n    return\n}\n```\n\nThis vulnerability affects the authorization mechanism across all APIs, for example\n\n![image-20250706204411739](https://github.com/user-attachments/assets/5da63d83-2652-4275-8a80-c7878de62f5c)\n![image-20250706204429581](https://github.com/user-attachments/assets/d83a323a-a98e-4ec0-9480-06e0d8670513)\n\nThis authentication vulnerability appears to affect versions **v2.3.19 to v2.5.5**.\n\n---\n\nData packet\n\n```text\nGET //api/...... HTTP/2\nHost: IP:PORT\nCookie: session=XXXXXX\nAccept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2\nAccept-Encoding: gzip, deflate\nContent-Type: application/json; charset=UTF-8\nConnection: close\n\n\n```\n\n```cmd\npython _wsdump.py wss://ip:port//api/ws/exec --headers \"Cookie: session=xxxxxx\" -n\n```\n\n### Impact\n\nUsers running Ratpanel versions v2.3.19 to v2.5.5\u2014especially those who have exposed their admin panel login URL or use weak login URL paths\u2014are vulnerable to unauthorized access. Additionally, versions v2.5.1 to v2.5.5 are susceptible to server and hosted machine takeover.",
  "id": "GHSA-fm3m-jrgm-5ppg",
  "modified": "2025-08-06T14:12:21Z",
  "published": "2025-08-04T20:46:32Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/tnborg/panel/security/advisories/GHSA-fm3m-jrgm-5ppg"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-53534"
    },
    {
      "type": "WEB",
      "url": "https://github.com/tnborg/panel/commit/4985eb2e1f388ecd6faf331941c13cb97368ec1d"
    },
    {
      "type": "WEB",
      "url": "https://github.com/tnborg/panel/commit/91ecd04c270061429f9df5ec19cd6b96a9f595f2"
    },
    {
      "type": "WEB",
      "url": "https://github.com/tnborg/panel/commit/ed5c74c7534230ba685273504af4c1e1e3598ff1"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/tnborg/panel"
    },
    {
      "type": "WEB",
      "url": "https://github.com/tnborg/panel/releases/tag/v2.5.6"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "RatPanel can perform remote command execution without authorization"
}

GHSA-FQC7-9XJW-JRH3

Vulnerability from github – Published: 2026-06-09 21:58 – Updated: 2026-06-09 21:58
VLAI
Summary
SymfonyRuntime CVE-2024-50340 Patch Bypass: Web Requests Can Still Set APP_ENV/APP_DEBUG via parse_str/SAPI Argv Mismatch
Details

Description

CVE-2024-50340 (GHSA-x8vp-gf4q-mw5j) addressed an issue where, with register_argc_argv=On, a crafted query string let an unauthenticated GET change the kernel environment and debug flag by feeding --env/--no-debug through $_SERVER['argv']. The fix shipped in symfony/runtime 5.4.46 / 6.4.14 / 7.1.7 gated the argv read on empty($_GET) as a proxy for "is this a CLI invocation".

That proxy is unsafe: parse_str() (which builds $_GET) and the web SAPI (which builds $_SERVER['argv'] from the raw query when register_argc_argv=On) do not agree on every input, so an attacker can craft a query that leaves $_GET empty while $_SERVER['argv'] carries the attacker's flags. SymfonyRuntime::getInput() then parses them, restoring the exact primitive CVE-2024-50340 was meant to prevent.

Preconditions and impact match the original CVE: web SAPI, register_argc_argv=On, app booted through symfony/runtime; from an unauthenticated GET an attacker can flip APP_ENV and toggle APP_DEBUG.

Resolution

SymfonyRuntime now gates the argv read on isset($_SERVER['QUERY_STRING']) rather than on empty($_GET). QUERY_STRING is the same input the SAPI uses to build argv, so the security check and the thing it protects no longer parse different sources. Worker SAPIs (FrankenPHP / RoadRunner / Swoole) keep working because the runtime constructor runs once at boot when QUERY_STRING is unset.

The patch for this issue is available here for branch 5.4.

Credits

SymfonyRuntime would like to thank 0xEr3n for reporting the issue and Nicolas Grekas for providing the fix.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "symfony/runtime"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "5.4.46"
            },
            {
              "fixed": "5.4.52"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "symfony/runtime"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "6.4.14"
            },
            {
              "fixed": "6.4.40"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "symfony/runtime"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "7.1.7"
            },
            {
              "fixed": "7.4.12"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "symfony/runtime"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "8.0.0"
            },
            {
              "fixed": "8.0.12"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "symfony/symfony"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "5.4.46"
            },
            {
              "fixed": "5.4.52"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "symfony/symfony"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "6.4.14"
            },
            {
              "fixed": "6.4.40"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "symfony/symfony"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "7.1.7"
            },
            {
              "fixed": "7.4.12"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "symfony/symfony"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "8.0.0"
            },
            {
              "fixed": "8.0.12"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-47767"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-20",
      "CWE-436",
      "CWE-74"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-06-09T21:58:11Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "### Description\n\nCVE-2024-50340 (GHSA-x8vp-gf4q-mw5j) addressed an issue where, with `register_argc_argv=On`, a crafted query string let an unauthenticated GET change the kernel environment and debug flag by feeding `--env`/`--no-debug` through `$_SERVER[\u0027argv\u0027]`. The fix shipped in `symfony/runtime` 5.4.46 / 6.4.14 / 7.1.7 gated the argv read on `empty($_GET)` as a proxy for \"is this a CLI invocation\".\n\nThat proxy is unsafe: `parse_str()` (which builds `$_GET`) and the web SAPI (which builds `$_SERVER[\u0027argv\u0027]` from the raw query when `register_argc_argv=On`) do not agree on every input, so an attacker can craft a query that leaves `$_GET` empty while `$_SERVER[\u0027argv\u0027]` carries the attacker\u0027s flags. `SymfonyRuntime::getInput()` then parses them, restoring the exact primitive CVE-2024-50340 was meant to prevent.\n\nPreconditions and impact match the original CVE: web SAPI, `register_argc_argv=On`, app booted through `symfony/runtime`; from an unauthenticated GET an attacker can flip `APP_ENV` and toggle `APP_DEBUG`.\n\n### Resolution\n\n`SymfonyRuntime` now gates the argv read on `isset($_SERVER[\u0027QUERY_STRING\u0027])` rather than on `empty($_GET)`. `QUERY_STRING` is the same input the SAPI uses to build argv, so the security check and the thing it protects no longer parse different sources. Worker SAPIs (FrankenPHP / RoadRunner / Swoole) keep working because the runtime constructor runs once at boot when `QUERY_STRING` is unset.\n\nThe patch for this issue is available [here](https://github.com/symfony/symfony/commit/3228c3806ee511008bea19a95084d460b17e5d25) for branch 5.4.\n\n### Credits\n\nSymfonyRuntime would like to thank 0xEr3n for reporting the issue and Nicolas Grekas for providing the fix.",
  "id": "GHSA-fqc7-9xjw-jrh3",
  "modified": "2026-06-09T21:58:11Z",
  "published": "2026-06-09T21:58:11Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/symfony/symfony/security/advisories/GHSA-fqc7-9xjw-jrh3"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/symfony/symfony"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "SymfonyRuntime CVE-2024-50340 Patch Bypass: Web Requests Can Still Set APP_ENV/APP_DEBUG via parse_str/SAPI Argv Mismatch"
}

No mitigation information available for this CWE.

CAPEC-105: HTTP Request Splitting

An adversary abuses the flexibility and discrepancies in the parsing and interpretation of HTTP Request messages by different intermediary HTTP agents (e.g., load balancer, reverse proxy, web caching proxies, application firewalls, etc.) to split a single HTTP request into multiple unauthorized and malicious HTTP requests to a back-end HTTP agent (e.g., web server).

See CanPrecede relationships for possible consequences.

CAPEC-273: HTTP Response Smuggling

An adversary manipulates and injects malicious content in the form of secret unauthorized HTTP responses, into a single HTTP response from a vulnerable or compromised back-end HTTP agent (e.g., server).

See CanPrecede relationships for possible consequences.

CAPEC-34: HTTP Response Splitting

An adversary manipulates and injects malicious content, in the form of secret unauthorized HTTP responses, into a single HTTP response from a vulnerable or compromised back-end HTTP agent (e.g., web server) or into an already spoofed HTTP response from an adversary controlled domain/site.

See CanPrecede relationships for possible consequences.