diff --git a/AGENTS.md b/AGENTS.md index 999cce231a..fc40272bfe 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -240,6 +240,8 @@ pre-commit install --hook-type commit-msg ## Remote pushes +- Default security-fix pull requests to `main`; use a release branch only when + the user explicitly requests that backport target. - When moving a focused fix from a release branch onto `main`, identify its original base and replay only the fix commits. Do not carry release-only CI changes or duplicate upstream features into the new branch. diff --git a/src/python/isaaccapture_egopost/egohand/models/backbones/dinov3.py b/src/python/isaaccapture_egopost/egohand/models/backbones/dinov3.py index 0b390644e5..afaa317eda 100644 --- a/src/python/isaaccapture_egopost/egohand/models/backbones/dinov3.py +++ b/src/python/isaaccapture_egopost/egohand/models/backbones/dinov3.py @@ -165,7 +165,9 @@ def load_pretrained(self, ckpt_path: str) -> None: (DINOv3 SSL artifact, harmless at inference). """ Log.info(f"[DinoV3Backbone] Loading pretrained weights from {ckpt_path}") - ckpt = torch.load(ckpt_path, map_location="cpu", weights_only=False) + # Checkpoints are data, not trusted code. Restricted loading rejects + # pickle globals while preserving tensors and primitive metadata. + ckpt = torch.load(ckpt_path, map_location="cpu", weights_only=True) sd = ckpt.get("state_dict", ckpt) if isinstance(ckpt, dict) else ckpt prefix = "backbone.encoder." diff --git a/src/python/isaaccapture_egopost/egohand/models/egohand.py b/src/python/isaaccapture_egopost/egohand/models/egohand.py index 253091c4eb..07a34b6328 100644 --- a/src/python/isaaccapture_egopost/egohand/models/egohand.py +++ b/src/python/isaaccapture_egopost/egohand/models/egohand.py @@ -161,8 +161,12 @@ def __init__(self, cfg: DictConfig, **kwargs): self.backbone.load_pretrained(backbone_weights) else: Log.info(f"Loading backbone weights from {backbone_weights}") + # Backbone files contain tensor state only; keep pickle globals + # disabled so loading a supplied checkpoint cannot execute code. self.backbone.load_state_dict( - torch.load(backbone_weights, map_location="cpu")["state_dict"] + torch.load(backbone_weights, map_location="cpu", weights_only=True)[ + "state_dict" + ] ) if self.freeze_backbone: self._freeze_backbone() diff --git a/src/python/isaaccapture_egopost/inference/pipeline/predictor.py b/src/python/isaaccapture_egopost/inference/pipeline/predictor.py index 062bde6d99..82dfad6a69 100644 --- a/src/python/isaaccapture_egopost/inference/pipeline/predictor.py +++ b/src/python/isaaccapture_egopost/inference/pipeline/predictor.py @@ -73,7 +73,9 @@ def load_egohand_model(checkpoint_path: str | Path, soma_hand_data_folder: str | model: EgoHand instance in eval mode on CPU. target: The ``_target_`` string from the checkpoint cfg (for logging). """ - ckpt = torch.load(str(checkpoint_path), map_location="cpu", weights_only=False) + # This path consumes tensors and primitive configuration only. Restricted + # loading prevents checkpoint pickle globals from executing during inference. + ckpt = torch.load(str(checkpoint_path), map_location="cpu", weights_only=True) cfg = OmegaConf.create(ckpt["hyper_parameters"]["cfg"]) target = str(cfg.get("_target_", "")) if not any(target.endswith(t) for t in _VALID_TARGETS):