{"id":"GHSA-f63g-88cj-hjf9","aliases":["CVE-2026-54550"],"title":"IzPack has Path Traversal in UnpackerBase that allows writing files outside the installation directory via malicious pack entries","description":"### Summary\n\nIzPack's `UnpackerBase.unpack()` resolves pack-file target paths without any\ncanonical-path or directory-containment check. An attacker who distributes a\ntrojanized installer JAR (the format is unsigned) can include pack entries whose\n`targetPath` contains `../` sequences. When a victim runs the installer the\nfile is written to an attacker-chosen location on disk under the victim's\nprivileges — including startup folders, PATH directories, or system locations.\n\n### Details\n\n**Vulnerable method:** `com.izforge.izpack.installer.unpacker.UnpackerBase.unpack()`\n**Source file:** `izpack-installer/src/main/java/com/izforge/izpack/installer/unpacker/UnpackerBase.java`\n**Vulnerable lines (5.2.4):** ~618–627\n\nThe relevant code path is:\n\n```java\nString targetPath = packFile.getTargetPath();             // attacker-controlled\nString path       = IoHelper.translatePath(targetPath, variables); // separator swap ONLY\nFile   target     = new File(path);                       // no canonical check\n// ... mkdirs() then file is written to `target`\n```\n\n`IoHelper.translatePath()` (source: `izpack-util/.../IoHelper.java`) performs\n**only** file-separator character conversion (`'/'` ↔ `File.separatorChar`) and\ncontains no security validation whatsoever. There is no call to\n`getCanonicalPath()`, no `startsWith(installDir)` containment check, and no\nnormalisation of `..` segments.\n\nBecause IzPack installer JARs carry **no digital signature**, an attacker can\nrepack any legitimate installer with malicious `PackFile` entries. The file\nformat is a standard ZIP with serialised resources — no integrity protection.\n\n**Confirmed unpatched in HEAD (fetched from GitHub, 2025):**\n```\ngit show HEAD:izpack-installer/src/main/java/com/izforge/izpack/installer/unpacker/UnpackerBase.java \\\n  | grep -n 'getCanonicalPath\\|startsWith.*install\\|traversal'\n# (no output — fix not present)\n```\n\n### PoC\n\n```bash\n# 1. Clone IzPack source and view the vulnerable code directly\ngit clone --depth=1 --branch izpack-5.2.4 https://github.com/izpack/izpack.git\nsed -n '615,650p' izpack/izpack-installer/src/main/java/com/izforge/izpack/installer/unpacker/UnpackerBase.java\n\n# 2. Compile and run the following Java reproducer (no IzPack classpath needed):\n```\n\n```java\n// TestPathTraversal.java\nimport java.io.*;\n\npublic class TestPathTraversal {\n    // Exact replication of IoHelper.translatePath() — separator swap, no security\n    static String translatePath(String destination) {\n        return destination.replace('/', File.separatorChar);\n    }\n\n    public static void main(String[] args) throws Exception {\n        String installDir   = \"/tmp/izpack_install\";\n        String maliciousPath = installDir + \"/../../../tmp/ESCAPED_FILE\";\n\n        // This is what UnpackerBase does:\n        String path   = translatePath(maliciousPath);\n        File   target = new File(path);           // resolves traversal\n        target.getParentFile().mkdirs();\n        try (FileWriter fw = new FileWriter(target)) {\n            fw.write(\"Written outside install dir via IzPack path traversal\\n\");\n        }\n        System.out.println(\"File written to: \" + target.getCanonicalPath());\n        System.out.println(\"Inside installDir: \" +\n            target.getCanonicalPath().startsWith(new File(installDir).getCanonicalPath()));\n    }\n}\n```\n\n```bash\njavac TestPathTraversal.java && java TestPathTraversal\n# Output: File written to: /tmp/ESCAPED_FILE\n#         Inside installDir: false\n```\n\n### Impact\n\nAny user who runs an IzPack-generated installer is affected. The attacker only\nneeds to distribute a repackaged installer — a common social-engineering vector.\nOn Windows (the primary IzPack platform) the victim typically runs the installer\nas a local administrator, so the attacker can write to `%APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup`,\n`%SystemRoot%\\System32`, or any other location reachable by the victim user.\nOn Linux/macOS the same applies for user-writable locations.\n\nNo authentication, no special privileges and no interaction beyond running the\ninstaller are required on the victim side.\n\n### Credits\nThis issue was identified by Michał Majchrowicz, Marcin Wyczechowski, and Paweł Zdunek, members of the AFINE Team.","severity":"high","score":7.4,"published":"2026-08-26T14:24:40.000Z","modified":"2026-10-27T15:15:07.956Z","withdrawn":false,"knownExploited":false,"affected":[{"ecosystem":"Maven","name":"org.codehaus.izpack:izpack-installer","ranges":[{"events":[{"introduced":"0"},{"fixed":"5.2.7"}],"type":"ECOSYSTEM"}],"versions":["5.0.0","5.0.0-beta1","5.0.0-beta10","5.0.0-beta11","5.0.0-beta2","5.0.0-beta3","5.0.0-beta5","5.0.0-beta6","5.0.0-beta7","5.0.0-beta8","5.0.0-beta9","5.0.0-rc1","5.0.0-rc2","5.0.0-rc3","5.0.0-rc4","5.0.0-rc5","5.0.1","5.0.10","5.0.2","5.0.3","5.0.4","5.0.5","5.0.6","5.0.7","5.0.8","5.0.9","5.1.0","5.1.0-RC1","5.1.0-RC2","5.1.0-RC3","5.1.0-RC4","5.1.0-RC5","5.1.0-RC6","5.1.0-RC7","5.1.1","5.1.2","5.1.3","5.2.0","5.2.1","5.2.2","5.2.3","5.2.4","5.2.5","5.2.6"],"fixed":["5.2.7"]}],"references":["https://github.com/izpack/izpack/security/advisories/GHSA-f63g-88cj-hjf9","https://nvd.nist.gov/vuln/detail/CVE-2026-54550","https://github.com/izpack/izpack/pull/1193","https://github.com/izpack/izpack/commit/4233ba38d0f1825f9cf3e0204e5261a5498e29d8","https://github.com/izpack/izpack/commit/8b7c6792c4fe85e3b1759c106aae39b904848466","https://github.com/izpack/izpack","https://github.com/izpack/izpack/releases/tag/izpack-5.2.7"],"sources":[{"name":"OSV","id":"GHSA-f63g-88cj-hjf9","modified":"2026-10-27T15:15:07.956770342Z","url":"https://osv.dev/vulnerability/GHSA-f63g-88cj-hjf9"}],"assessments":[{"source":"OSV","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:N/I:H/A:N","score":7.4}]}