apache/pulsar · error · IOException
Invalid path: ${path}
Error message
Invalid path: ${path} What it means
FileSystemPackagesStorage.getPath resolves a user-supplied path relative to the configured storage directory. After normalization it verifies the resulting absolute path still starts with the storage root; if not, the path escapes the storage directory (path traversal, e.g. via "../") and an IOException is thrown. This guards against reading/writing/deleting files outside the package storage.
Source
Thrown at pulsar-package-management/filesystem-storage/src/main/java/org/apache/pulsar/packages/management/storage/filesystem/FileSystemPackagesStorage.java:67
private final File storagePath;
FileSystemPackagesStorage(PackagesStorageConfiguration configuration) {
String storagePath = configuration.getProperty(STORAGE_PATH);
if (storagePath != null) {
this.storagePath = new File(storagePath);
} else {
this.storagePath = new File(DEFAULT_STORAGE_PATH);
}
}
private File getPath(String path) throws IOException {
// Normalize the path to remove any redundant path elements
File f = Paths.get(storagePath.toString(), path).normalize().toFile();
// Ensure the normalized path is still within the storagePath
if (!f.getAbsolutePath().startsWith(storagePath.getAbsolutePath())) {
throw new IOException("Invalid path: " + path);
}
if (!f.getParentFile().exists()) {
if (!f.getParentFile().mkdirs()) {
throw new RuntimeException("Failed to create parent dirs for " + path);
}
}
return f;
}
@Override
public void initialize() {
if (!storagePath.exists()) {
if (!storagePath.mkdirs()) {
throw new RuntimeException("Failed to create base storage directory at " + storagePath);
}
}
View on GitHub (pinned to 820761864e)
Solutions
- Remove ".." segments and use paths relative to the storage root.
- Check the storagePath configuration (packagesManagementStorageProvider config) — set it to a canonical absolute directory and ensure paths resolve under it.
- Resolve symlinks: the check compares string prefixes of absolute paths, so a symlinked storagePath can false-positive; use the real canonical path in configuration.
- Inspect the failing path value in the message for traversal sequences or encoding issues.
Example fix
// before
storage.read("../../etc/passwd"); // throws Invalid path
// after
storage.read("tenant/namespace/package/metadata"); // stays under storage root Defensive patterns
Strategy: validation
Validate before calling
static boolean isPathInsideStorage(String path, String storageRoot) throws java.io.IOException {
java.nio.file.Path resolved = java.nio.file.Paths.get(storageRoot, path).normalize().toAbsolutePath().toRealPath();
java.nio.file.Path root = java.nio.file.Paths.get(storageRoot).toAbsolutePath().toRealPath();
return resolved.startsWith(root);
} Try / catch
try {
storage.readAsync(path).get();
} catch (java.io.IOException e) {
if (e.getMessage().startsWith("Invalid path:")) {
log.warn("Rejected path outside storage root: {}", path);
throw new RestException(Response.Status.BAD_REQUEST, "invalid path");
}
throw e;
} Prevention
- Never pass client-controlled paths containing '..' or absolute components.
- Configure storagePath as a canonical absolute directory (avoid symlink ambiguity).
- Normalize/validate paths server-side before storage calls.
- Log rejected traversal attempts for security auditing.
When it happens
Trigger: read/delete/list calls with paths containing ".." segments or absolute components that resolve outside storagePath; storagePath itself configured as a relative path or symlink so the startsWith prefix check fails even for legitimate paths.
Common situations: Path traversal attempt in a request; misconfigured storagePath (relative path, trailing differences, symlinked directory) making valid paths appear outside the root; storage backends migrated between machines with different layouts.
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 filename:
- Failed to create parent dirs for ${path}
- Failed to create base storage directory at ${storagePath}
- Timeout during managed ledger offload operation
- Invalid broker configuration. Authentication must be enabled
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/c108edf585e3281e.
Report an issue: GitHub.