{"id":"GHSA-f63g-88cj-hjf9","summary":"IzPack has Path Traversal in UnpackerBase that allows writing files outside the installation directory via malicious pack entries","details":"### 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.","aliases":["CVE-2026-54550"],"modified":"2026-08-26T14:41:19.228027Z","published":"2026-08-26T14:24:40Z","database_specific":{"severity":"HIGH","github_reviewed":true,"github_reviewed_at":"2026-08-26T14:24:40Z","nvd_published_at":null,"cwe_ids":["CWE-22"]},"references":[{"type":"WEB","url":"https://github.com/izpack/izpack/security/advisories/GHSA-f63g-88cj-hjf9"},{"type":"WEB","url":"https://github.com/izpack/izpack/pull/1193"},{"type":"WEB","url":"https://github.com/izpack/izpack/commit/4233ba38d0f1825f9cf3e0204e5261a5498e29d8"},{"type":"WEB","url":"https://github.com/izpack/izpack/commit/8b7c6792c4fe85e3b1759c106aae39b904848466"},{"type":"PACKAGE","url":"https://github.com/izpack/izpack"}],"affected":[{"package":{"name":"org.codehaus.izpack:izpack-installer","ecosystem":"Maven","purl":"pkg:maven/org.codehaus.izpack/izpack-installer"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"5.2.6"}]}],"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"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/08/GHSA-f63g-88cj-hjf9/GHSA-f63g-88cj-hjf9.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:N/I:H/A:N"}]}