Skip to content

Commit f19ad24

Browse files
authoredMar 20, 2025
fix: Application import deserialization vulnerability #2604 (#2633)
1 parent 5baa141 commit f19ad24

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed
 

‎apps/application/serializers/application_serializers.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
from common.field.common import UploadedImageField, UploadedFileField
4040
from common.models.db_model_manage import DBModelManage
4141
from common.response import result
42-
from common.util.common import valid_license, password_encrypt
42+
from common.util.common import valid_license, password_encrypt, restricted_loads
4343
from common.util.field_message import ErrMessage
4444
from common.util.file_util import get_file_content
4545
from dataset.models import DataSet, Document, Image
@@ -60,6 +60,7 @@
6060

6161

6262
class MKInstance:
63+
6364
def __init__(self, application: dict, function_lib_list: List[dict], version: str):
6465
self.application = application
6566
self.function_lib_list = function_lib_list
@@ -727,7 +728,7 @@ def import_(self, with_valid=True):
727728
user_id = self.data.get('user_id')
728729
mk_instance_bytes = self.data.get('file').read()
729730
try:
730-
mk_instance = pickle.loads(mk_instance_bytes)
731+
mk_instance = restricted_loads(mk_instance_bytes)
731732
except Exception as e:
732733
raise AppApiException(1001, _("Unsupported file format"))
733734
application = mk_instance.application
@@ -813,7 +814,7 @@ def list_function_lib(self, with_valid=True):
813814
return FunctionLibSerializer.Query(
814815
data={'user_id': application.user_id, 'is_active': True,
815816
'function_type': FunctionType.PUBLIC}
816-
).list(with_valid=True)
817+
).list(with_valid=True)
817818

818819
def get_function_lib(self, function_lib_id, with_valid=True):
819820
if with_valid:

‎apps/common/util/common.py

+25
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import importlib
1111
import io
1212
import mimetypes
13+
import pickle
1314
import re
1415
import shutil
1516
from functools import reduce
@@ -23,6 +24,30 @@
2324
from ..exception.app_exception import AppApiException
2425
from ..models.db_model_manage import DBModelManage
2526

27+
safe_builtins = {
28+
'MKInstance'
29+
}
30+
31+
ALLOWED_CLASSES = {
32+
("builtins", "dict"),
33+
('uuid', 'UUID'),
34+
("application.serializers.application_serializers", "MKInstance")
35+
}
36+
37+
38+
class RestrictedUnpickler(pickle.Unpickler):
39+
40+
def find_class(self, module, name):
41+
if (module, name) in ALLOWED_CLASSES:
42+
return super().find_class(module, name)
43+
raise pickle.UnpicklingError("global '%s.%s' is forbidden" %
44+
(module, name))
45+
46+
47+
def restricted_loads(s):
48+
"""Helper function analogous to pickle.loads()."""
49+
return RestrictedUnpickler(io.BytesIO(s)).load()
50+
2651

2752
def encryption(message: str):
2853
"""

0 commit comments

Comments
 (0)