{"record":{"id":"f8090b3b0af45bed","repo":"Tencent/matrix","slug":"extractzipentry-entry-targetentry-getname-fai","errorCode":null,"errorMessage":"extractZipEntry entry ${targetEntry.getName()} failed!","messagePattern":"extractZipEntry entry (.+?) failed!","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"matrix/matrix-android/matrix-resource-canary/matrix-resource-canary-common/src/main/java/com/tencent/matrix/resource/common/utils/StreamUtil.java","lineNumber":68,"sourceCode":"    }\n\n    public static boolean preventZipSlip(java.io.File output, String zipEntryName) {\n\n        try {\n            if (zipEntryName.contains(\"..\") && new File(output, zipEntryName).getCanonicalPath().startsWith(output.getCanonicalPath() + File.separator)) {\n                return true;\n            }\n        } catch (IOException e) {\n            e.printStackTrace();\n            return true;\n        }\n        return false;\n    }\n\n    public static void extractZipEntry(ZipFile zipFile, ZipEntry targetEntry, File output) throws IOException {\n\n        if (preventZipSlip(output, targetEntry.getName())) {\n            throw new IllegalStateException(\"extractZipEntry entry \" + targetEntry.getName() + \" failed!\");\n        }\n\n        InputStream is = null;\n        OutputStream os = null;\n        try {\n            is = new BufferedInputStream(zipFile.getInputStream(targetEntry));\n            os = new BufferedOutputStream(new FileOutputStream(output));\n            final byte[] buffer = new byte[4096];\n            int bytesRead = 0;\n            while ((bytesRead = is.read(buffer)) > 0) {\n                os.write(buffer, 0, bytesRead);\n            }\n        } finally {\n            closeQuietly(os);\n            closeQuietly(is);\n        }\n    }\n","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/Tencent/matrix/blob/3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7/matrix/matrix-android/matrix-resource-canary/matrix-resource-canary-common/src/main/java/com/tencent/matrix/resource/common/utils/StreamUtil.java#L50-L86","documentation":"StreamUtil.extractZipEntry extracts a single zip entry to an output file, but first calls preventZipSlip to verify the entry name doesn't escape the output directory (zip-slip path traversal). If the guard trips, it throws IllegalStateException('extractZipEntry entry <name> failed!'). The library deliberately refuses entries whose resolved path lies outside the target directory.","triggerScenarios":"Extracting a zip entry whose name contains '..' segments, an absolute path, or a name that resolves outside the given output File's directory — typically from a crafted or third-party hprof/zip file.","commonSituations":"Processing untrusted or externally supplied archive files; zips created on Windows with backslash separators mis-resolved as separators; renamed entries in repacked archives pointing to parent directories.","solutions":["Inspect the offending entry name and sanitize it (strip leading '/', resolve '..') before extraction.","Only extract archives from trusted sources; reject or quarantine suspicious entries.","Extract to a fresh empty directory so entry names can't collide with existing files outside the target.","If you control archive creation, ensure entry names are plain relative paths."],"exampleFix":"// before\nStreamUtil.extractZipEntry(zipFile, entry, new File(\"/data/out\")); // entry = \"../../evil.so\"\n// after\nString safeName = entry.getName().replace(\"\\\\\", \"/\").replaceAll(\"(^|/)\\\\.\\\\.(/|$)\", \"\");\nZipEntry safe = new ZipEntry(safeName);\nStreamUtil.extractZipEntry(zipFile, safe, new File(\"/data/out\"));","handlingStrategy":"validation","validationCode":"String name = entry.getName().replace('\\\\', '/');\nFile outDir = output.getCanonicalFile();\nFile target = new File(outDir, name).getCanonicalFile();\nif (!target.getPath().startsWith(outDir.getPath() + File.separator)) {\n    throw new SecurityException(\"zip-slip entry rejected: \" + name);\n}","typeGuard":"static boolean isSafeEntryName(String name) {\n    return !name.startsWith(\"/\") && !name.contains(\"..\") && !name.contains(\"\\\\\");\n}","tryCatchPattern":"try {\n    StreamUtil.extractZipEntry(zipFile, entry, output);\n} catch (IllegalStateException e) {\n    Log.w(TAG, \"Rejected unsafe zip entry\", e);\n}","preventionTips":["Only extract archives from trusted sources","Sanitize entry names to relative paths without '..' or absolute prefixes","Extract into a fresh empty directory"],"tags":["zip","path-traversal","security","file-extraction"],"backgroundTag":"path-traversal-blocked","analyzedSha":"3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7","analyzedAt":"2026-09-08T08:01:39.722Z","contentChangedAt":"2026-09-08T08:01:39.722Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}