{"record":{"id":"c963825d157e6ecb","repo":"alibaba/spring-ai-alibaba","slug":"fieldname-contains-unsafe-path-segment-segment","errorCode":null,"errorMessage":"{fieldName} contains unsafe path segment: {segment}","messagePattern":"(.+?) contains unsafe path segment: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"warning","filePath":"spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/store/stores/FileSystemStore.java","lineNumber":275,"sourceCode":"\t\tfor (String ns : namespace) {\n\t\t\tvalidatePathSegment(ns, \"namespace\");\n\t\t\tpath = path.resolve(ns);\n\t\t}\n\t\tvalidatePathSegment(key, \"key\");\n\t\tPath itemPath = path.resolve(key + \".json\").normalize();\n\t\tif (!itemPath.startsWith(rootPath.toAbsolutePath().normalize())) {\n\t\t\tthrow new IllegalArgumentException(\"resolved path escapes root directory\");\n\t\t}\n\t\treturn itemPath;\n\t}\n\n\tprivate void validatePathSegment(String segment, String fieldName) {\n\t\tif (segment == null || segment.trim().isEmpty()) {\n\t\t\tthrow new IllegalArgumentException(fieldName + \" cannot be null or empty\");\n\t\t}\n\t\tPath candidate = Paths.get(segment);\n\t\tif (candidate.isAbsolute() || candidate.getNameCount() != 1 || \"..\".equals(segment) || \".\".equals(segment)) {\n\t\t\tthrow new IllegalArgumentException(fieldName + \" contains unsafe path segment: \" + segment);\n\t\t}\n\t}\n\n\t/**\n\t * Ensure directory exists.\n\t * @param directory directory to create\n\t */\n\tprivate void ensureDirectoryExists(Path directory) throws IOException {\n\t\tif (!Files.exists(directory)) {\n\t\t\tFiles.createDirectories(directory);\n\t\t}\n\t}\n\n\t/**\n\t * Get all items from file system.\n\t * @return list of all items\n\t */\n\tprivate List<StoreItem> getAllItems() {","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/store/stores/FileSystemStore.java#L257-L293","documentation":"FileSystemStore.validatePathSegment throws IllegalArgumentException('<field> contains unsafe path segment: <segment>') when a namespace or key would form an absolute path, span multiple path components, or equal '.'/'..'. This prevents path traversal and escaping the store root.","triggerScenarios":"Passing '/etc' or 'C:\\\\tmp' as a key, keys containing '/' or '\\\\' (multiple name components), or the literal segments '.' or '..' to any store operation.","commonSituations":"Using user-supplied filenames directly as keys; building keys like \"dir/\" + name; Windows vs Unix path separator surprises; attackers sending '../../secret' in API fields used as store keys.","solutions":["Restrict keys/namespaces to a safe charset regex like [A-Za-z0-9._-]+ (excluding '..')","Replace path separators in incoming identifiers before storage","Hash or UUID-encode untrusted identifiers instead of using them verbatim","Catch IllegalArgumentException and reject the request as invalid input"],"exampleFix":"// before\nString key = fileName; // may contain '/'\nstore.putItem(ns, key, value);\n// after\nString key = fileName.replaceAll(\"[^A-Za-z0-9._-]\", \"_\");\nif (key.equals(\"..\") || key.equals(\".\")) key = \"_\";\nstore.putItem(ns, key, value);","handlingStrategy":"validation","validationCode":"private static final Pattern SAFE = Pattern.compile(\"[A-Za-z0-9._-]+\");\nstatic boolean safe(String s) {\n    return s != null && SAFE.matcher(s).matches() && !s.equals(\"..\") && !s.equals(\".\");\n}","typeGuard":"static boolean isPathSafe(String segment) {\n    return segment != null && !segment.contains(\"/\") && !segment.contains(\"\\\\\")\n        && !segment.equals(\"..\") && !segment.equals(\".\");\n}","tryCatchPattern":"try {\n    store.putItem(namespace, key, value);\n} catch (IllegalArgumentException e) {\n    throw new BadRequestException(\"unsafe store key: \" + e.getMessage());\n}","preventionTips":["Treat namespace/key as untrusted input; whitelist characters","Normalize separators before validation","Log rejected segments to detect traversal attempts"],"tags":["security","path-traversal","validation"],"backgroundTag":"path-traversal-blocked","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}