{"record":{"id":"cbd6aefbcd02864d","repo":"huggingface/transformers","slug":"invalid-checkpoint-path-checkpoint-attempts-t","errorCode":null,"errorMessage":"Invalid checkpoint path: '{checkpoint}' attempts to escape `dump_path`: {dump_path}","messagePattern":"Invalid checkpoint path: '(.+?)' attempts to escape `dump_path`: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/transformers/convert_slow_tokenizers_checkpoints_to_fast.py","lineNumber":88,"sourceCode":"        for checkpoint in checkpoint_names:\n            logger.info(f\"Loading {tokenizer_class.__class__.__name__} {checkpoint}\")\n\n            # Load tokenizer\n            tokenizer = tokenizer_class.from_pretrained(checkpoint, force_download=force_download)\n\n            # Save fast tokenizer\n            logger.info(f\"Save fast tokenizer to {dump_path} with prefix {checkpoint} add_prefix {add_prefix}\")\n\n            # For organization names we create sub-directories\n            if \"/\" in checkpoint:\n                checkpoint_directory, checkpoint_prefix_name = checkpoint.split(\"/\")\n                dump_path_full = os.path.join(dump_path, checkpoint_directory)\n\n                # Security check\n                try:\n                    Path(dump_path_full).resolve().relative_to(Path(dump_path).resolve())\n                except ValueError:\n                    raise ValueError(\n                        f\"Invalid checkpoint path: '{checkpoint}' attempts to escape `dump_path`: {dump_path}\"\n                    )\n\n            elif add_prefix:\n                checkpoint_prefix_name = checkpoint\n                dump_path_full = dump_path\n            else:\n                checkpoint_prefix_name = None\n                dump_path_full = dump_path\n\n            logger.info(f\"=> {dump_path_full} with prefix {checkpoint_prefix_name}, add_prefix {add_prefix}\")\n\n            if checkpoint in list(tokenizer.pretrained_vocab_files_map.values())[0]:\n                file_path = list(tokenizer.pretrained_vocab_files_map.values())[0][checkpoint]\n                next_char = file_path.split(checkpoint)[-1][0]\n                if next_char == \"/\":\n                    dump_path_full = os.path.join(dump_path_full, checkpoint_prefix_name)\n                    checkpoint_prefix_name = None","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/huggingface/transformers/blob/a597f974857b3d92939971296bc0deb93d33d780/src/transformers/convert_slow_tokenizers_checkpoints_to_fast.py#L70-L106","documentation":"Security ValueError from convert_slow_checkpoint_to_fast: when a checkpoint name contains '/', the script joins it under dump_path and then verifies with Path.resolve().relative_to() that the resolved destination stays inside dump_path. A checkpoint whose organization component resolves outside dump_path (e.g. '../..', absolute paths, or symlink tricks) trips this guard.","triggerScenarios":"Passing a checkpoint name like \"../evil/model\" so dump_path_full resolves above dump_path; a symlinked organization directory inside dump_path that points elsewhere and changes the resolved path.","commonSituations":"Feeding untrusted checkpoint lists to the batch conversion tool; paths with '..' segments; symlinked caches under the dump directory.","solutions":["Use plain 'org/model' style checkpoint names with no '..' or absolute-path components.","Remove or repoint symlinks inside dump_path before running.","If orchestrating untrusted inputs, normalize and reject names containing '..' or starting with '/' upstream."],"exampleFix":"// before\npython utils/convert_slow_tokenizers_checkpoints_to_fast.py --checkpoints ../escape/model --dump_path /data/out  # ValueError\n\n// after\npython utils/convert_slow_tokenizers_checkpoints_to_fast.py --checkpoints valid_org/model --dump_path /data/out","handlingStrategy":"validation","validationCode":"from pathlib import Path\nname = checkpoint_name\nparts = name.split(\"/\") if \"/\" in name else [name]\nif name.startswith((\"/\", \"\\\\\")) or \"..\" in parts or Path(name).is_absolute():\n    raise ValueError(f\"checkpoint name {name!r} must be a relative org/model style path\")","typeGuard":"def checkpoint_name_is_safe(checkpoint: str, dump_path: str) -> bool:\n    from pathlib import Path\n    full = Path(dump_path) / checkpoint.split(\"/\")[0]\n    try:\n        full.resolve().relative_to(Path(dump_path).resolve())\n        return True\n    except ValueError:\n        return False","tryCatchPattern":null,"preventionTips":["Reject checkpoint names containing '..', leading '/', or backslashes before invoking the tool.","Run batch conversion as an unprivileged user with dump_path on a symlink-free directory."],"tags":["security","path-traversal","tooling","tokenizer"],"backgroundTag":null,"analyzedSha":"a597f974857b3d92939971296bc0deb93d33d780","analyzedAt":"2026-08-14T18:24:08.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}