spring-projects/spring-ai · error · IOException
Invalid filename for file '': resolves outside target direct
Error message
Invalid filename for file '': resolves outside target directory ''
What it means
Final hardening check in resolveSafeChildPath: after resolving the single-segment name against the normalized absolute target directory, it throws this IOException if the resolved path does not remain under the base directory. This backstops any future rule changes or platform path quirks that could let a file land outside the target directory (a path-traversal attack).
Source
Thrown at models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicSkillsResponseHelper.java:177
}
if (name.isAbsolute() || name.getRoot() != null) {
throw new IOException("Invalid filename for file '" + fileId + "': absolute path '" + rawName + "'");
}
if (name.getNameCount() != 1) {
throw new IOException(
"Invalid filename for file '" + fileId + "': must be a single path segment '" + rawName + "'");
}
String only = name.getName(0).toString();
if (only.equals(".") || only.equals("..")) {
throw new IOException("Invalid filename for file '" + fileId + "': '" + rawName + "'");
}
// One extra hardening check to make sure nothing fell through the cracks above
// (future tweaks to the rules, odd platform path quirks, etc.).
Path base = targetDir.toAbsolutePath().normalize();
Path resolved = base.resolve(only).normalize();
if (!resolved.startsWith(base)) {
throw new IOException(
"Invalid filename for file '" + fileId + "': resolves outside target directory '" + rawName + "'");
}
return resolved;
}
private static void extractFileIdsFromBashResult(BashCodeExecutionToolResultBlock resultBlock,
List<String> fileIds) {
BashCodeExecutionToolResultBlock.Content content = resultBlock.content();
if (content.isBashCodeExecutionResultBlock()) {
for (BashCodeExecutionOutputBlock outputBlock : content.asBashCodeExecutionResultBlock().content()) {
fileIds.add(outputBlock.fileId());
}
}
}
private static void extractFileIdsFromCodeExecutionResult(CodeExecutionToolResultBlock resultBlock,
List<String> fileIds) {
CodeExecutionToolResultBlockContent content = resultBlock.content();View on GitHub (pinned to 98a7beda4f)
Solutions
- Treat the filename as untrusted: reject any name containing separators, '..', or non-portable characters before calling filePath.
- Verify your target directory is not itself a symlink whose parent chain changes resolution semantics.
- Audit where the filename originates (API response field vs. user input) and whitelist alphanumerics/dots/dashes/hyphens.
- Catch the IOException, log the rejected name, and abort processing that file.
Example fix
// before
Path p = helper.filePath(fileId, apiReturnedName);
// after
if (!apiReturnedName.matches("[A-Za-z0-9._-]+")) {
throw new IllegalArgumentException("Unsafe filename: " + apiReturnedName);
}
Path p = helper.filePath(fileId, apiReturnedName); Defensive patterns
Strategy: validation
Validate before calling
static boolean staysUnderBase(Path base, String name) {
return base.toAbsolutePath().normalize()
.resolve(name).normalize().startsWith(base.toAbsolutePath().normalize());
} Type guard
static String strictSafeName(String name) {
if (name == null || name.contains("/") || name.contains("\\")
|| !name.matches("[A-Za-z0-9._-]+")) {
throw new IllegalArgumentException("Unsafe filename: " + name);
}
return name;
} Try / catch
try {
Path p = helper.filePath(fileId, name);
} catch (IOException e) {
securityLog.warn("Path traversal attempt rejected: {}", name);
throw e;
} Prevention
- Reject any filename containing path separators or '..' at your API boundary.
- Keep the defense-in-depth check enabled; never bypass it in production.
- Audit sources of filenames (API responses, user uploads) and whitelist formats.
When it happens
Trigger: A filename that, after normalize(), escapes the base dir — e.g. via platform-specific quirks or a name that survived earlier checks such as a case where resolve introduces '..' behavior (symbolic-link-adjacent or driver/root-relative oddities).
Common situations: Hostile filenames returned by a compromised or mocked API endpoint; unusual filesystems (Windows drive-relative paths); regression after changing validation rules.
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 for file '': absolute path ''
- Resource URI resolves outside the cache directory:
- SHA-256 not available
- Invalid filename for file '': must be a single path segment
- Invalid filename for file '': ''
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/2b9143cb7edf1a1b.
Report an issue: GitHub.