diff --git a/cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/AppController.java b/cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/AppController.java index f5e6b42e..559d32a4 100644 --- a/cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/AppController.java +++ b/cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/AppController.java @@ -3,6 +3,7 @@ package com.cameleer3.server.app.controller; import com.cameleer3.server.core.runtime.App; import com.cameleer3.server.core.runtime.AppService; import com.cameleer3.server.core.runtime.AppVersion; +import com.cameleer3.server.core.runtime.RuntimeType; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; @@ -117,18 +118,38 @@ public class AppController { } } + private static final java.util.regex.Pattern CUSTOM_ARGS_PATTERN = + java.util.regex.Pattern.compile("^[-a-zA-Z0-9_.=:/\\s+\"']*$"); + + private void validateContainerConfig(Map config) { + Object customArgs = config.get("customArgs"); + if (customArgs instanceof String s && !s.isBlank() && !CUSTOM_ARGS_PATTERN.matcher(s).matches()) { + throw new IllegalArgumentException("customArgs contains invalid characters. Only JVM-style arguments are allowed."); + } + Object runtimeType = config.get("runtimeType"); + if (runtimeType instanceof String s && !s.isBlank() && RuntimeType.fromString(s) == null) { + throw new IllegalArgumentException("Invalid runtimeType: " + s + + ". Must be one of: auto, spring-boot, quarkus, plain-java, native"); + } + } + @PutMapping("/{appSlug}/container-config") @Operation(summary = "Update container config for an app") @ApiResponse(responseCode = "200", description = "Container config updated") + @ApiResponse(responseCode = "400", description = "Invalid configuration") @ApiResponse(responseCode = "404", description = "App not found") public ResponseEntity updateContainerConfig(@PathVariable String appSlug, @RequestBody Map containerConfig) { try { + validateContainerConfig(containerConfig); App app = appService.getBySlug(appSlug); appService.updateContainerConfig(app.id(), containerConfig); return ResponseEntity.ok(appService.getById(app.id())); } catch (IllegalArgumentException e) { - return ResponseEntity.notFound().build(); + if (e.getMessage().contains("not found")) { + return ResponseEntity.notFound().build(); + } + return ResponseEntity.badRequest().build(); } } diff --git a/cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/EnvironmentAdminController.java b/cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/EnvironmentAdminController.java index 9b83780c..d3546ec7 100644 --- a/cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/EnvironmentAdminController.java +++ b/cameleer3-server-app/src/main/java/com/cameleer3/server/app/controller/EnvironmentAdminController.java @@ -2,6 +2,7 @@ package com.cameleer3.server.app.controller; import com.cameleer3.server.core.runtime.Environment; import com.cameleer3.server.core.runtime.EnvironmentService; +import com.cameleer3.server.core.runtime.RuntimeType; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; @@ -90,17 +91,37 @@ public class EnvironmentAdminController { } } + private static final java.util.regex.Pattern CUSTOM_ARGS_PATTERN = + java.util.regex.Pattern.compile("^[-a-zA-Z0-9_.=:/\\s+\"']*$"); + + private void validateContainerConfig(Map config) { + Object customArgs = config.get("customArgs"); + if (customArgs instanceof String s && !s.isBlank() && !CUSTOM_ARGS_PATTERN.matcher(s).matches()) { + throw new IllegalArgumentException("customArgs contains invalid characters. Only JVM-style arguments are allowed."); + } + Object runtimeType = config.get("runtimeType"); + if (runtimeType instanceof String s && !s.isBlank() && RuntimeType.fromString(s) == null) { + throw new IllegalArgumentException("Invalid runtimeType: " + s + + ". Must be one of: auto, spring-boot, quarkus, plain-java, native"); + } + } + @PutMapping("/{id}/default-container-config") @Operation(summary = "Update default container config for an environment") @ApiResponse(responseCode = "200", description = "Default container config updated") + @ApiResponse(responseCode = "400", description = "Invalid configuration") @ApiResponse(responseCode = "404", description = "Environment not found") public ResponseEntity updateDefaultContainerConfig(@PathVariable UUID id, @RequestBody Map defaultContainerConfig) { try { + validateContainerConfig(defaultContainerConfig); environmentService.updateDefaultContainerConfig(id, defaultContainerConfig); return ResponseEntity.ok(environmentService.getById(id)); } catch (IllegalArgumentException e) { - return ResponseEntity.notFound().build(); + if (e.getMessage().contains("not found")) { + return ResponseEntity.notFound().build(); + } + return ResponseEntity.badRequest().body(Map.of("error", e.getMessage())); } }