From aadf4889535e74dec22f4bf7c1ea80591fd06640 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 11 Aug 2026 23:10:35 +0900 Subject: [PATCH 1/7] test(storage): reject unknown artifact-store modes --- .../viewer/config/ArtifactStorePropertiesTest.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/clearfolio/viewer/config/ArtifactStorePropertiesTest.java b/src/test/java/com/clearfolio/viewer/config/ArtifactStorePropertiesTest.java index 357ab2c3b..73853ba97 100644 --- a/src/test/java/com/clearfolio/viewer/config/ArtifactStorePropertiesTest.java +++ b/src/test/java/com/clearfolio/viewer/config/ArtifactStorePropertiesTest.java @@ -2,6 +2,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; @@ -39,13 +40,16 @@ void setModeFallsBackToFilesystemForNullAndBlankValues() { } @Test - void setModeKeepsUnknownValuesWithoutSelectingInMemory() { + void setModeRejectsUnknownStorageModes() { ArtifactStoreProperties properties = new ArtifactStoreProperties(); - properties.setMode("cloud"); + IllegalArgumentException error = assertThrows( + IllegalArgumentException.class, + () -> properties.setMode("cloud") + ); - assertEquals("cloud", properties.getMode()); - assertFalse(properties.isInMemoryMode()); + assertEquals("unsupported artifact store mode: cloud", error.getMessage()); + assertEquals(ArtifactStoreProperties.MODE_FILESYSTEM, properties.getMode()); } @Test From 4de4a7f6d82b047ffe8f97f66a799d16dd140613 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 11 Aug 2026 23:14:45 +0900 Subject: [PATCH 2/7] fix(storage): reject unsupported artifact-store modes --- .../viewer/config/ArtifactStoreProperties.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/clearfolio/viewer/config/ArtifactStoreProperties.java b/src/main/java/com/clearfolio/viewer/config/ArtifactStoreProperties.java index 3f39c5b00..f2a3eed4f 100644 --- a/src/main/java/com/clearfolio/viewer/config/ArtifactStoreProperties.java +++ b/src/main/java/com/clearfolio/viewer/config/ArtifactStoreProperties.java @@ -42,15 +42,24 @@ public String getMode() { } /** - * Sets the artifact store mode; blank or null values fall back to the - * disk-backed default, and any value other than {@link #MODE_IN_MEMORY} - * selects the disk-backed store. + * Sets the artifact store mode. Blank or null values fall back to the + * disk-backed default; unsupported non-blank modes are rejected so a + * deployment cannot silently persist artifacts to a different store than + * the operator intended. * * @param mode artifact store mode + * @throws IllegalArgumentException when a non-blank mode is unsupported */ public void setMode(String mode) { String sanitized = sanitize(mode); - this.mode = sanitized.isEmpty() ? MODE_FILESYSTEM : sanitized; + if (sanitized.isEmpty()) { + this.mode = MODE_FILESYSTEM; + return; + } + if (!MODE_FILESYSTEM.equals(sanitized) && !MODE_IN_MEMORY.equals(sanitized)) { + throw new IllegalArgumentException("unsupported artifact store mode: " + sanitized); + } + this.mode = sanitized; } /** From fc4ff052c6962cce8c321b2261505d6f9efa720e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 11 Aug 2026 23:20:57 +0900 Subject: [PATCH 3/7] test(storage): cover explicit filesystem mode --- .../viewer/config/ArtifactStorePropertiesTest.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/test/java/com/clearfolio/viewer/config/ArtifactStorePropertiesTest.java b/src/test/java/com/clearfolio/viewer/config/ArtifactStorePropertiesTest.java index 73853ba97..973043eb8 100644 --- a/src/test/java/com/clearfolio/viewer/config/ArtifactStorePropertiesTest.java +++ b/src/test/java/com/clearfolio/viewer/config/ArtifactStorePropertiesTest.java @@ -28,6 +28,17 @@ void setModeNormalizesCaseAndWhitespace() { assertTrue(properties.isInMemoryMode()); } + @Test + void setModeAcceptsExplicitFilesystemMode() { + ArtifactStoreProperties properties = new ArtifactStoreProperties(); + properties.setMode(ArtifactStoreProperties.MODE_IN_MEMORY); + + properties.setMode(" FILESYSTEM "); + + assertEquals(ArtifactStoreProperties.MODE_FILESYSTEM, properties.getMode()); + assertFalse(properties.isInMemoryMode()); + } + @Test void setModeFallsBackToFilesystemForNullAndBlankValues() { ArtifactStoreProperties properties = new ArtifactStoreProperties(); From 9d2ff58126c99daf41254f1a843d4fe72a65bfd7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 12 Aug 2026 00:39:53 +0900 Subject: [PATCH 4/7] test(storage): reject NUL-corrupted store modes --- .../viewer/config/ArtifactStorePropertiesTest.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test/java/com/clearfolio/viewer/config/ArtifactStorePropertiesTest.java b/src/test/java/com/clearfolio/viewer/config/ArtifactStorePropertiesTest.java index 973043eb8..787c0e382 100644 --- a/src/test/java/com/clearfolio/viewer/config/ArtifactStorePropertiesTest.java +++ b/src/test/java/com/clearfolio/viewer/config/ArtifactStorePropertiesTest.java @@ -63,6 +63,18 @@ void setModeRejectsUnknownStorageModes() { assertEquals(ArtifactStoreProperties.MODE_FILESYSTEM, properties.getMode()); } + @Test + void setModeRejectsNulCorruptedKnownMode() { + ArtifactStoreProperties properties = new ArtifactStoreProperties(); + + assertThrows( + IllegalArgumentException.class, + () -> properties.setMode("file\u0000system") + ); + + assertEquals(ArtifactStoreProperties.MODE_FILESYSTEM, properties.getMode()); + } + @Test void setRootDirFallsBackToDefaultForNullAndBlankValues() { ArtifactStoreProperties properties = new ArtifactStoreProperties(); From 7cd888aaafab882ebe2d33d1257c0a54a611b5a8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 12 Aug 2026 00:40:55 +0900 Subject: [PATCH 5/7] fix(storage): reject NUL-corrupted store modes --- .../clearfolio/viewer/config/ArtifactStoreProperties.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/clearfolio/viewer/config/ArtifactStoreProperties.java b/src/main/java/com/clearfolio/viewer/config/ArtifactStoreProperties.java index f2a3eed4f..c07dee5c8 100644 --- a/src/main/java/com/clearfolio/viewer/config/ArtifactStoreProperties.java +++ b/src/main/java/com/clearfolio/viewer/config/ArtifactStoreProperties.java @@ -95,6 +95,9 @@ private static String sanitize(String value) { if (value == null) { return ""; } - return value.replace("\u0000", "").strip().toLowerCase(Locale.ROOT); + if (value.indexOf('\u0000') >= 0) { + throw new IllegalArgumentException("unsupported artifact store mode: contains NUL"); + } + return value.strip().toLowerCase(Locale.ROOT); } } From 2e76ab8ab7c0f03379cbaa3081672464af2c36db Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 12 Aug 2026 04:53:42 +0900 Subject: [PATCH 6/7] test(storage): redact rejected artifact-store modes --- .../clearfolio/viewer/config/ArtifactStorePropertiesTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/clearfolio/viewer/config/ArtifactStorePropertiesTest.java b/src/test/java/com/clearfolio/viewer/config/ArtifactStorePropertiesTest.java index 787c0e382..602e50f53 100644 --- a/src/test/java/com/clearfolio/viewer/config/ArtifactStorePropertiesTest.java +++ b/src/test/java/com/clearfolio/viewer/config/ArtifactStorePropertiesTest.java @@ -56,10 +56,10 @@ void setModeRejectsUnknownStorageModes() { IllegalArgumentException error = assertThrows( IllegalArgumentException.class, - () -> properties.setMode("cloud") + () -> properties.setMode("cloud://tenant-secret") ); - assertEquals("unsupported artifact store mode: cloud", error.getMessage()); + assertEquals("unsupported artifact store mode", error.getMessage()); assertEquals(ArtifactStoreProperties.MODE_FILESYSTEM, properties.getMode()); } From 7efb30f6d8b323426db640bc6a892c210df4f46c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 12 Aug 2026 05:05:41 +0900 Subject: [PATCH 7/7] fix(storage): redact rejected artifact-store modes --- .../com/clearfolio/viewer/config/ArtifactStoreProperties.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/clearfolio/viewer/config/ArtifactStoreProperties.java b/src/main/java/com/clearfolio/viewer/config/ArtifactStoreProperties.java index c07dee5c8..b158ce6aa 100644 --- a/src/main/java/com/clearfolio/viewer/config/ArtifactStoreProperties.java +++ b/src/main/java/com/clearfolio/viewer/config/ArtifactStoreProperties.java @@ -57,7 +57,7 @@ public void setMode(String mode) { return; } if (!MODE_FILESYSTEM.equals(sanitized) && !MODE_IN_MEMORY.equals(sanitized)) { - throw new IllegalArgumentException("unsupported artifact store mode: " + sanitized); + throw new IllegalArgumentException("unsupported artifact store mode"); } this.mode = sanitized; }