--- a/torch/_weights_only_unpickler.py
+++ b/torch/_weights_only_unpickler.py
@@ -309,6 +309,14 @@
         self.read = file.read
         self.memo: dict[int, Any] = {}
         self.proto: int = -1
+        self._safe_storages: set = set()
+
+    def _check_set_item_target(self, opcode: str):
+        if type(self.stack[-1]) not in (dict, OrderedDict, Counter):
+            raise UnpicklingError(
+                f"Can only {opcode} for dict, collections.OrderedDict, "
+                f"collections.Counter, but got {type(self.stack[-1])}"
+            )
 
     def load(self):
         """Read a pickled object representation from the open file.
@@ -418,8 +426,29 @@
                 inst = self.stack[-1]
                 if type(inst) is torch.Tensor:
                     # Legacy unpickling
+                    # Validate that storage in state came from persistent_load (archive),
+                    # not from an attacker-constructed REDUCE(UntypedStorage, ...) call
+                    if isinstance(state, tuple) and len(state) >= 1:
+                        storage = state[0]
+                        if isinstance(storage, torch.UntypedStorage):
+                            if id(storage) not in self._safe_storages:
+                                raise UnpicklingError(
+                                    "BUILD on Tensor: storage must originate from the "
+                                    "checkpoint archive (persistent_load), not from "
+                                    "REDUCE-constructed storage"
+                                )
                     inst.set_(*state)
                 elif type(inst) is torch.nn.Parameter:
+                    # Validate that any storage in state came from persistent_load
+                    if isinstance(state, tuple) and len(state) >= 1:
+                        storage = state[0]
+                        if isinstance(storage, torch.UntypedStorage):
+                            if id(storage) not in self._safe_storages:
+                                raise UnpicklingError(
+                                    "BUILD on Parameter: storage must originate from the "
+                                    "checkpoint archive (persistent_load), not from "
+                                    "REDUCE-constructed storage"
+                                )
                     inst.__setstate__(state)
                 elif type(inst) is OrderedDict:
                     inst.__dict__.update(state)
@@ -464,9 +493,11 @@
                 list_obj.extend(items)
             elif key[0] == SETITEM[0]:
                 (v, k) = (self.stack.pop(), self.stack.pop())
+                self._check_set_item_target("SETITEM")
                 self.stack[-1][k] = v
             elif key[0] == SETITEMS[0]:
                 items = self.pop_mark()
+                self._check_set_item_target("SETITEMS")
                 for i in range(0, len(items), 2):
                     self.stack[-1][items[i]] = items[i + 1]
             elif key[0] == MARK[0]:
@@ -532,7 +563,11 @@
                     raise UnpicklingError(
                         f"Only persistent_load of storage is allowed, but got {pid[0]}"
                     )
-                self.append(self.persistent_load(pid))
+                loaded = self.persistent_load(pid)
+                # Track archive-sourced storages as safe
+                if isinstance(loaded, torch.UntypedStorage):
+                    self._safe_storages.add(id(loaded))
+                self.append(loaded)
             elif key[0] in [BINGET[0], LONG_BINGET[0]]:
                 idx = (read(1) if key[0] == BINGET[0] else unpack("<I", read(4)))[0]
                 self.append(self.memo[idx])
