Executive brief
SENAITE.core is a laboratory information management system (LIMS) used to manage patient samples and test results. This vulnerability allows any unauthenticated attacker on the network to execute arbitrary Python code on the LIMS server through a two-step attack: first by discovering the UID of a public configuration object, then sending a specially crafted request that exploits missing permission checks and unsafe use of Python's eval() function. An attacker with this access gains complete control over the system, including the ability to read/modify all patient data, create administrator accounts, and execute system commands.
Technical details
The vulnerability is a chain of two flaws in SENAITE.core's JSON API. First, the /@@API/update route fails to enforce the AccessJSONAPI permission check before processing requests, in contrast to the /@@API/create route which correctly validates permissions. This allows unauthenticated users (granted default Plone "View" permission) to reach the update handler. Second, within set_fields_from_request() in jsonapi/__init__.py, the code passes user-supplied field values directly to Python's eval() function for RecordsField and RecordField types (line 240), without any prior validation or permission checks. The eval() executes in the Zope worker process with full Python builtins, enabling arbitrary code execution. An attacker can discover the UID of the anonymous-readable bika_setup object via the @@uuid endpoint, then POST a crafted RejectionReasons or IDFormatting field value containing Python code (e.g., __import__('os').popen('id').read()). The ZODB transaction rolls back but side effects (subprocess spawning, file I/O, network calls) persist. Both flaws predate the SENAITE fork (introduced 2013) and are present in all 2.x versions through 2.6.0.
Affected products
- SENAITE senaite.core 2.0.0 through 2.6.0
Timeline
- 2026-07-10: advisory: GitHub Security Advisory published
- 2026-08-26: disclosed: Advisory updated with full details and PoC
- 2013-09-04: other: Original eval() sink introduced in commit d7bf2d4507
- 2013: other: Unchecked update route introduced in commit be3d8cc916