CVE-2025-54886 – skops
Package
Manager: pip
Name: skops
Vulnerable Version: >=0 <0.13.0
Severity
Level: High
CVSS v3.1: CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CVSS v4.0: CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
EPSS: 0.0007 pctl0.21941
Details
SKOPS Card.get_model happily allows arbitrary code execution ## Summary When using `Card.get_model`, `skops` allows for arbitrary code execution. This is due to the fact that `Card.get_model` allows both `joblib` and `skops` to be used for loading models, and as is well known, `joblib` allows for arbitrary code execution when loading objects. I do not know if this is intended or not, but I found this really concerning for a library that is founded on security. Even if intended, I kindly ask you to consider the security implications of this, disclose the potential implications through an advisory, and change the behavior of the function in future library versions (see below for possible fixes). ## What is the issue? The `Card.get_model` function allows loading models using the `get_model` method. When a `.skops` model is provided, it uses the `load` function from `skops`, which is secure to our knowledge. The `Card` class also allows consistent management of the `trusted` list, allowing it to be passed during instance creation. As expected, if a `skops` model is provided without a `trusted` list, and an untrusted type is found during loading, it will raise an error. This is perfectly fine and consistent with the security principles of `skops`. The problem arises when a file format different from a `.zip` file is provided. In this case, as shown in the code snippet below, the `joblib` library is used to load the model. This happens **silently**, without any warning or indication that the model is being loaded using `joblib`. This is a significant security risk, as `joblib` does not enforce the same security measures as `skops`, allowing for arbitrary code execution ```python # from `card/_model_card.py:354-358` try: if zipfile.is_zipfile(model_path): model = load(model_path, trusted=trusted) else: model = joblib.load(model_path) ``` Hence, for example, a simple code like the following will execute arbitrary code: ```python from skops.card import Card card = Card("model.skops") clf = card.get_model() ``` In this case, despite the name, the `model.skops` file is not a `.zip` file, and thus the `joblib.load` function is called, allowing for arbitrary code execution. This is also difficult to spot for the user, since the check is transparent and performed on the file's nature, not on the file extension or name. **Note**: this happens despite the `trusted` list being passed during the `Card` instance creation or any other parameter. ## Impact An attacker can exploit this vulnerability by crafting a malicious model file that, when loaded using `Card.get_model`, executes arbitrary code on the victim's machine. The attack does not require any special privileges or additional steps from the victim; simply loading the model is sufficient to trigger the execution of the attacker's code. The attack happens silently and at loading time, making it particularly stealthy and difficult to detect. This is particularly concerning if we consider that `Card.get_model` and `skops` are often used in collaborative environments and that `skops` promotes a security-oriented policy. Thank you for your attention to this matter. I hope this report helps improve the security of the `Card.get_model` function and the overall security posture of the `skops` library.
Metadata
Created: 2025-08-07T16:42:54Z
Modified: 2025-09-05T16:09:26Z
Source: https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2025/08/GHSA-378x-6p4f-8jgm/GHSA-378x-6p4f-8jgm.json
CWE IDs: ["CWE-502"]
Alternative ID: GHSA-378x-6p4f-8jgm
Finding: F096
Auto approve: 1