VYPR
Medium severity5.6NVD Advisory· Published Jun 13, 2025· Updated Apr 15, 2026

CVE-2025-22242

CVE-2025-22242

Description

Worker process denial of service through file read operation. .A vulnerability exists in the Master's “pub_ret” method which is exposed to all minions. The un-sanitized input value “jid” is used to construct a path which is then opened for reading. An attacker could exploit this vulnerabilities by attempting to read from a filename that will not return any data, e.g. by targeting a pipe node on the proc file system.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
saltPyPI
>= 3007.0rc1, < 3007.43007.4
saltPyPI
>= 3006.0rc1, < 3006.123006.12

Patches

1
e39116fb87bf

Fix traversal in pub_ret

https://github.com/saltstack/saltDaniel A. WozniakApr 30, 2025via ghsa
2 files changed · +33 5
  • salt/master.py+4 4 modified
    @@ -1269,7 +1269,7 @@ def __verify_minion(self, id_, token):
             """
             if not salt.utils.verify.valid_id(self.opts, id_):
                 return False
    -        pub_path = os.path.join(self.opts["pki_dir"], "minions", id_)
    +        pub_path = salt.utils.verify.clean_join(self.opts["pki_dir"], "minions", id_)
     
             try:
                 pub = salt.crypt.PublicKey(pub_path)
    @@ -1690,8 +1690,8 @@ def _return(self, load):
             if "sig" in load:
                 log.trace("Verifying signed event publish from minion")
                 sig = load.pop("sig")
    -            this_minion_pubkey = os.path.join(
    -                self.opts["pki_dir"], "minions/{}".format(load["id"])
    +            this_minion_pubkey = salt.utils.clean_join(
    +                self.opts["pki_dir"], "minions", load["id"]
                 )
                 serialized_load = salt.serializers.msgpack.serialize(load)
                 if not salt.crypt.verify_signature(
    @@ -1803,7 +1803,7 @@ def pub_ret(self, load):
             auth_cache = os.path.join(self.opts["cachedir"], "publish_auth")
             if not os.path.isdir(auth_cache):
                 os.makedirs(auth_cache)
    -        jid_fn = os.path.join(auth_cache, str(load["jid"]))
    +        jid_fn = salt.utils.verify.clean_join(auth_cache, str(load["jid"]))
             with salt.utils.files.fopen(jid_fn, "r") as fp_:
                 if not load["id"] == fp_.read():
                     return {}
    
  • tests/pytests/unit/test_master.py+29 1 modified
    @@ -4,19 +4,22 @@
     import pytest
     
     import salt.master
    +import salt.utils.files
     import salt.utils.platform
     from tests.support.mock import patch
     
     
     @pytest.fixture
     def encrypted_requests(tmp_path):
         # To honor the comment on AESFuncs
    +    (tmp_path / "pki").mkdir()
         return salt.master.AESFuncs(
             opts={
    +            "pki_dir": str(tmp_path / "pki"),
                 "cachedir": str(tmp_path / "cache"),
                 "sock_dir": str(tmp_path / "sock_drawer"),
                 "conf_file": str(tmp_path / "config.conf"),
    -            "fileserver_backend": "local",
    +            "fileserver_backend": ["local"],
                 "master_job_cache": False,
             }
         )
    @@ -193,3 +196,28 @@ def test_syndic_return_cache_dir_creation_traversal(encrypted_requests):
         )
         assert not (cachedir / "syndics").exists()
         assert not (cachedir / "mamajama").exists()
    +
    +
    +def test_pub_ret_traversal(encrypted_requests, tmp_path):
    +    """
    +    master's  AESFuncs._syndic_return method cachdir creation is not vulnerable to a directory traversal
    +    """
    +    salt.crypt.gen_keys(tmp_path, "minion", 2048)
    +
    +    minions = pathlib.Path(encrypted_requests.opts["pki_dir"]) / "minions"
    +    minions.mkdir()
    +
    +    with salt.utils.files.fopen(minions / "minion", "wb") as wfp:
    +        with salt.utils.files.fopen(tmp_path / "minion.pub", "rb") as rfp:
    +            wfp.write(rfp.read())
    +
    +    priv = salt.crypt.PrivateKey(tmp_path / "minion.pem")
    +    with pytest.raises(salt.exceptions.SaltValidationError):
    +        encrypted_requests.pub_ret(
    +            {
    +                "tok": priv.encrypt(b"salt"),
    +                "id": "minion",
    +                "jid": "asdf/../../../sdf",
    +                "return": {},
    +            }
    +        )
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.