VYPR
Critical severityNVD Advisory· Published Jan 3, 2018· Updated Sep 17, 2024

CVE-2017-1000469

CVE-2017-1000469

Description

Cobbler version up to 2.8.2 is vulnerable to a command injection vulnerability in the "add repo" component resulting in arbitrary code execution as root user.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Cobbler up to 2.8.2 contains a command injection in the repo add component, allowing unauthenticated remote code execution as root.

Vulnerability

A command injection vulnerability exists in Cobbler versions up to 2.8.2, specifically in the 'add repo' component. The reposync action does not sanitize user-supplied input for repository mirror fields, allowing an attacker to inject arbitrary shell commands. The affected code paths are found in the wget_sync, rsync_sync, rhn_sync, and createrepo_walker functions, where parameters like dest_path, repo_mirror, and dirname are passed directly to shell commands without proper escaping [1][3].

Exploitation

An attacker needs access to the Cobbler web interface or API to create or edit a repository with a malicious mirror string. No authentication is required if the Cobbler service is exposed. The attack sequence involves: (1) creating a new repo and entering a crafted payload (e.g., backticks or semicolons) in the Mirror field, and (2) triggering a reposync action via the web UI, CLI, or scheduler. The unsanitized input is then executed as part of shell commands like wget, rsync, or createrepo [1][3].

Impact

Successful exploitation allows arbitrary command execution with root privileges, as Cobbler runs as root. An attacker can execute any system command, leading to full compromise of the server, including data exfiltration, installation of backdoors, or lateral movement within the network [2][3].

Mitigation

The fix was committed in commit 4b20397425a5d42a2d8927233654f4d7435bd4c2, which uses pipes.quote() to escape shell parameters [1]. Users should upgrade to a patched version (>= 2.8.3) or apply the commit manually. As a workaround, restrict access to the Cobbler interface and avoid exposing it to untrusted networks. The issue is not listed in CISA's Known Exploited Vulnerabilities catalog as of this writing.

AI Insight generated on May 22, 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.

PackageAffected versionsPatched versions
cobblerPyPI
< 3.0.03.0.0

Affected products

29

Patches

1
4b20397425a5

Escape shell parameters provided by user on reposync action (CVE-2017-1000469)

