Repository navigation
Workspace files can make DataLab import modules and call functions through stored parameter sets #407
Description
Summary
When DataLab reads the parameter sets stored in a workspace (HDF5 file), it decodes them with guidata's json_to_dataset in its permissive mode. This concerns processing parameters, analysis-result parameters, creation parameters and History arguments.
The permissive mode imports the module named by the class_module field of the stored JSON and calls the object named by class_name without arguments, before checking anything. A crafted workspace can therefore make DataLab import any installed module, which runs its import-time code, and call any zero-argument callable of that module. Examples are os.abort, which crashes the application, and tempfile.mkdtemp, which creates a folder.
When it happens
It is enough to open a received workspace and select an object:
- Properties panel:
display_analysis_parametersdecodes analysis-result parameters (BaseResultAdapter.get_param). - Processing tab, History tools and recomputation:
extract_processing_parametersdecodes stored processing parameters (ProcessingParameters.set_param_from_json). - Creation tab:
extract_creation_parametersandconvert_legacy_creation_parameters. - History sessions read from a workspace or a
.dlhistfile:decode_kwargs.
The pattern exists since DataLab 1.0, with 5 call sites, and has 9 call sites in 1.3.0 and develop.
Harmless reproduction
import json, os, tempfile
import guidata.dataset as gds
from sigima.params import NormalizeParam
from datalab.gui.processor.base import ProcessingParameters
payload = json.loads(gds.dataset_to_json(NormalizeParam()))
payload.update(class_module="tempfile", class_name="mkdtemp")
before = set(os.listdir(tempfile.gettempdir()))
ProcessingParameters("normalize", "1-to-1").set_param_from_json(json.dumps(payload))
print(set(os.listdir(tempfile.gettempdir())) - before) # a folder was createdDataLab only shows the warning "Failed to deserialize processing parameters from JSON." after the call has happened. With "class_module": "this", the module is imported and prints its poem.
Impact
A file cannot supply code or arguments: only code already installed can be reached. Effects range from a crash or an exit (denial of service) to side effects of installed modules. The issue would only become arbitrary code execution if a malicious module were already importable.
Workspace capsules make exchanging workspaces between users routine, so a file should not be able to choose the code DataLab loads.
Not affected:
- capsule inspection, verification and replay, which decode parameters through the Sigima operation contracts;
- DataLab-Web;
- ROI payloads of the History, already restricted to
sigima.ROI classes.
Proposed fix
Decode every stored parameter set through one helper that resolves its class safely:
- the class must be a guidata
DataSetsubclass; - its module must either be already loaded by DataLab (Sigima, DataLab, guidata, installed plugins) or belong to the
sigima,sigimax,datalaborguidatapackages, which may be imported; - nothing else is imported or called, and a refused payload is reported like any other unreadable parameter set.
Field reading stays tolerant, as today: unknown fields are ignored and missing ones keep their defaults. Workspaces saved by earlier versions therefore keep their parameters.
Out of scope
- Remote control (XML-RPC): its clients can already import and run macros by design.
NativeH5Readercallable references: they are restricted to packages whose name starts withdatalab, and are returned, not called.
Activity
PierreRaybaut commentedon Oct 20, 2026
Fixed by #408 (merged into \develop\ as b6d78b3), to be released in DataLab 1.4.0. Stored parameter sets are now decoded by \datalab.utils.datasetjson.decode_dataset_json, which only builds guidata \DataSet\ subclasses from modules already loaded by DataLab or from public modules of DataLab's own packages; nothing else is imported or called.
docs(security): the stored-parameter risk of DataLab Desktop is fixed…