arduino/Arduino · error · IOException
Invalid archive: it must contain a single root folder while
Error message
Invalid archive: it must contain a single root folder while file {linkName} is outside {pathPrefix} What it means
For archive entries that are links (hard or symbolic), the link's target path (linkName) must also lie inside the stripped root prefix. If the link points outside the root folder — a classic path-traversal / symlink-attack shape — extract() throws this IOException naming the link target and the expected prefix.
Source
Thrown at arduino-core/src/cc/arduino/utils/ArchiveExtractor.java:191
stripPath--;
}
pathPrefix = name.substring(0, slash);
}
// Strip the common path prefix when requested
if (!name.startsWith(pathPrefix)) {
throw new IOException("Invalid archive: it must contain a single root folder while file " + name + " is outside " + pathPrefix);
}
name = name.substring(pathPrefix.length());
if (name.isEmpty()) {
continue;
}
File outputFile = new File(destFolder, name);
File outputLinkedFile = null;
if (isLink) {
if (!linkName.startsWith(pathPrefix)) {
throw new IOException("Invalid archive: it must contain a single root folder while file " + linkName + " is outside " + pathPrefix);
}
linkName = linkName.substring(pathPrefix.length());
outputLinkedFile = new File(destFolder, linkName);
}
if (isSymLink) {
// Symbolic links are referenced with relative paths
outputLinkedFile = new File(linkName);
if (outputLinkedFile.isAbsolute()) {
System.err.println(I18n.format(tr("Warning: file {0} links to an absolute path {1}"), outputFile, outputLinkedFile));
System.err.println();
}
}
// Safety check
if (isDirectory) {
if (outputFile.isFile() && !overwrite) {
throw new IOException("Can't create folder " + outputFile + ", a file with the same name exists!");
}View on GitHub (pinned to a0df6e0e83)
Solutions
- Repackage the archive with only relative links that stay inside the root folder (or remove links entirely)
- Inspect with tar -tvf to find suspicious absolute or '../' link targets and fix them before distributing
- If you just need the files, extract with tar manually and resolve/remove the offending links
Example fix
// before (inside tar) ln -s /etc/passwd lib/config -> link outside root // after ln -s ../shared/config lib/config -> relative link within root folder
Defensive patterns
Strategy: validation
Validate before calling
// reject archives whose link targets are absolute or escape the root
try (TarArchiveInputStream in = new TarArchiveInputStream(new FileInputStream(archiveFile))) {
TarArchiveEntry e;
while ((e = in.getNextTarEntry()) != null) {
if (e.isLink() && (e.getLinkName().startsWith("/") || e.getLinkName().contains(".."))) throw new SecurityException("Unsafe link target: " + e.getLinkName());
}
} Try / catch
try { extractor.extract(archive, dest, 1); } catch (IOException e) { if (e.getMessage().contains("is outside")) { rejectOrSanitizeArchive(archive); } else { throw e; } } Prevention
- Use only relative links contained within the archive root
- Remove build symlinks before packaging
- Scan link entries with `tar -tvf` for absolute or '../' targets
When it happens
Trigger: A tar entry is a link whose target path (linkName) does not start with the computed root pathPrefix, e.g. a symlink pointing to '../..' or to an absolute path outside the archive's root folder.
Common situations: Archives that bundle absolute or parent-relative symlinks (common when tarring from odd locations or packaging artifacts referencing the build machine); malicious archives attempting symlink escape; developer archives containing build symlinks to toolchains.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- Invalid archive: it must contain a single root folder while
- Archive format not supported.
- Invalid archive: it must contain a single root folder
AI-assisted analysis of arduino/Arduino@a0df6e0e83 (2026-09-06).
Data as JSON: /api/errors/717845d4cc4d11f8.
Report an issue: GitHub.