GHSA-GFHX-HW2G-V5HG

Vulnerability from github – Published: 2026-09-30 15:40 – Updated: 2026-09-30 15:40
VLAI
Summary
Serialize JavaScript: Cross-site scripting (XSS) via unescaped </script> in serialized function bodies
Details

Impact

serialize-javascript escapes its output so it is safe to embed inside a <script> element. In 7.1.1 that guarantee does not hold for function values: a crafted function body can carry a literal, unescaped </script> into the output, terminating the script element early so the remainder is parsed as HTML.

SCRIPT_CLOSE_REGEXP used <\/script[^>]*> as its first alternative. The character class excludes only >, so a single match could run from one `

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "serialize-javascript"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "7.1.1"
            },
            {
              "fixed": "7.1.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-97711"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-79",
      "CWE-80"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-09-30T15:40:05Z",
    "nvd_published_at": "2026-09-29T16:17:19Z",
    "severity": "LOW"
  },
  "details": "### Impact\n\n`serialize-javascript` escapes its output so it is safe to embed inside a\n`\u003cscript\u003e` element. In 7.1.1 that guarantee does not hold for **function\nvalues**: a crafted function body can carry a literal, unescaped `\u003c/script\u003e`\ninto the output, terminating the script element early so the remainder is\nparsed as HTML.\n\n`SCRIPT_CLOSE_REGEXP` used `\u003c\\/script[^\u003e]*\u003e` as its first alternative. The\ncharacter class excludes only `\u003e`, so a single match could run from one\n`\u003c/script` all the way to the next `\u003e` anywhere in the source \u2014 swallowing a\nsecond, complete `\u003c/script\u003e` along the way. Only one replacement is emitted\nper match, and the plain-code branch neutralizes just the leading `\u003c`\n(`\u0027\u003c \u0027 + match.slice(1)`), so the swallowed tag was re-emitted verbatim.\n\nReaching that shape requires `\u003c/script` in code position, which is legal\nJavaScript: `x\u003c/script=+/` parses as `x \u003c /script=+/`, a comparison against a\nregex literal.\n\n```js\nconst serialize = require(\u0027serialize-javascript\u0027);\nconst src = \"function f(x){ return x\u003c/script=+/ + \u0027\u003c/script\u003e\u003cimg src=x onerror=alert(1)\u003e\u0027 }\";\nconst out = serialize({ h: new Function(\u0027return \u0027 + src)() });\n// {\"h\":function f(x){ return x\u003c /script=+/ + \u0027\u003c/script\u003e\u003cimg src=x onerror=alert(1)\u003e\u0027 }}\n```\n\nEmbedded as the README documents (`\u003cscript\u003ewindow.S = \u003c%= serialize(state) %\u003e\u003c/script\u003e`)\nand parsed by Chromium, the script element ends at the injected tag and the\n`\u003cimg\u003e` becomes a live DOM node with its `onerror` handler executing in the\npage origin.\n\nOnly the function path is affected. The same payload passed as **data** is\nescaped correctly, and `options.isJSON` / non-function values are unaffected.\n\n### Patches\n\nFixed in **7.1.2**. The wildcard now excludes `\u003c` as well as `\u003e`\n(`[^\u003c\u003e]*`), so a match can never reach past a second `\u003c`. Every `\u003c/script`\nin the source therefore either begins its own match or is followed by a\ncharacter the HTML tokenizer does not accept as ending a tag name \u2014 it ends\nthe tag name only on TAB, LF, FF, CR, SPACE, `/` or `\u003e`, and emits anything\nelse as text.\n\n### Workarounds\n\nUpgrade to **7.1.2**. If you cannot upgrade, 7.1.0 and earlier are\nunaffected, or avoid serializing functions whose source text is\nattacker-influenced.\n\n### Regression note\n\nThis is a regression specific to 7.1.1, not a long-standing issue. 7.1.0 and\nearlier applied the same wildcard but escaped the **entire** match, so no tag\nsurvived. Downstream scanners defaulting to a `\u003e= 7.1.0` range would be\noverly broad.",
  "id": "GHSA-gfhx-hw2g-v5hg",
  "modified": "2026-09-30T15:40:06Z",
  "published": "2026-09-30T15:40:05Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/yahoo/serialize-javascript/security/advisories/GHSA-gfhx-hw2g-v5hg"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-97711"
    },
    {
      "type": "WEB",
      "url": "https://github.com/yahoo/serialize-javascript/commit/2bdbaaff9cb8a4639135eb24cfcd383d3fefb534"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/yahoo/serialize-javascript"
    },
    {
      "type": "WEB",
      "url": "https://github.com/yahoo/serialize-javascript/releases/tag/v7.1.2"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Serialize JavaScript: Cross-site scripting (XSS) via unescaped \u003c/script\u003e in serialized function bodies"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…