Leaving a loaded mousetrap in a mailroom that only the postmaster can trigger
CVE-2026-102147 is a stored cross-site scripting flaw in Kiteworks Core < 9.5.1 that lets an *unauthenticated* attacker inject malicious JavaScript through a publicly accessible content-submission endpoint. The payload persists in the database and fires when an authenticated administrator views the affected page. Once triggered, the script runs in the admin's browser session and can create a new administrative account, giving the attacker persistent full-privilege access to the platform — including every file, user, transfer log, and integration credential managed by Kiteworks.
The vendor rates this CRITICAL 9.3, and the CVSS vector (AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N) is technically defensible on paper. In practice, though, 9.3 overstates the urgency relative to a true unauthenticated RCE. The chain cannot fire without an admin visiting the booby-trapped page — a probabilistic gate the CVSS UI:R metric undervalues. Kiteworks *does* use HttpOnly session cookies (so the XSS cannot directly exfiltrate the session token), but it ships no Content Security Policy, meaning any injected inline script will execute without browser-side interference. The attacker can still create a rogue admin account by issuing API calls from within the admin's session context. The realistic severity is HIGH (8.2): dangerous enough to warrant fast patching, but the user-interaction bottleneck and browser-mediated execution make it fundamentally different from the remote-code-execution bugs that earn CRITICAL in the field.
5 steps from start to impact.
Identify internet-facing Kiteworks instance
http.title:"Kiteworks" or http.favicon.hash:-1923055866), Censys, or FOFA. Shadowserver has identified ~400 exposed instances (234 in the US); Kevin Beaumont estimates ~1,000 total. Because Kiteworks is a managed-file-transfer platform, it is internet-facing *by design*.- Kiteworks instance reachable over the public internet
- Kiteworks is designed for external access, so this is not a real friction point
Inject stored XSS payload via public endpoint
- Kiteworks Core < 9.5.1
- No public PoC exists — attacker must independently identify the vulnerable endpoint
- Without a public PoC, an attacker must reverse-engineer the injection surface, which requires non-trivial effort
- Kiteworks has not disclosed the specific endpoint, limiting opportunistic mass-exploitation
<script>, event handlers (onerror, onload), and encoded variants can flag common XSS payloads. No Nuclei template or Nessus plugin specific to this CVE exists yet.Wait for administrator to view stored content
- An administrator must load the affected page in their browser
- The administrator's browser must execute inline JavaScript (no CSP blocks this on Kiteworks)
- Timing is unpredictable — could take minutes or days
- If the organization uses a dedicated admin browser profile with restrictive extensions (e.g., NoScript, uBlock Origin), the script may be blocked
XSS executes in admin session context
HttpOnly (blocking document.cookie access), the script operates within the admin's authenticated session and can issue same-origin API requests. The attacker's script calls the Kiteworks admin API to create a new administrative account with attacker-controlled credentials.- No Content Security Policy enforced on the Kiteworks instance
- Admin browser does not have third-party script-blocking extensions
- HttpOnly cookies prevent direct session-token theft, forcing the attacker to operate within the browser session rather than replaying the token externally
- Organizations with browser-isolation or VDI for admin tasks add an additional layer
POST /api/v*/users with admin role) without corresponding change-management tickets. Audit log monitoring for new admin accounts is the most reliable detection.Persistent admin access and data exfiltration
- Successful admin account creation in Step 4
- MFA on admin login would block direct credential login even after account creation (though the XSS could also disable MFA policy if the API allows it)
- Network segmentation or IP allowlisting on admin endpoints adds friction
<script>, event handler attributes (onerror, onload, onfocus), javascript: URIs, and HTML-encoded variants. Apply to all Kiteworks-fronting virtual servers. This blocks the injection at Step 2 of the attack chain before the payload reaches the database. Deploy within 30 days per the noisgate mitigation SLA for HIGH-severity findings.POST to user-management API endpoints where the role is admin or system_admin. This doesn't prevent the attack but ensures you detect it within minutes of detonation (Step 4 → Step 5 transition). Mean time to detection directly limits data exfiltration window. Deploy within 30 days./admin and admin API endpoints to a known set of management IPs or a VPN-gated network. This prevents the attacker from logging in with the rogue admin account from an external IP (Step 5). The XSS still fires in the legitimate admin's browser from the allowed network, but the attacker's direct login attempt from an external IP is blocked. Deploy within 30 days.- Browser-level CSP headers injected by reverse proxy — Adding CSP via a reverse proxy (e.g.,
Content-Security-Policy: script-src 'self') *could* help in theory, but Kiteworks is a complex web application that likely uses inline scripts andeval()for legitimate functionality. A restrictive CSP will almost certainly break the application unless Kiteworks publishes a supported CSP policy. Do not attempt without thorough testing. - Disabling JavaScript in the admin's browser — Kiteworks's admin interface is a JavaScript-heavy SPA; disabling JS renders it non-functional. Not a viable control.
- Network-level IDS/IPS signatures — The XSS payload is injected via an HTTPS POST body. Unless you're performing TLS inspection on Kiteworks traffic, network IDS cannot see the payload. Even with TLS inspection, stored-XSS signatures have high false-positive rates on MFT platforms that legitimately handle HTML content.
The supporting signals.
| In-the-wild exploitation | Not confirmed. No KEV listing. No GreyNoise tags. Kiteworks states 'no indication the vulnerability was ever exploited.' However, federal intelligence agencies warned Kiteworks of an *imminent* attack on Sept 25, 2026, prompting a precautionary 9-hour shutdown — this involved a separate zero-day (no CVE assigned, affecting <1% of customers), not CVE-2026-102147 directly. |
|---|---|
| Threat actor interest | Elevated. Kiteworks (formerly Accellion) is the same vendor whose legacy FTA product was mass-exploited by Clop/FIN11 in 2020–2021. Clop has since systematically targeted GoAnywhere, MOVEit, and Cleo MFT platforms. The federal intelligence warning in Sept 2026 suggests ongoing threat actor reconnaissance against Kiteworks infrastructure. |
| Proof-of-concept | None public. No PoC on GitHub, ExploitDB, pocindex.io, Nuclei templates, or Metasploit as of 2026-10-01. The specific injection endpoint has not been disclosed. This significantly raises the bar for opportunistic exploitation. |
| EPSS score | Not yet scored. CVE was published 2026-09-30; EPSS model has not ingested it. Expect initial scoring within 7–14 days. Comparable stored-XSS-to-admin-takeover CVEs in enterprise web apps typically land in the 5–15th percentile range absent a public PoC. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N — Network-accessible, low complexity, no privileges required, user interaction required, scope changed, high confidentiality and integrity impact. The UI:R and S:C are the pivotal metrics: UI:R gates the entire chain on admin behavior; S:C reflects XSS executing in a different security context than the vulnerable component. |
| Affected versions | Kiteworks Core < 9.5.1 (all prior versions from 0.x). Some critical flaws in the 78-CVE batch were fixed in 9.5.0; this specific CVE requires 9.5.1. |
| Fixed version | Kiteworks Core 9.5.1 (released ~2026-09-30). Part of a batch fixing 78 vulnerabilities (9 Critical, 35 High, 29 Medium, 5 Low). |
| Exposure data | Shadowserver: ~400 internet-facing instances (234 US). Kevin Beaumont estimate: ~1,000 (may overcount). Shodan dork: http.title:"Kiteworks" or http.favicon.hash:-1923055866. Kiteworks serves 3,800+ organizations including government agencies and regulated industries. |
| Disclosure timeline | 2026-09-25: Federal intelligence warning → precautionary shutdown (separate zero-day). 2026-09-27: Shutdown lifted, patch deployed. 2026-09-30: CVE-2026-102147 published as part of 78-CVE batch. 2026-10-01: NVD status 'Awaiting Analysis.' |
| Discovery credit | Not attributed. No researcher or organization credited in the advisory or GHSA (GHSA-xgh2-fgj6-w93r). Likely found via internal audit or third-party pentest. |
Sources.
- The Hacker Wire — CVE-2026-102147 Analysis
- Strix AI — CVE-2026-102147 Fix & Details
- SecurityOnline — Kiteworks Patches 78 Vulnerabilities
- TechCrunch — Kiteworks Shutdown Advisory
- BleepingComputer — Kiteworks Patches Critical Flaw
- The Hacker News — Kiteworks Nine-Hour Shutdown
- GHSA-xgh2-fgj6-w93r — GitHub Security Advisory
- UpGuard — Kiteworks Security Rating
Why this verdict
- User-interaction gate halves the weaponization odds. The entire chain depends on an administrator visiting a specific page. Unlike RCE, the attacker cannot force execution — they plant a trap and wait. Real-world admin browsing patterns are unpredictable, and organizations using dedicated admin browser profiles with script blockers (NoScript, uBlock) may prevent detonation entirely. This friction is under-weighted by the
UI:Rmetric in CVSS, which only applies a ~0.6-point penalty. - No CSP but HttpOnly cookies limit blast options. Kiteworks lacks a Content Security Policy (so the XSS fires), but session cookies *are* HttpOnly (so direct token exfiltration fails). The attacker must operate within the browser session — making API calls to create an admin account — rather than stealing the token for offline replay. This constrains the attack to the lifespan of the admin's tab and adds detection surface (anomalous admin-creation API calls).
- No public PoC raises the skill bar. The injection endpoint is undisclosed. No GitHub repos, ExploitDB entries, or Nuclei templates target this CVE. An attacker must independently identify the vulnerable input surface, which requires application-specific reconnaissance. This filters out drive-by and script-kiddie exploitation.
- Role multiplier: Kiteworks is *canonically* a high-value-role component — it is an internet-facing MFT platform handling regulated data (PII, PHI, financial records) for 3,800+ organizations including government agencies. Admin takeover = access to all stored files, transfer credentials, user accounts, and integration secrets. The blast radius is tenant-level data egress — equivalent to the MOVEit/GoAnywhere breaches that affected hundreds of downstream organizations. The chain succeeds in this canonical deployment role. This sets a floor of HIGH. Clop/FIN11's documented pattern of systematically targeting MFT platforms (Accellion FTA → GoAnywhere → MOVEit → Cleo) means the threat-actor interest is not theoretical.
- XSS ≠ RCE keeps this below CRITICAL. Despite the high blast radius, the attack is browser-mediated — the attacker does not gain OS-level code execution on the Kiteworks server. They get application-level admin access, which is devastating for data exfiltration but does not provide the lateral-movement, persistence, or ransomware-deployment capabilities that true RCE enables. The chain has a probabilistic gate (admin must visit) that RCE chains do not.
Why not higher?
A CRITICAL rating would require either unauthenticated remote code execution, a deterministic trigger that doesn't depend on user interaction, or confirmed active exploitation. This CVE has none of those: it requires an admin to view a booby-trapped page, provides application-level access rather than OS-level RCE, has no public PoC, and has no confirmed exploitation. The high-value role floor elevates it to the top of HIGH, but the user-interaction bottleneck and browser-mediated execution model prevent CRITICAL.
Why not lower?
Dropping below HIGH would require either that Kiteworks is not deployed in high-value roles (it is — it's a regulated-data MFT platform by definition) or that the exploitation chain is unreliable in practice (it isn't — no CSP means the XSS fires reliably, and admin page visits are routine on MFT platforms). The Clop/FIN11 pattern of targeting MFT vendors, the federal intelligence warning about imminent Kiteworks targeting, and the ~400-1000 internet-facing instances all prevent a MEDIUM rating.
Crowdsourced verification payload.
Run this script on any host with curl and network access to your Kiteworks instance. Invoke as: bash check_cve_2026_102147.sh https://your-kiteworks-host.example.com. No authentication or elevated privileges required — it queries the Kiteworks version endpoint.
#!/usr/bin/env bash
# check_cve_2026_102147.sh — Kiteworks Core CVE-2026-102147 version check
# Usage: bash check_cve_2026_102147.sh <KITEWORKS_BASE_URL>
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -euo pipefail
if [[ $# -lt 1 ]]; then
echo "Usage: $0 <KITEWORKS_BASE_URL>"
echo "Example: $0 https://files.example.com"
exit 2
fi
BASE_URL="${1%/}"
TIMEOUT=10
# Attempt to retrieve version from common Kiteworks endpoints
VERSION=""
for ENDPOINT in "/rest/public/server/info" "/api/v1/server/info" "/__version__" "/rest/server/version"; do
RESP=$(curl -sk --max-time "$TIMEOUT" "${BASE_URL}${ENDPOINT}" 2>/dev/null || true)
if [[ -n "$RESP" ]]; then
# Try to extract version string (e.g., 9.5.1, 9.4.2)
VER=$(echo "$RESP" | grep -oP '"version"\s*:\s*"\K[0-9]+\.[0-9]+\.[0-9]+' 2>/dev/null || true)
if [[ -n "$VER" ]]; then
VERSION="$VER"
break
fi
# Fallback: look for version in HTML or plain text
VER=$(echo "$RESP" | grep -oP '[0-9]+\.[0-9]+\.[0-9]+' | head -1 2>/dev/null || true)
if [[ -n "$VER" ]]; then
VERSION="$VER"
break
fi
fi
done
# Also check HTTP headers for version hints
if [[ -z "$VERSION" ]]; then
HEADERS=$(curl -skI --max-time "$TIMEOUT" "${BASE_URL}/" 2>/dev/null || true)
VER=$(echo "$HEADERS" | grep -iP '(x-kiteworks-version|x-app-version|server)' | grep -oP '[0-9]+\.[0-9]+\.[0-9]+' | head -1 2>/dev/null || true)
if [[ -n "$VER" ]]; then
VERSION="$VER"
fi
fi
if [[ -z "$VERSION" ]]; then
echo "UNKNOWN — Could not determine Kiteworks Core version at ${BASE_URL}"
echo "Verify manually: Admin > System Settings > About, or check /opt/kiteworks/VERSION on the appliance."
exit 2
fi
echo "Detected Kiteworks Core version: $VERSION"
# Compare version — vulnerable if < 9.5.1
IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION"
FIX_MAJOR=9
FIX_MINOR=5
FIX_PATCH=1
if (( MAJOR > FIX_MAJOR )) || \
(( MAJOR == FIX_MAJOR && MINOR > FIX_MINOR )) || \
(( MAJOR == FIX_MAJOR && MINOR == FIX_MINOR && PATCH >= FIX_PATCH )); then
echo "PATCHED — Version $VERSION >= 9.5.1. CVE-2026-102147 is remediated."
exit 0
else
echo "VULNERABLE — Version $VERSION < 9.5.1. CVE-2026-102147 applies."
echo "Action: Upgrade to Kiteworks Core 9.5.1 or later."
exit 1
fi