-
Notifications
You must be signed in to change notification settings - Fork 613
Expand file tree
/
Copy pathCVE-2026-1669.patch
More file actions
174 lines (165 loc) · 6.54 KB
/
CVE-2026-1669.patch
File metadata and controls
174 lines (165 loc) · 6.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
From e24a3c620061070910de069ad5eed298241bbc9d Mon Sep 17 00:00:00 2001
From: AllSpark <allspark@microsoft.com>
Date: Tue, 14 Apr 2026 10:18:35 +0000
Subject: [PATCH] Do not allow external links in HDF5 files; verify
group/dataset; remove unverified items/values; adjust failed_saveables
handling
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
Upstream-reference: AI Backport of https://github.com/keras-team/keras/commit/8a37f9dadd8e23fa4ee3f537eeb6413e75d12553.patch
---
keras/src/saving/saving_lib.py | 72 ++++++++++++++++++----------------
1 file changed, 39 insertions(+), 33 deletions(-)
diff --git a/keras/src/saving/saving_lib.py b/keras/src/saving/saving_lib.py
index 0bcce01..fe5eb10 100644
--- a/keras/src/saving/saving_lib.py
+++ b/keras/src/saving/saving_lib.py
@@ -413,7 +413,8 @@ def _load_state(
try:
saveable.load_own_variables(weights_store.get(inner_path))
except Exception as e:
- failed_saveables.add(id(saveable))
+ if failed_saveables is not None:
+ failed_saveables.add(id(saveable))
error_msgs[id(saveable)] = saveable, e
failure = True
else:
@@ -424,7 +425,8 @@ def _load_state(
try:
saveable.load_assets(assets_store.get(inner_path))
except Exception as e:
- failed_saveables.add(id(saveable))
+ if failed_saveables is not None:
+ failed_saveables.add(id(saveable))
error_msgs[id(saveable)] = saveable, e
failure = True
else:
@@ -472,7 +474,7 @@ def _load_state(
if not failure:
if visited_saveables is not None and newly_failed <= 0:
visited_saveables.add(id(saveable))
- if id(saveable) in failed_saveables:
+ if failed_saveables is not None and id(saveable) in failed_saveables:
failed_saveables.remove(id(saveable))
error_msgs.pop(id(saveable))
@@ -657,10 +659,12 @@ class H5Entry:
else:
found = False
if not path:
- self.group = self.h5_file["vars"]
+ self.group = self._verify_group(self.h5_file["vars"])
found = True
elif path in self.h5_file and "vars" in self.h5_file[path]:
- self.group = self.h5_file[path]["vars"]
+ self.group = self._verify_group(
+ self._verify_group(self.h5_file[path])["vars"]
+ )
found = True
else:
# No hit.
@@ -671,22 +675,43 @@ class H5Entry:
)
self.path = path
if path in self.h5_file and "vars" in self.h5_file[path]:
- self.group = self.h5_file[path]["vars"]
+ self.group = self._verify_group(
+ self._verify_group(self.h5_file[path])["vars"]
+ )
found = True
if not found:
self.group = {}
+ def _verify_group(self, group):
+ if not isinstance(group, h5py.Group):
+ raise ValueError(
+ f"Invalid H5 file, expected Group but received {type(group)}"
+ )
+ return group
+
+ def _verify_dataset(self, dataset):
+ if not isinstance(dataset, h5py.Dataset):
+ raise ValueError(
+ f"Invalid H5 file, expected Dataset, received {type(dataset)}"
+ )
+ # Disallow external links
+ try:
+ external = dataset.external
+ except Exception:
+ external = False
+ if external:
+ raise ValueError(
+ "Not allowed: H5 file Dataset with external links: "
+ f"{dataset.external}"
+ )
+ return dataset
+
def __len__(self):
return self.group.__len__()
def keys(self):
return self.group.keys()
- def items(self):
- return self.group.items()
-
- def values(self):
- return self.group.values()
def __setitem__(self, key, value):
if self.mode != "w":
@@ -700,56 +725,37 @@ class H5Entry:
def __getitem__(self, name):
value = self.group[name]
-
- # ------------------------------------------------------
- # CASE 2 — HDF5 DATASET → SAFE LOADING
- # ------------------------------------------------------
-
- # Skip any objects that are not proper datasets
+ # Not a dataset: try to read scalar content if possible
if not hasattr(value, "shape") or not hasattr(value, "dtype"):
- # Fallback: attempt read if possible, else return as-is
try:
return value[()]
except Exception:
return value
-
+ # Verify dataset and disallow external links
+ value = self._verify_dataset(value)
shape = value.shape
dtype = value.dtype
-
- # ------------------------------------------------------
- # Validate SHAPE (avoid malformed / malicious metadata)
- # ------------------------------------------------------
-
# No negative dimensions
if any(dim < 0 for dim in shape):
raise ValueError(
"Malformed HDF5 dataset shape encountered in .keras file; "
"negative dimension detected."
)
-
# Prevent absurdly high-rank tensors
if len(shape) > 64:
raise ValueError(
"Malformed HDF5 dataset shape encountered in .keras file; "
"tensor rank exceeds safety limit."
)
-
# Safe product computation (Python int is unbounded)
num_elems = int(np.prod(shape))
-
- # ------------------------------------------------------
# Validate TOTAL memory size
- # ------------------------------------------------------
size_bytes = num_elems * dtype.itemsize
if size_bytes > MAX_BYTES:
raise ValueError(
f"HDF5 dataset too large to load safely "
f"({size_bytes} bytes; limit is {MAX_BYTES})."
)
-
- # ------------------------------------------------------
- # SAFE — load dataset (guaranteed ≤ 4 GiB)
- # ------------------------------------------------------
arr = value[()]
if "dtype" in value.attrs and value.attrs["dtype"] == "bfloat16":
arr = np.array(arr, dtype=ml_dtypes.bfloat16)
--
2.45.4