iBotPeaches/Apktool · error · InvalidPathException

Absolute paths are not allowed

Error message

Absolute paths are not allowed

What it means

Thrown by BrutIO.sanitizePath when the input path is absolute (e.g. '/etc/passwd' or 'C:\x'). The method only accepts paths relative to a base directory so that the resolved result stays inside it. It is a security guard used when extracting or writing zip entries to prevent writing outside the target directory.

Source

Thrown at brut.j.util/src/main/java/brut/util/BrutIO.java:108

    public static CRC32 calculateCrc(InputStream in) throws IOException {
        CRC32 crc = new CRC32();
        int bytesRead;
        byte[] buffer = new byte[8192];
        while ((bytesRead = in.read(buffer)) != -1) {
            crc.update(buffer, 0, bytesRead);
        }
        return crc;
    }

    public static String sanitizePath(File baseDir, String path) throws InvalidPathException, IOException {
        if (path == null || path.isEmpty()) {
            throw new InvalidPathException(path, "Path is null or empty");
        }

        Path origPath = Paths.get(path);
        if (origPath.isAbsolute()) {
            throw new InvalidPathException(path, "Absolute paths are not allowed");
        }

        Path basePath = Paths.get(baseDir.getCanonicalPath());
        Path resolvedPath = basePath.resolve(origPath).normalize();
        if (!resolvedPath.startsWith(basePath)) {
            throw new InvalidPathException(path, "Path traverses outside the base directory");
        }

        return basePath.relativize(resolvedPath).toString();
    }
}

View on GitHub (pinned to 79b63384d7)

Solutions

  1. Strip the leading separator or convert the input to a path relative to baseDir before calling sanitizePath (e.g. path.startsWith("/") ? path.substring(1) : path)
  2. If the absolute path is legitimate, compute the relative portion yourself: baseDir.toPath().relativize(Paths.get(path)) and pass that result
  3. Reject or skip absolute entries at the boundary where untrusted names enter (zip entry loop, config parser) instead of letting sanitizePath throw

Example fix

// before
String rel = BrutIO.sanitizePath(baseDir, entryName); // entryName = "/res/values.xml"

// after
String cleaned = entryName.startsWith("/") ? entryName.substring(1) : entryName;
String rel = BrutIO.sanitizePath(baseDir, cleaned);
Defensive patterns

Strategy: validation

Validate before calling

boolean isSafeRelative(String p) {
    if (p == null || p.isEmpty()) return false;
    Path path = Paths.get(p);
    return !path.isAbsolute() && !p.contains("..");
}
// use: if (isSafeRelative(entryName)) BrutIO.sanitizePath(baseDir, entryName); else skip();

Prevention

When it happens

Trigger: Calling BrutIO.sanitizePath(baseDir, path) with any string for which Paths.get(path).isAbsolute() is true — a leading '/' on Unix, a drive letter or leading backslash on Windows, or a UNC path.

Common situations: Processing zip/apk entries that store absolute entry names; passing user-supplied or config-file paths that were written with leading separators; code ported from Windows to Unix or vice versa; tests feeding OS-native paths into the sanitizer.

Related errors


AI-assisted analysis of iBotPeaches/Apktool@79b63384d7 (2026-08-14). Data as JSON: /api/errors/f6eaa4cb5deb41c3. Report an issue: GitHub.