diff --git a/spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java b/spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java index a2085d1ad64..59a6693e829 100644 --- a/spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java +++ b/spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java @@ -617,10 +617,12 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol private Set getClassPathManifestEntriesFromJar(File jar) throws IOException { URL base = jar.toURI().toURL(); File parent = jar.getAbsoluteFile().getParentFile(); + try (JarFile jarFile = new JarFile(jar)) { Manifest manifest = jarFile.getManifest(); Attributes attributes = (manifest != null ? manifest.getMainAttributes() : null); String classPath = (attributes != null ? attributes.getValue(Name.CLASS_PATH) : null); + Set manifestEntries = new LinkedHashSet<>(); if (StringUtils.hasLength(classPath)) { StringTokenizer tokenizer = new StringTokenizer(classPath); @@ -631,14 +633,14 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol continue; } - // Handle absolute paths correctly - don't use parent for absolute paths + // Handle absolute paths correctly: do not apply parent to absolute paths. File pathFile = new File(path); - File candidate = pathFile.isAbsolute() ? pathFile : new File(parent, path); + File candidate = (pathFile.isAbsolute() ? pathFile : new File(parent, path)); - // For relative paths, enforce security check (must be under parent) - // For absolute paths, just verify file exists (matching JVM behavior) - if (candidate.isFile() && - (pathFile.isAbsolute() || candidate.getCanonicalPath().contains(parent.getCanonicalPath()))) { + // For relative paths, enforce security check: must be under parent. + // For absolute paths, just verify file exists (matching JVM behavior). + if (candidate.isFile() && (pathFile.isAbsolute() || + candidate.getCanonicalPath().contains(parent.getCanonicalPath()))) { manifestEntries.add(ClassPathManifestEntry.of(candidate, this.useCaches)); } }