diff --git a/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/skill/validation/SkillPackageValidator.java b/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/skill/validation/SkillPackageValidator.java index 46e2d004..d3966ca5 100644 --- a/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/skill/validation/SkillPackageValidator.java +++ b/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/skill/validation/SkillPackageValidator.java @@ -8,6 +8,7 @@ import com.iflytek.skillhub.domain.skill.metadata.SkillMetadataParser; import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -64,7 +65,7 @@ public class SkillPackageValidator { this.maxSingleFileSize = maxSingleFileSize; this.maxTotalPackageSize = maxTotalPackageSize; this.allowedExtensions = allowedExtensions.stream() - .map(String::toLowerCase) + .map(extension -> extension.toLowerCase(Locale.ROOT)) .collect(java.util.stream.Collectors.toUnmodifiableSet()); } @@ -138,7 +139,8 @@ public class SkillPackageValidator { } private boolean hasAllowedExtension(String normalizedPath) { - return allowedExtensions.stream().anyMatch(normalizedPath::endsWith); + String lowercasePath = normalizedPath.toLowerCase(Locale.ROOT); + return allowedExtensions.stream().anyMatch(lowercasePath::endsWith); } private String formatMetadataError(LocalizedDomainException exception) { diff --git a/server/skillhub-domain/src/test/java/com/iflytek/skillhub/domain/skill/validation/SkillPackageValidatorTest.java b/server/skillhub-domain/src/test/java/com/iflytek/skillhub/domain/skill/validation/SkillPackageValidatorTest.java index 43c49c02..8314050b 100644 --- a/server/skillhub-domain/src/test/java/com/iflytek/skillhub/domain/skill/validation/SkillPackageValidatorTest.java +++ b/server/skillhub-domain/src/test/java/com/iflytek/skillhub/domain/skill/validation/SkillPackageValidatorTest.java @@ -6,6 +6,7 @@ import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.List; +import java.util.Set; import static org.junit.jupiter.api.Assertions.*; @@ -103,6 +104,23 @@ class SkillPackageValidatorTest { assertTrue(result.warnings().stream().anyMatch(e -> e.contains("Disallowed file extension") && e.contains("malware.exe"))); } + @Test + void acceptsAllowedExtensionRegardlessOfFilenameCase() { + SkillPackageValidator customValidator = new SkillPackageValidator( + new SkillMetadataParser(), 100, SkillPackagePolicy.MAX_SINGLE_FILE_SIZE, + SkillPackagePolicy.MAX_TOTAL_PACKAGE_SIZE, Set.of(".md", "Makefile")); + List entries = List.of( + skillMdEntry(), + new PackageEntry("Makefile", "build:\n".getBytes(), 7, "text/plain") + ); + + ValidationResult result = customValidator.validate(entries); + + assertTrue(result.passed()); + assertTrue(result.warnings().stream() + .noneMatch(warning -> warning.contains("Disallowed file extension: Makefile"))); + } + @Test void testFileTooLarge() { // Use a custom validator with 1KB single file limit to test the logic