https://github.com/cobbler/cobblerPablo Suárez HernándezApr 26, 2018via ghsa
1 file changed · +9 7
  • cobbler/action_reposync.py+9 7 modified
    @@ -23,6 +23,7 @@
     
     import os
     import os.path
    +import pipes
     import urlgrabber
     
     HAS_YUM = True
    @@ -201,7 +202,7 @@ def createrepo_walker(self, repo, dirname, fnames):
                 flags = blended.get("createrepo_flags", "(ERROR: FLAGS)")
                 try:
                     # BOOKMARK
    -                cmd = "createrepo %s %s %s" % (" ".join(mdoptions), flags, dirname)
    +                cmd = "createrepo %s %s %s" % (" ".join(mdoptions), flags, pipes.quote(dirname))
                     utils.subprocess_call(self.logger, cmd)
                 except:
                     utils.log_exc(self.logger)
    @@ -225,7 +226,7 @@ def wget_sync(self, repo):
             dest_path = os.path.join(self.settings.webdir + "/repo_mirror", repo.name)
     
             # FIXME: wrapper for subprocess that logs to logger
    -        cmd = "wget -N -np -r -l inf -nd -P %s %s" % (dest_path, repo_mirror)
    +        cmd = "wget -N -np -r -l inf -nd -P %s %s" % (pipes.quote(dest_path), pipes.quote(repo_mirror))
             rc = utils.subprocess_call(self.logger, cmd)
     
             if rc != 0:
    @@ -257,7 +258,7 @@ def rsync_sync(self, repo):
                 repo.mirror = "%s/" % repo.mirror
     
             # FIXME: wrapper for subprocess that logs to logger
    -        cmd = "rsync -rltDv --copy-unsafe-links --delete-after %s --delete --exclude-from=/etc/cobbler/rsync.exclude %s %s" % (spacer, repo.mirror, dest_path)
    +        cmd = "rsync -rltDv --copy-unsafe-links --delete-after %s --delete --exclude-from=/etc/cobbler/rsync.exclude %s %s" % (spacer, pipes.quote(repo.mirror), pipes.quote(dest_path))
             rc = utils.subprocess_call(self.logger, cmd)
     
             if rc != 0:
    @@ -321,7 +322,7 @@ def rhn_sync(self, repo):
             if has_rpm_list:
                 self.logger.warning("warning: --rpm-list is not supported for RHN content")
             rest = repo.mirror[6:]      # everything after rhn://
    -        cmd = "%s %s --repo=%s --download_path=%s" % (cmd, self.rflags, rest, self.settings.webdir + "/repo_mirror")
    +        cmd = "%s %s --repo=%s --download_path=%s" % (cmd, self.rflags, pipes.quote(rest), pipes.quote(self.settings.webdir + "/repo_mirror"))
             if repo.name != rest:
                 args = {"name": repo.name, "rest": rest}
                 utils.die(self.logger, "ERROR: repository %(name)s needs to be renamed %(rest)s as the name of the cobbler repository must match the name of the RHN channel" % args)
    @@ -415,7 +416,7 @@ def yum_sync(self, repo):
     
             if not has_rpm_list:
                 # if we have not requested only certain RPMs, use reposync
    -            cmd = "%s %s --config=%s --repoid=%s --download_path=%s" % (cmd, self.rflags, temp_file, repo.name, self.settings.webdir + "/repo_mirror")
    +            cmd = "%s %s --config=%s --repoid=%s --download_path=%s" % (cmd, self.rflags, temp_file, pipes.quote(repo.name), pipes.quote(self.settings.webdir + "/repo_mirror"))
                 if repo.arch != "":
                     if repo.arch == "x86":
                         repo.arch = "i386"      # FIX potential arch errors
    @@ -443,7 +444,7 @@ def yum_sync(self, repo):
                     cmd = "/usr/bin/dnf download"
                 else:
                     cmd = "/usr/bin/yumdownloader"
    -            cmd = "%s %s %s --disablerepo=* --enablerepo=%s -c %s --destdir=%s %s" % (cmd, extra_flags, use_source, repo.name, temp_file, dest_path, " ".join(repo.rpm_list))
    +            cmd = "%s %s %s --disablerepo=* --enablerepo=%s -c %s --destdir=%s %s" % (cmd, extra_flags, use_source, pipes.quote(repo.name), temp_file, pipes.quote(dest_path), " ".join(repo.rpm_list))
     
             # now regardless of whether we're doing yumdownloader or reposync
             # or whether the repo was http://, ftp://, or rhn://, execute all queued
    @@ -534,7 +535,7 @@ def apt_sync(self, repo):
                 dists = ",".join(repo.apt_dists)
                 components = ",".join(repo.apt_components)
     
    -            mirror_data = "--method=%s --host=%s --root=%s --dist=%s --section=%s" % (method, host, mirror, dists, components)
    +            mirror_data = "--method=%s --host=%s --root=%s --dist=%s --section=%s" % (pipes.quote(method), pipes.quote(host), pipes.quote(mirror), pipes.quote(dists), pipes.quote(components))
     
                 rflags = "--nocleanup"
                 for x in repo.yumopts:
    @@ -543,6 +544,7 @@ def apt_sync(self, repo):
                     else:
                         rflags += " %s" % x
                 cmd = "%s %s %s %s" % (mirror_program, rflags, mirror_data, dest_path)
    +            cmd = "%s %s %s %s" % (mirror_program, rflags, mirror_data, pipes.quote(dest_path))
                 if repo.arch == "src":
                     cmd = "%s --source" % cmd
                 else:
    

Vulnerability mechanics

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

References

4

News mentions

0

No linked articles in our index yet.