From a72402c8439be14eed2d132630c4d12d417e190b Mon Sep 17 00:00:00 2001 From: "B. John Braddock" <69231844+BJohnBraddock@users.noreply.github.com> Date: Sat, 2 Aug 2025 23:34:44 -0600 Subject: [PATCH] hashing: Add usedforsecurity=False on hashlib calls (#10826) --- dvc/lock.py | 2 +- dvc/repo/__init__.py | 5 +++-- dvc/utils/__init__.py | 2 +- tests/func/test_diff.py | 2 +- tests/unit/fs/test_dvcfs.py | 6 ++++-- tests/unit/test_analytics.py | 6 ++++-- 6 files changed, 14 insertions(+), 9 deletions(-) diff --git a/dvc/lock.py b/dvc/lock.py index 3f49a8f4b..df03188fb 100644 --- a/dvc/lock.py +++ b/dvc/lock.py @@ -212,7 +212,7 @@ class HardlinkLock(flufl.lock.Lock, LockBase): if self._tmp_dir is not None: # Under Windows file path length is limited so we hash it - hasher = hashlib.md5(self._claimfile.encode()) # noqa: S324 + hasher = hashlib.md5(self._claimfile.encode(), usedforsecurity=False) filename = hasher.hexdigest() self._claimfile = os.path.join(self._tmp_dir, filename + ".lock") diff --git a/dvc/repo/__init__.py b/dvc/repo/__init__.py index 363ade993..ba850bb6e 100644 --- a/dvc/repo/__init__.py +++ b/dvc/repo/__init__.py @@ -641,10 +641,11 @@ class Repo: # that just happened to be at the same path as old deleted ones. btime = self._btime or getattr(os.stat(root_dir), "st_birthtime", None) - md5 = hashlib.md5( # noqa: S324 + md5 = hashlib.md5( str( (root_dir, subdir, btime, getpass.getuser(), version_tuple[0], salt) - ).encode() + ).encode(), + usedforsecurity=False, ) repo_token = md5.hexdigest() return os.path.join(repos_dir, repo_token) diff --git a/dvc/utils/__init__.py b/dvc/utils/__init__.py index f0eb65198..d8dc31afc 100644 --- a/dvc/utils/__init__.py +++ b/dvc/utils/__init__.py @@ -18,7 +18,7 @@ TARGET_REGEX = re.compile(r"(?P.*?)(:(?P[^\\/:]*))??$") def bytes_hash(byts, typ): - hasher = getattr(hashlib, typ)() + hasher = getattr(hashlib, typ)(usedforsecurity=False) hasher.update(byts) return hasher.hexdigest() diff --git a/tests/func/test_diff.py b/tests/func/test_diff.py index 2c818c8df..32776761d 100644 --- a/tests/func/test_diff.py +++ b/tests/func/test_diff.py @@ -9,7 +9,7 @@ from dvc.utils.fs import remove def digest(text): - return hashlib.md5(bytes(text, "utf-8")).hexdigest() + return hashlib.md5(bytes(text, "utf-8"), usedforsecurity=False).hexdigest() def test_no_scm(tmp_dir, dvc): diff --git a/tests/unit/fs/test_dvcfs.py b/tests/unit/fs/test_dvcfs.py index c3ad6b598..d90abaec2 100644 --- a/tests/unit/fs/test_dvcfs.py +++ b/tests/unit/fs/test_dvcfs.py @@ -67,7 +67,9 @@ class DVCFixtures: └── 📄 {hashed([0-9])}.txt """ dir_contents = { - md5(str(i).encode("utf-8")).hexdigest() + ".txt": str(i) for i in range(10) + md5(str(i).encode("utf-8"), usedforsecurity=False).hexdigest() + + ".txt": str(i) + for i in range(10) } tmp_dir.dvc_gen({"source": dir_contents}, commit="add source") tmp_dir.scm_gen(".gitignore", "/source", commit="add .gitignore") @@ -751,7 +753,7 @@ class TestDVCFileSystemGet(DVCFixtures): source_files = [] destination_files = [] for i in range(10): - hashed_i = md5(str(i).encode("utf-8")).hexdigest() + hashed_i = md5(str(i).encode("utf-8"), usedforsecurity=False).hexdigest() source_files.append(fs_join(source, f"{hashed_i}.txt")) destination_files.append( make_path_posix(local_join(target, f"{hashed_i}.txt")) diff --git a/tests/unit/test_analytics.py b/tests/unit/test_analytics.py index b0e75d455..844230e2d 100644 --- a/tests/unit/test_analytics.py +++ b/tests/unit/test_analytics.py @@ -176,7 +176,7 @@ def test_system_info(): ) def test_git_remote_hash(mocker, git_remote): m = mocker.patch("dvc.analytics._git_remote_url", return_value=git_remote) - expected = hashlib.md5(b"iterative/dvc.git").hexdigest() + expected = hashlib.md5(b"iterative/dvc.git", usedforsecurity=False).hexdigest() assert analytics._git_remote_path_hash(None) == expected m.assert_called_once_with(None) @@ -194,6 +194,8 @@ def test_git_remote_hash(mocker, git_remote): def test_git_remote_hash_local(mocker, git_remote): m = mocker.patch("dvc.analytics._git_remote_url", return_value=git_remote) - expected = hashlib.md5(git_remote.encode("utf-8")).hexdigest() + expected = hashlib.md5( + git_remote.encode("utf-8"), usedforsecurity=False + ).hexdigest() assert analytics._git_remote_path_hash(None) == expected m.assert_called_once_with(None)