Moderate severityNVD Advisory· Published Feb 5, 2024· Updated Jun 3, 2025
CVE-2023-34042
CVE-2023-34042
Description
The spring-security.xsd file inside the spring-security-config jar is world writable which means that if it were extracted it could be written by anyone with access to the file system.
While there are no known exploits, this is an example of “CWE-732: Incorrect Permission Assignment for Critical Resource” and could result in an exploit. Users should update to the latest version of Spring Security to mitigate any future exploits found around this issue.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.springframework.security:spring-security-configMaven | >= 6.1.1, < 6.1.4 | 6.1.4 |
org.springframework.security:spring-security-configMaven | >= 6.0.4, < 6.0.7 | 6.0.7 |
org.springframework.security:spring-security-configMaven | >= 5.8.4, < 5.8.7 | 5.8.7 |
org.springframework.security:spring-security-configMaven | >= 5.7.9, < 5.7.11 | 5.7.11 |
Affected products
1- Range: Spring Security 6.1.x prior to 6.1.4, Spring Security 6.0.x prior to 6.0.7, Spring Security 5.8.x prior to 5.8.7, Spring Security 5.7.x prior to 5.7.11
Patches
15b293d21161eAutomate spring-security.xsd
5 files changed · +263 −11
buildSrc/src/main/groovy/io/spring/gradle/convention/SchemaZipPlugin.groovy+11 −10 modified@@ -4,6 +4,7 @@ import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.plugins.JavaPlugin import org.gradle.api.tasks.bundling.Zip +import org.springframework.gradle.xsd.CreateVersionlessXsdTask public class SchemaZipPlugin implements Plugin<Project> { @@ -15,7 +16,10 @@ public class SchemaZipPlugin implements Plugin<Project> { schemaZip.archiveClassifier = 'schema' schemaZip.description = "Builds -${schemaZip.archiveClassifier} archive containing all " + "XSDs for deployment at static.springframework.org/schema." - + def versionlessXsd = project.tasks.create("versionlessXsd", CreateVersionlessXsdTask) { + description = "Generates spring-security.xsd" + versionlessXsdFile = project.layout.buildDirectory.file("versionlessXsd/spring-security.xsd") + } project.rootProject.subprojects.each { module -> module.getPlugins().withType(JavaPlugin.class).all { @@ -36,17 +40,14 @@ public class SchemaZipPlugin implements Plugin<Project> { duplicatesStrategy 'exclude' from xsdFile.path } - } - File symlink = module.sourceSets.main.resources.find { - it.path.endsWith('org/springframework/security/config/spring-security.xsd') - } - if (symlink != null) { - schemaZip.into('security') { - duplicatesStrategy 'exclude' - from symlink.path - } + versionlessXsd.getInputFiles().from(xsdFile.path) } } } + + schemaZip.into("security") { + from(versionlessXsd.getOutputs()) + } + } }
buildSrc/src/main/java/org/springframework/gradle/xsd/CreateVersionlessXsdTask.java+147 −0 added@@ -0,0 +1,147 @@ +/* + * Copyright 2019-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.gradle.xsd; + +import org.gradle.api.DefaultTask; +import org.gradle.api.file.ConfigurableFileCollection; +import org.gradle.api.file.RegularFileProperty; +import org.gradle.api.tasks.*; +import org.gradle.work.DisableCachingByDefault; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Creates the spring-security.xsd automatically + * + * @author Rob Winch + */ +@DisableCachingByDefault(because = "not worth it") +public abstract class CreateVersionlessXsdTask extends DefaultTask { + + @InputFiles + public abstract ConfigurableFileCollection getInputFiles(); + + @OutputFile + abstract RegularFileProperty getVersionlessXsdFile(); + + @TaskAction + void createVersionlessXsd() throws IOException { + XsdFileMajorMinorVersion largest = null; + ConfigurableFileCollection inputFiles = getInputFiles(); + if (inputFiles.isEmpty()) { + throw new IllegalStateException("No Inputs configured"); + } + for (File file : inputFiles) { + XsdFileMajorMinorVersion current = XsdFileMajorMinorVersion.create(file); + if (current == null) { + continue; + } + if (largest == null) { + largest = current; + } + else if (current.getVersion().isGreaterThan(largest.getVersion())) { + largest = current; + } + } + if (largest == null) { + throw new IllegalStateException("Could not create versionless xsd file because no files matching spring-security-<digit>.xsd were found in " + inputFiles.getFiles()); + } + Path to = getVersionlessXsdFile().getAsFile().get().toPath(); + Path from = largest.getFile().toPath(); + Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES); + } + + static class XsdFileMajorMinorVersion { + private final File file; + + private final MajorMinorVersion version; + + private XsdFileMajorMinorVersion(File file, MajorMinorVersion version) { + this.file = file; + this.version = version; + } + + private static final Pattern FILE_MAJOR_MINOR_VERSION_PATTERN = Pattern.compile("^spring-security-(\\d+)\\.(\\d+)\\.xsd$"); + + /** + * If matches xsd with major minor version (e.g. spring-security-5.1.xsd returns it, otherwise null + * @param file + * @return + */ + static XsdFileMajorMinorVersion create(File file) { + String fileName = file.getName(); + Matcher matcher = FILE_MAJOR_MINOR_VERSION_PATTERN.matcher(fileName); + if (!matcher.find()) { + return null; + } + int major = Integer.parseInt(matcher.group(1)); + int minor = Integer.parseInt(matcher.group(2)); + MajorMinorVersion version = new MajorMinorVersion(major, minor); + return new XsdFileMajorMinorVersion(file, version); + } + + public File getFile() { + return file; + } + + public MajorMinorVersion getVersion() { + return version; + } + } + + static class MajorMinorVersion { + private final int major; + + private final int minor; + + MajorMinorVersion(int major, int minor) { + this.major = major; + this.minor = minor; + } + + public int getMajor() { + return major; + } + + public int getMinor() { + return minor; + } + + public boolean isGreaterThan(MajorMinorVersion version) { + if (getMajor() > version.getMajor()) { + return true; + } + if (getMajor() < version.getMajor()) { + return false; + } + if (getMinor() > version.getMinor()) { + return true; + } + if (getMinor() < version.getMinor()) { + return false; + } + // they are equal + return false; + } + } +}
buildSrc/src/test/java/org/springframework/gradle/xsd/CreateVersionlessXsdTaskTests.java+94 −0 added@@ -0,0 +1,94 @@ +/* + * Copyright 2019-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.gradle.xsd; + +import org.junit.jupiter.api.Test; +import org.springframework.gradle.xsd.CreateVersionlessXsdTask.MajorMinorVersion; +import org.springframework.gradle.xsd.CreateVersionlessXsdTask.XsdFileMajorMinorVersion; + +import java.io.File; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +/** + * @author Rob Winch + */ +class CreateVersionlessXsdTaskTests { + + @Test + void xsdCreateWhenValid() { + File file = new File("spring-security-2.0.xsd"); + XsdFileMajorMinorVersion xsdFile = XsdFileMajorMinorVersion.create(file); + assertThat(xsdFile).isNotNull(); + assertThat(xsdFile.getFile()).isEqualTo(file); + assertThat(xsdFile.getVersion().getMajor()).isEqualTo(2); + assertThat(xsdFile.getVersion().getMinor()).isEqualTo(0); + } + + @Test + void xsdCreateWhenPatchReleaseThenNull() { + File file = new File("spring-security-2.0.1.xsd"); + XsdFileMajorMinorVersion xsdFile = XsdFileMajorMinorVersion.create(file); + assertThat(xsdFile).isNull(); + } + + @Test + void xsdCreateWhenNotXsdFileThenNull() { + File file = new File("spring-security-2.0.txt"); + XsdFileMajorMinorVersion xsdFile = XsdFileMajorMinorVersion.create(file); + assertThat(xsdFile).isNull(); + } + + @Test + void xsdCreateWhenNotStartWithSpringSecurityThenNull() { + File file = new File("spring-securityNO-2.0.xsd"); + XsdFileMajorMinorVersion xsdFile = XsdFileMajorMinorVersion.create(file); + assertThat(xsdFile).isNull(); + } + + @Test + void isGreaterWhenMajorLarger() { + MajorMinorVersion larger = new MajorMinorVersion(2,0); + MajorMinorVersion smaller = new MajorMinorVersion(1,0); + assertThat(larger.isGreaterThan(smaller)).isTrue(); + assertThat(smaller.isGreaterThan(larger)).isFalse(); + } + + @Test + void isGreaterWhenMinorLarger() { + MajorMinorVersion larger = new MajorMinorVersion(1,1); + MajorMinorVersion smaller = new MajorMinorVersion(1,0); + assertThat(larger.isGreaterThan(smaller)).isTrue(); + assertThat(smaller.isGreaterThan(larger)).isFalse(); + } + + @Test + void isGreaterWhenMajorAndMinorLarger() { + MajorMinorVersion larger = new MajorMinorVersion(2,1); + MajorMinorVersion smaller = new MajorMinorVersion(1,0); + assertThat(larger.isGreaterThan(smaller)).isTrue(); + assertThat(smaller.isGreaterThan(larger)).isFalse(); + } + + @Test + void isGreaterWhenSame() { + MajorMinorVersion first = new MajorMinorVersion(1,0); + MajorMinorVersion second = new MajorMinorVersion(1,0); + assertThat(first.isGreaterThan(second)).isFalse(); + assertThat(second.isGreaterThan(first)).isFalse(); + } +}
config/spring-security-config.gradle+11 −0 modified@@ -1,4 +1,5 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.springframework.gradle.xsd.CreateVersionlessXsdTask apply plugin: 'io.spring.convention.spring-module' apply plugin: 'trang' @@ -113,6 +114,16 @@ dependencies { testRuntimeOnly 'org.hsqldb:hsqldb' } +def versionlessXsd = project.tasks.create("versionlessXsd", CreateVersionlessXsdTask) { + inputFiles.from(project.sourceSets.main.resources) + versionlessXsdFile = project.layout.buildDirectory.file("versionlessXsd/spring-security.xsd") +} + +processResources { + from(versionlessXsd) { + into 'org/springframework/security/config/' + } +} rncToXsd { rncDir = file('src/main/resources/org/springframework/security/config/')
config/src/main/resources/org/springframework/security/config/spring-security.xsd+0 −1 removed@@ -1 +0,0 @@ -spring-security-5.7.xsd \ No newline at end of file
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5News mentions
0No linked articles in our index yet.