This is graffiti on the inside wall, not a battering ram at the front gate
CVE-2026-40108 is a stored XSS in GLPI ITIL Costs on the 11.0 branch, affecting 11.0.0 through 11.0.6 and fixed in 11.0.7. The attacker plants script in a cost-related field tied to tickets or changes; when another user later opens the affected view, the browser executes attacker-controlled JavaScript in that user's GLPI session.
GLPI labels this issue High, but there is no published vendor CVSS score. For enterprise triage, this behaves more like a post-initial-access admin-console abuse bug than a perimeter emergency: the attacker needs a technician-level authenticated foothold to seed the payload, the victim must hit the right page, and the blast radius depends on which privileged user views it. That is why this is = ASSESSED AT MEDIUM, even though the technical impact can become serious after successful session riding.
4 steps from start to impact.
Get a technician session
Hydra for credential attacks or straight browser reuse of stolen cookies.- GLPI login is reachable to the attacker
- A valid account exists with technician or equivalent rights
- MFA/SSO controls do not stop account takeover
- This is not unauthenticated remote exploitation
- Many enterprises front GLPI with SSO, VPN, or reverse proxies
- Technician rights are a narrower population than ordinary requesters
Store the payload in ITIL Costs
Burp Suite, the attacker writes a JavaScript payload into an ITIL cost field. This is a classic stored XSS staging step: the payload persists server-side and waits for a future viewer rather than firing immediately.- The target instance runs GLPI 11.0.0-11.0.6
- The attacker can create or edit the affected ITIL cost object
- Server-side sanitization is missing on the vulnerable field
- Only the 11.0 branch is implicated by the vendor bulletin
- Profile configuration may restrict who can touch cost objects
- Well-run teams often have limited use of cost fields compared with tickets themselves
Wait for a higher-value viewer
BeEF-style browser hooks to steal CSRF tokens, replay in-session actions, or pivot into admin-only GLPI functions without needing raw password disclosure.- A privileged or otherwise useful user views the poisoned ticket/change cost view
- The victim browser executes inline or attacker-supplied script
- Session controls do not fully neutralize script-driven actions
- There is a UI requirement and often a specific page-view requirement
- HttpOnly can block direct cookie theft even if action riding remains possible
- CSP, browser hardening, or re-auth prompts can reduce post-XSS payoff
Abuse the inherited GLPI trust
- The victim session has materially higher privileges than the attacker
- The session remains valid long enough to complete follow-on actions
- Blast radius is bounded by the victim's role and module access
- This does not inherently give shell access to the GLPI host
- Operationally, many actions still leave visible audit traces inside GLPI
The supporting signals.
| In-the-wild status | No public evidence of active exploitation found in accessible reporting reviewed here. It is not in CISA KEV and no campaign reporting was located. |
|---|---|
| KEV status | Not KEV-listed as of the reviewed sources; user prompt also states KEV listed: No. |
| EPSS | No EPSS value located yet; Feedly shows "No EPSS yet" for this CVE, which is consistent with a newer record. |
| Proof-of-concept availability | No public PoC repo or exploit write-up located for CVE-2026-40108 specifically. That lowers opportunistic abuse volume, though XSS payload construction is trivial for anyone who already has app access. |
| Affected versions | GLPI 11.0.0 through 11.0.6 are the specifically identified vulnerable releases per third-party indexing of the CVE and the vendor's 11.0.7 security release context. |
| Fixed versions | Fixed in GLPI 11.0.7. The vendor bulletin lists the issue as High on 11.0 only; 10.0.25 shipped the same day but this CVE is not listed for 10.0, so treat 10.x as not affected for this CVE unless your own testing proves otherwise. |
| Vendor severity / scoring | Vendor release notes label it High, but no official CVSS vector or score was found. Because there is no published baseline score, this review is = ASSESSED AT MEDIUM rather than upgraded or downgraded. |
| CVSS-style interpretation | No official CVSS published. Functionally this looks like an *authenticated stored XSS with user interaction* problem: remote over web, low attack complexity, requires privileges, and payoff depends on who views the poisoned record. |
| Exposure / scanning reality | Public GLPI instances are clearly discoverable on the internet; community guidance shows common search patterns such as http.title:"GLPI" in Shodan and services.http.response.html_title: GLPI in Censys. I did not obtain a trustworthy live host count from accessible primary sources, so treat exposure as real but unquantified here. |
| Disclosure timeline | The fix shipped on 2026-04-29 in GLPI 11.0.7, and CERT-FR published on 2026-05-07. The user-supplied 2026-06-02 likely reflects a later catalog/publication date rather than the first vendor disclosure. |
noisgate verdict.
The decisive downgrading factor is attacker position: this bug starts with an authenticated technician-level user, which makes it a post-initial-access problem rather than a perimeter-breaker. The impact can be ugly if a privileged user opens the poisoned record, but the reachable population and exploit chain are both materially narrower than an internet-facing pre-auth flaw.
Why this verdict
- Start from High technical impact: stored XSS inside a trusted ITSM/admin plane can absolutely become admin action replay, token theft, or sensitive ticket/data exposure.
- Down one notch for attacker position: the chain requires an authenticated technician-equivalent account to plant the payload, which implies prior compromise, insider access, or credential theft before the CVE even starts to matter.
- Down again for reachability: only the 11.0 branch is implicated, and the exploit still needs the right victim to open the right poisoned record, adding UI friction and reducing real-world execution rate.
- No exploitation amplifier: there is no KEV listing, no public campaign reporting, and no public PoC located, so there is no evidence-based reason to treat this as a hot exploit queue item.
- Blast radius is role-bound: XSS inherits whatever the viewing user can do in GLPI; if the viewer is low-privilege, the payoff is limited, and even with higher privilege it remains an application-session compromise, not immediate host takeover.
Why not higher?
This is not an unauthenticated internet exploit, not a direct server compromise, and not a universally reachable workflow. Requiring a technician-level foothold plus a second user interaction step creates compound friction that should keep it out of the HIGH bucket for most 10,000-host enterprises.
Why not lower?
It still sits inside a management plane that holds sensitive asset, ticket, and workflow data, and stored XSS in that context is more than cosmetic. If a privileged operator or admin regularly reviews cost-bearing tickets or changes, the attacker can convert one compromised technician account into broader GLPI control.
What to do — in priority order.
- Restrict ITIL cost editing — Limit who can create or modify ITIL Costs to the smallest operational group possible, ideally finance-specific or senior service-management roles. For a MEDIUM verdict there is no mitigation SLA — go straight to the 365-day remediation window, but this permission trim is cheap risk reduction and should be done during your normal role-review cycle well before patch completion.
- Put GLPI behind stronger identity controls — Require SSO and MFA for all technician and admin profiles, or at minimum restrict GLPI administration to VPN or trusted network paths. This directly attacks the most important prerequisite: getting the authenticated technician foothold in the first place; with no mitigation SLA on a MEDIUM item, fold it into your standard hardening backlog while still patching within the remediation window.
- Harden session cookies and browser trust — Set PHP/GLPI session protections such as
session.cookie_httponly=On,session.cookie_secure=On, and sane SameSite behavior so XSS has a harder time stealing reusable session material. This will not stop all in-session action riding, but it meaningfully reduces the easiest post-exploitation win and should be deployed as standard hygiene before the 365-day remediation deadline. - Review GLPI profile sprawl — Audit who actually has technician or elevated service-desk roles and remove stale access, shared accounts, and generic break-glass profiles. Because this CVE only matters after authenticated write access is obtained, entitlement cleanup is one of the highest-return compensating controls you can deploy during the normal remediation cycle.
- Watch for suspicious script-bearing content — Add log or database review for cost fields containing
<script>,onerror=,javascript:, encoded payloads, or abnormal HTML. This is detective control only, not prevention, but it can catch abuse attempts while you move toward the patch inside the 365-day remediation window.
- A WAF alone will not reliably save you; the malicious content is stored through legitimate authenticated application traffic and often renders later inside a trusted browser session.
- Server EDR is mostly blind if the attacker never leaves the web-app/session layer. No shell, no dropped file, no useful telemetry.
- Network segmentation does not solve browser-executed XSS once the victim is already on the application page.
- Patching browsers is not a fix; the bug is application-side output handling, not a browser memory corruption issue.
Crowdsourced verification payload.
Run this on the GLPI application host or in the container/VM where GLPI files live. Invoke it as bash verify-cve-2026-40108.sh /var/www/glpi or pass an explicit version string like bash verify-cve-2026-40108.sh 11.0.6; it needs only read access to the GLPI directory and the ability to execute php if you want automatic version detection from bin/console.
#!/usr/bin/env bash
# verify-cve-2026-40108.sh
# Checks whether a GLPI instance is vulnerable to CVE-2026-40108
# Affected: 11.0.0 through 11.0.6
# Fixed: 11.0.7+
# Not affected for this CVE: 10.x branch per vendor bulletin context
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN, 3=USAGE
set -u
TARGET="${1:-}"
usage() {
echo "Usage: $0 <glpi_root_path|version>"
exit 3
}
if [[ -z "$TARGET" ]]; then
usage
fi
trim() {
local s="$1"
s="${s#${s%%[![:space:]]*}}"
s="${s%${s##*[![:space:]]}}"
printf '%s' "$s"
}
extract_version() {
local input="$1"
local root console_out ver
# If caller passed a plain version, use it directly.
if [[ "$input" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "$input"
return 0
fi
root="$input"
if [[ ! -d "$root" ]]; then
return 1
fi
# Best effort 1: Symfony/GLPI console version output.
if [[ -x "$root/bin/console" || -f "$root/bin/console" ]]; then
if command -v php >/dev/null 2>&1; then
console_out="$(php "$root/bin/console" --version 2>/dev/null || php "$root/bin/console" -V 2>/dev/null || true)"
ver="$(printf '%s\n' "$console_out" | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+' | head -n1 || true)"
if [[ -n "$ver" ]]; then
echo "$ver"
return 0
fi
fi
fi
# Best effort 2: parse known GLPI diagnostic artifacts/logs for GLPI_VERSION.
ver="$(grep -RhoE 'GLPI_VERSION[:=][[:space:]]*"?[0-9]+\.[0-9]+\.[0-9]+' "$root" 2>/dev/null | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+' | head -n1 || true)"
if [[ -n "$ver" ]]; then
echo "$ver"
return 0
fi
return 1
}
ver_ge() {
# returns 0 if $1 >= $2
[[ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | tail -n1)" == "$1" ]]
}
ver_lt() {
# returns 0 if $1 < $2
[[ "$1" != "$2" ]] && [[ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" == "$1" ]]
}
VERSION="$(extract_version "$TARGET" || true)"
VERSION="$(trim "$VERSION")"
if [[ -z "$VERSION" ]]; then
echo "UNKNOWN: could not determine GLPI version from '$TARGET'"
exit 2
fi
# Branch logic.
case "$VERSION" in
10.*)
echo "PATCHED: GLPI $VERSION is not in the affected 11.0 branch for CVE-2026-40108"
exit 0
;;
11.*)
if ver_ge "$VERSION" "11.0.0" && ver_lt "$VERSION" "11.0.7"; then
echo "VULNERABLE: GLPI $VERSION is within the affected range 11.0.0-11.0.6"
exit 1
elif ver_ge "$VERSION" "11.0.7"; then
echo "PATCHED: GLPI $VERSION is fixed for CVE-2026-40108"
exit 0
else
echo "UNKNOWN: GLPI $VERSION is on 11.x but could not be classified"
exit 2
fi
;;
*)
echo "UNKNOWN: unrecognized GLPI version '$VERSION'"
exit 2
;;
esac
If you remember one thing.
Sources
- GLPI official release note for 11.0.7 / 10.0.25
- GLPI GitHub releases
- CERT-FR advisory CERTFR-2026-AVI-0551
- Feedly CVE tracking page
- Zero Redgem CVE index entry
- ITčko summary of GLPI 11.0.7 security fixes
- GLPI Help Center CLI documentation
- GLPI issue showing security recommendations for HttpOnly/Secure cookies
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.