CVE-2026-109322
Executive Summary
CVE-2026-109322 is a stored cross-site scripting (XSS) vulnerability in the Grav Guestbook plugin affecting versions prior to 0.5.2 (confirmed in 0.5.0 and 0.5.1). The flaw exists because the plugin's AJAX "Load more" and "Admin Load all" handlers render stored author and message fields as unescaped HTML using jQuery, allowing unauthenticated visitors to inject persistent markup that executes in other visitors' browsers — and, in versions 0.5.0 and 0.5.1, within administrator moderation sessions. An attacker can compromise the integrity of the guestbook page, hijack visitor browser sessions, and potentially perform privileged actions as an administrator via stored payloads.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Technical Analysis
CVE-2026-109322 is classified as CWE-79 (Improper Neutralization of Input During Web Page Generation, commonly "Cross-site Scripting"). The vulnerability class is stored XSS, meaning the malicious payload is persisted server-side (in the guestbook entries) and retrieved on subsequent page views rather than being reflected from a single request.
The specific failure point, per the NVD description, is the plugin's client-side rendering logic. Two AJAX handlers — "Load more" (available on the public-facing guestbook) and "Admin Load all" (available in the administrative moderation interface) — insert the stored author and message fields into the DOM "as unescaped HTML via jQuery." jQuery's HTML-insertion methods (such as .html(), .append(), etc.) do not escape their argument; when server-supplied data is passed directly, any markup it contains becomes live DOM. Because the author and message values originate from unauthenticated visitor submissions, an attacker controls the exact content that is later rendered into other users' browsers.
Two properties elevate the risk beyond a typical self-XSS:
- Unauthenticated write. Any visitor can submit a guestbook entry containing markup; no account or privilege is required to plant the payload.
- Cross-user and cross-privilege execution. The payload executes in the browser of every subsequent visitor whose client loads the affected entries. Critically, in versions 0.5.0 and 0.5.1, the "Admin Load all" handler renders the same unescaped fields within administrator moderation sessions — meaning a stored payload can execute with the admin's session context, escalating a public guestbook flaw into a potential administrative compromise vector.
Input sanitization failure occurs on the output/rendering side rather than at submission time. The NVD description does not specify whether server-side storage sanitizes the fields; the observable defect is that the AJAX handlers treat stored values as trusted HTML. The CVSS vector (AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N) reflects a network-reachable, low-complexity attack requiring no privileges but user interaction, with scope change — consistent with XSS that escapes the vulnerable component's intended security context to affect other users' browsers and sessions.
Exploitation Scenarios
No public PoC is available for CVE-2026-109322. The attack chain below is inferred from the stored-XSS vulnerability class and the specific handlers named in the NVD description; no specific payload, function name, or endpoint beyond those in the description is asserted.
Reconnaissance / target identification. An attacker identifies a Grav-based site running the Guestbook plugin at a version below 0.5.2 (0.5.0 or 0.5.1 for the admin-session variant). Identification can be performed passively by browsing the guestbook page, observing the plugin's AJAX-driven "Load more" behavior, and fingerprinting the front-end framework, or by enumerating known Grav plugin paths and page slugs.
Triggering the flaw class (injection). The attacker submits a new guestbook entry as an ordinary, unauthenticated visitor. The
authorand/ormessagefields are populated with markup that will be interpreted as HTML/script when rendered. Because the plugin persists entries and later loads them through the vulnerable AJAX handlers, the payload is stored rather than reflected.Payload execution (rendering). When any visitor triggers the "Load more" AJAX handler — or when an administrator opens the moderation interface and the "Admin Load all" handler runs — the plugin inserts the stored
authorandmessagevalues into the DOM as unescaped HTML via jQuery. The embedded markup executes in that user's browser context. In versions 0.5.0 and 0.5.1, this includes the administrator's authenticated moderation session.Post-exploitation impact. In a visitor's browser, successful execution allows the attacker to act as the victim site's origin: read and modify page content, exfiltrate data accessible to the page, perform actions on behalf of the victim (CSRF-style request forgery against the application), or redirect the user. In the administrator-context variant, the attacker may perform privileged moderation or configuration actions available to the admin, or exfiltrate session material that enables session hijacking. Note that the CVSS vector scopes confidentiality and integrity impacts as Low (C:L/I:L) with no availability impact (A:N), reflecting meaningful but bounded damage per the scoring analysis.
Impact Assessment
The CVSS v3.1 base score is 6.1 (Medium) with vector CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N. Breaking this down against the described vulnerability:
- AV:N (Network) — the guestbook is a web-facing component; no local access is needed.
- AC:L (Low) — no special conditions or race windows; standard web requests suffice.
- PR:N (None) — submission of a malicious entry requires no account or privilege.
- UI:R (Required) — a victim must load a page that renders the stored payload (any visitor, or an admin in affected versions).
- S:C (Changed) — execution escapes the vulnerable component's security scope into the broader site/browser session context.
- C:L / I:L — limited confidentiality and integrity impact, consistent with XSS affecting session data and page content.
- A:N — no availability impact.
Blast radius. Every Grav installation running the Guestbook plugin below 0.5.2 that exposes a public guestbook is in scope. The population of affected visitors is potentially large on high-traffic sites, since the payload persists and re-executes for every user who triggers the affected AJAX handlers. The most severe consequence is reserved for versions 0.5.0 and 0.5.1, where the administrator moderation interface loads the same unescaped fields — placing privileged sessions at risk. Business impact includes defacement of guestbook content, theft of user session data on the affected origin, reputational damage, and potential administrative account compromise leading to broader site takeover. EPSS has not yet been scored by FIRST.org, and CISA KEV does not list this CVE; no observed in-the-wild exploitation is currently reported, but stored XSS in unauthenticated-input components is a commonly targeted class.
Detection Guidance
Sigma Rule
title: Grav Guestbook Plugin Stored XSS Attempt (CVE-2026-109322)
id: 4c9f1a72-7b3e-4d21-9e88-0a5c2f6d1b44
status: experimental
description: Detects guestbook entry submissions containing HTML/script markup targeting the Grav Guestbook plugin AJAX Load handlers (CVE-2026-109322).
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-109322
author: valtersit.com
date: 2026-01-01
logsource:
category: webserver
detection:
selection_endpoint:
cs-method: 'POST'
cs-uri-query|contains:
- 'guestbook'
selection_payload:
cs-uri-query|contains:
- '<script'
- 'onerror='
- 'onload='
- 'javascript:'
- '<img'
- '<svg'
- 'document.cookie'
condition: selection_endpoint and selection_payload
falsepositives:
- Legitimate users posting code snippets or discussing HTML in messages
level: medium
tags:
- attack.t1189
- cwe.79
YARA Rule
rule CVE_2026_109322_Grav_Guestbook_Stored_XSS
{
meta:
description = "Detects stored XSS payload markers submitted to Grav Guestbook plugin (< 0.5.2)"
author = "valtersit.com"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2026-109322"
date = "2026-01-01"
cve = "CVE-2026-109322"
strings:
$a1 = "<script" nocase
$a2 = "</script>" nocase
$a3 = "onerror=" nocase
$a4 = "onload=" nocase
$a5 = "javascript:" nocase
$a6 = "document.cookie" nocase
$a7 = "<svg" nocase
$a8 = "<img" nocase
condition:
any of ($a*)
}
Suricata IDS Rule
alert http any any -> any any (msg:"CVE-2026-109322 Grav Guestbook Stored XSS Attempt"; flow:to_server,established; http.method; content:"POST"; http.uri; content:"guestbook"; nocase; http.request_body; content:"<script"; nocase; http.request_body; content:"<img"; nocase; http.request_body; content:"onerror="; nocase; classtype:web-application-attack; reference:cve,2026-109322; sid:2026109322; rev:1;)
Elastic Detection
sequence by source.ip with maxspan=30s
[network where http.request.method == "POST" and url.path : "*guestbook*"]
[network where http.request.method == "POST" and url.path : "*guestbook*" and
(http.request.body.content : "*<script*" or http.request.body.content : "*onerror=*" or
http.request.body.content : "*javascript:*" or http.request.body.content : "*<svg*")]
Splunk SPL Query
index=web sourcetype=access_combined OR sourcetype=nginx:plus:access
| where like(lower(uri), "%guestbook%") AND method="POST"
| eval body_check = if(match(lower(_raw), "<script|onerror=|onload=|javascript:|%3cscript|document\.cookie"), 1, 0)
| where body_check=1
| stats count min(_time) as first_seen max(_time) as last_seen by src_ip, uri, method
| sort - count
| convert ctime(first_seen) ctime(last_seen)
Wazuh OSSEC Rule
<group name="web,appsec,cve-2026-109322,">
<rule id="109322" level="10">
<decoded_as>web-accesslog</decoded_as>
<if_sid>31100</if_sid>
<id>^POST</id>
<url>guestbook</url>
<regex type="pcre2">(?i)(<script|onerror=|onload=|javascript:|document\.cookie|%3cscript)</regex>
<description>CVE-2026-109322: Possible Grav Guestbook stored XSS payload submitted in POST to guestbook endpoint</description>
<mitre>
<id>T1189</id>
</mitre>
</rule>
</group>
Mitigation & Patch Guidance
Patch confidence: 0/4 (UNPATCHED — no patch evidence from any tracked source). No vendor fix, patch source, or workaround has been confirmed through tracked sources. The following guidance is based on the vulnerability class and the affected component's behavior.
Immediate mitigations (no patch available):
- Output-encode guestbook fields. Because the defect is unescaped HTML insertion via jQuery in the "Load more" and "Admin Load all" handlers, ensure that stored
authorandmessagevalues are rendered using text-safe methods (e.g., jQuery's.text()/.textContentsemantic) rather than HTML-insertion methods. This closes the client-side sink even before an upstream fix. - Sanitize at submission (defense in depth). Apply server-side input sanitization/HTML escaping to guestbook submissions so markup cannot be persisted, and validate against existing stored entries already containing markup.
- Disable or restrict the plugin. If the guestbook is non-essential, disable the Grav Guestbook plugin until a fixed version is available. If it must remain, restrict the admin moderation surface to trusted networks and require re-authentication where possible.
- Deploy WAF rules. Block submissions whose content contains script/markup patterns (see detection rules above) to reduce injection at the edge.
- Output-encode guestbook fields. Because the defect is unescaped HTML insertion via jQuery in the "Load more" and "Admin Load all" handlers, ensure that stored
Patch / upgrade steps: Upgrade the Grav Guestbook plugin to version 0.5.2 or later, which is the version identified as containing the fix boundary ("before 0.5.2"). Until a verified vendor advisory or release artifact is available, validate the upgrade through the plugin's official distribution channel and confirm the rendered handlers escape stored fields. Monitor the Grav plugin repository and vendor channels for an official security release.
Long-term hardening:
- Adopt a content security policy (CSP) that disallows inline script execution to limit XSS payload impact.
- Implement output encoding as a framework-standard practice across all plugins that render user-supplied content.
- Enable integrity monitoring on the guestbook data store to detect injection of markup into stored entries.
- Track CVE-2026-109322 through NVD and the Grav security channels for the formal patch and any revision to the CVSS score or EPSS.
References
- NVD — CVE-2026-109322: https://nvd.nist.gov/vuln/detail/CVE-2026-109322
- MITRE CWE-79 — Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting'): https://cwe.mitre.org/data/definitions/79.html
- FIRST EPSS (not yet scored at time of writing): https://www.first.org/epss/
- CISA Known Exploited Vulnerabilities Catalog (CVE-2026-109322 not listed): https://www.cisa.gov/known-exploited-vulnerabilities-catalog
- Grav Guestbook plugin distribution channel (verify 0.5.2+ release availability): https://getgrav.org/ and the plugin's repository listing
No public proof-of-concept, Nuclei template, or exploit code is currently available for CVE-2026-109322. No threat actor campaign or exploit-in-the-wild evidence is associated with this CVE as of this writing.
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.