CVE-2025-22240
Description
Arbitrary directory creation or file deletion. In the find_file method of the GitFS class, a path is created using os.path.join using unvalidated input from the “tgt_env” variable. This can be exploited by an attacker to delete any file on the Master's process has permissions to.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Unvalidated input in Salt's GitFS find_file method allows path traversal, enabling arbitrary file deletion or directory creation on the master.
Vulnerability
Overview
The vulnerability resides in the find_file method of the GitFS fileserver class. A path is constructed using os.path.join from the unvalidated tgt_env parameter [1]. This allows an attacker to inject path traversal sequences (e.g., ../) into the resulting file path [2][3]. The fix replaces the unsafe salt.utils.path.join with the sanitized salt.utils.verify.clean_join function, which validates that the resulting path stays within the intended root directory [3].
Exploitation
An attacker who can influence the tgt_env argument passed to find_file can cause the master to reference paths outside of the intended GitFS cache directory [1][3]. The attack does not require authentication beyond normal minion access; a malicious or compromised minion can send crafted requests to the master [2][4]. The clean_join helper validates each component of the path against the root, effectively preventing directory traversal [3].
Impact
Successful exploitation allows the attacker to arbitrarily create directories or delete any file that the Salt master process has permission to modify [1]. This can lead to denial of service, information disclosure, or further compromise of the master host [4].
Mitigation
The vulnerability is patched in Salt version 3006.12, released as part of the June 2025 security release [4]. Users are advised to upgrade to this or a later patched version. The commit that applies the fix is available in the public repository [3].
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
saltPyPI | >= 3007.0rc1, < 3007.4 | 3007.4 |
saltPyPI | >= 3006.0rc1, < 3006.12 | 3006.12 |
Affected products
1Patches
1f7c28ffbf18dFix traversal in gitfs find_file
3 files changed · +84 −8
salt/utils/gitfs.py+5 −4 modified@@ -3242,14 +3242,15 @@ def find_file(self, path, tgt_env="base", **kwargs): # pylint: disable=W0613 if os.path.isabs(path): return fnd - dest = salt.utils.path.join(self.cache_root, "refs", tgt_env, path) - hashes_glob = salt.utils.path.join( + # dest = salt.utils.path.join(self.cache_root, "refs", tgt_env, path) + dest = salt.utils.verify.clean_join(self.cache_root, "refs", tgt_env, path) + hashes_glob = salt.utils.verify.clean_join( self.hash_cachedir, tgt_env, f"{path}.hash.*" ) - blobshadest = salt.utils.path.join( + blobshadest = salt.utils.verify.clean_join( self.hash_cachedir, tgt_env, f"{path}.hash.blob_sha1" ) - lk_fn = salt.utils.path.join(self.hash_cachedir, tgt_env, f"{path}.lk") + lk_fn = salt.utils.verify.clean_join(self.hash_cachedir, tgt_env, f"{path}.lk") destdir = os.path.dirname(dest) hashdir = os.path.dirname(blobshadest) if not os.path.isdir(destdir):
salt/utils/verify.py+7 −4 modified@@ -548,10 +548,13 @@ def clean_join(root, *paths, subdir=False, realpath=True): Performa a join and then check the result against the clean_path method. If clean_path fails a SaltValidationError is raised. """ - path = os.path.join(root, *paths) - if not clean_path(root, path, subdir, realpath): - raise SaltValidationError(f"Invalid path: {path!r}") - return path + parent = root + for path in paths: + child = os.path.join(parent, path) + if not clean_path(parent, child, subdir, realpath): + raise SaltValidationError(f"Invalid path: {path!r}") + parent = child + return child def valid_id(opts, id_):
tests/pytests/unit/utils/test_gitfs.py+72 −0 modified@@ -4,6 +4,7 @@ import pytest import salt.config +import salt.exceptions import salt.fileserver.gitfs import salt.utils.gitfs from salt.exceptions import FileserverConfigError @@ -262,3 +263,74 @@ def test_checkout_pygit2(_prepare_provider): ) def test_get_cachedir_basename_pygit2(_prepare_provider): assert "_" == _prepare_provider.get_cache_basename() + + +def test_find_file(tmp_path): + opts = { + "cachedir": f"{tmp_path / 'cache'}", + "gitfs_user": "", + "gitfs_password": "", + "gitfs_pubkey": "", + "gitfs_privkey": "", + "gitfs_passphrase": "", + "gitfs_insecure_auth": False, + "gitfs_refspecs": salt.config._DFLT_REFSPECS, + "gitfs_ssl_verify": True, + "gitfs_branch": "master", + "gitfs_base": "master", + "gitfs_root": "", + "gitfs_env": "", + "gitfs_fallback": "", + } + remotes = [] + + gitfs = salt.utils.gitfs.GitFS(opts, remotes) + assert gitfs.find_file("asdf") == {"path": "", "rel": ""} + + +def test_find_file_bad_path(tmp_path): + opts = { + "cachedir": f"{tmp_path / 'cache'}", + "gitfs_user": "", + "gitfs_password": "", + "gitfs_pubkey": "", + "gitfs_privkey": "", + "gitfs_passphrase": "", + "gitfs_insecure_auth": False, + "gitfs_refspecs": salt.config._DFLT_REFSPECS, + "gitfs_ssl_verify": True, + "gitfs_branch": "master", + "gitfs_base": "master", + "gitfs_root": "", + "gitfs_env": "", + "gitfs_fallback": "", + } + remotes = [] + + gitfs = salt.utils.gitfs.GitFS(opts, remotes) + with pytest.raises(salt.exceptions.SaltValidationError): + gitfs.find_file("sdf/../../../asdf") + + +def test_find_file_bad_env(tmp_path): + opts = { + "cachedir": f"{tmp_path / 'cache'}", + "gitfs_user": "", + "gitfs_password": "", + "gitfs_pubkey": "", + "gitfs_privkey": "", + "gitfs_passphrase": "", + "gitfs_insecure_auth": False, + "gitfs_refspecs": salt.config._DFLT_REFSPECS, + "gitfs_ssl_verify": True, + "gitfs_branch": "master", + "gitfs_base": "master", + "gitfs_root": "", + "gitfs_env": "", + "gitfs_fallback": "", + } + remotes = [] + + gitfs = salt.utils.gitfs.GitFS(opts, remotes) + with pytest.raises(salt.exceptions.SaltValidationError): + gitfs.find_file("asdf", tgt_env="asd/../../../sdf")
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-xh32-3m67-qjgfghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-22240ghsaADVISORY
- docs.saltproject.io/en/3006/topics/releases/3006.12.htmlnvdWEB
- docs.saltproject.io/en/3007/topics/releases/3007.4.htmlnvdWEB
- github.com/saltstack/salt/commit/f7c28ffbf18dbf693a15b1ba9493918de3e88cf3ghsaWEB
News mentions
0No linked articles in our index yet.