- Advisory: GHSA-g2f7-8mp5-qw65 · CVE-2026-52768
- Severity: Moderate · CVSS 4.0
AV:A/AC:L/AT:P/PR:H/UI:P/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N - CWE: CWE-22 / CWE-23 (path traversal)
- Affected: glpi-agent
< 1.18— fixed in 1.18. Reported by Pig-Tail via coordinated disclosure.
GLPI::Agent::Tools::Archive::_unzip_az() is the pure-Perl ZIP extractor used as a fallback when the
unzip binary is absent (and $PREFER_BIN = 0 means it is tried first when Archive::Zip is
installed). It builds the destination path by naive concatenation:
my $to = File::Spec->catfile( $extract_dir, $member->{fileName} ); # no normalisation
$zip->extractMember($member, $to); # writes wherever toldFile::Spec->catfile() does not collapse or reject .. components, and
Archive::Zip::extractMember() writes to the exact path given. A member named ../../etc/cron.d/evil
therefore escapes $extract_dir. This is the only extractor in the tool that is vulnerable — the
unzip, tar, and 7z binaries all strip or reject ../ components by default.
Triggered from the Deploy task (Task/Deploy/Datastore/WorkDir.pm) when a deploy job delivers a ZIP with
uncompress, on a host where 7z is not available and Archive::Zip is installed. A malicious archive
(delivered through a compromised/MITM GLPI server, or a crafted archive an admin includes in a Deploy
package) then writes attacker-controlled content to any path the agent can reach — typically root —
enabling persistence (/etc/cron.d, systemd units), credential/authorized_keys overwrite, etc.
poc/poc_zip_slip.pl reproduces the primitive in isolation, replaying _unzip_az() verbatim with the
same Archive::Zip library the agent uses. Everything happens inside one throwaway temp sandbox (no
shared /tmp paths); the malicious member ../pwned_<marker> must escape sandbox/extract into
sandbox/. Benign marker file, sandbox auto-removed.
cd poc
perl poc_zip_slip.pl # exit 42 = traversal reproducedObserved:
[*] extract_dir : /tmp/XXXX/extract
[*] evil member : ../pwned_GLPI_ZIPSLIP_CVE_2026_52768
extract ../pwned_GLPI_ZIPSLIP_CVE_2026_52768 -> /tmp/XXXX/extract/../pwned_GLPI_ZIPSLIP_CVE_2026_52768
[!!] TRAVERSAL CONFIRMED: file written OUTSIDE extract_dir at
/tmp/XXXX/pwned_GLPI_ZIPSLIP_CVE_2026_52768
[+] Zip Slip reproduced (arbitrary file write via ../ member)
Requires Archive::Zip (apt install libarchive-zip-perl / cpan Archive::Zip); without it the
vulnerable code path doesn't exist and the PoC exits cleanly.
1.18 mimics the unzip binary by stripping ./.. components from each member path before extraction
(File::Spec->splitdir + grep { $_ !~ /^\.\.?$/ }), so the remaining path is always confined to the
destination directory instead of skipping the file.