From fe83b72d675a9064239c7e08276d76c786a1ce47 Mon Sep 17 00:00:00 2001 From: matevip Date: Sat, 11 Apr 2026 18:21:17 +0800 Subject: [PATCH] fix(security): harden JWT, CORS, and H2 Console for production --- .../mate/config/SecurityStartupValidator.java | 57 +++++++++++++++++++ .../java/vip/mate/config/WebMvcConfig.java | 7 ++- .../src/main/resources/application.yml | 4 +- 3 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 mateclaw-server/src/main/java/vip/mate/config/SecurityStartupValidator.java diff --git a/mateclaw-server/src/main/java/vip/mate/config/SecurityStartupValidator.java b/mateclaw-server/src/main/java/vip/mate/config/SecurityStartupValidator.java new file mode 100644 index 00000000..ec64e509 --- /dev/null +++ b/mateclaw-server/src/main/java/vip/mate/config/SecurityStartupValidator.java @@ -0,0 +1,57 @@ +package vip.mate.config; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +/** + * Startup security validator — warns about insecure default configurations. + * + * @author MateClaw Team + */ +@Slf4j +@Component +@Order(1) +public class SecurityStartupValidator implements ApplicationRunner { + + private static final String DEFAULT_JWT_SECRET = "MateClaw-JWT-Secret-Key-2024-Please-Change-In-Production"; + + @Value("${mateclaw.jwt.secret}") + private String jwtSecret; + + @Value("${spring.h2.console.enabled:false}") + private boolean h2ConsoleEnabled; + + @Value("${mateclaw.cors.allowed-origins:*}") + private String corsOrigins; + + @Override + public void run(ApplicationArguments args) { + boolean hasWarnings = false; + + if (DEFAULT_JWT_SECRET.equals(jwtSecret)) { + log.warn("╔══════════════════════════════════════════════════════════════╗"); + log.warn("║ SECURITY WARNING: Using default JWT secret! ║"); + log.warn("║ Set JWT_SECRET environment variable for production. ║"); + log.warn("╚══════════════════════════════════════════════════════════════╝"); + hasWarnings = true; + } + + if (h2ConsoleEnabled) { + log.warn("[Security] H2 Console is enabled at /h2-console. Set H2_CONSOLE_ENABLED=false in production."); + hasWarnings = true; + } + + if ("*".equals(corsOrigins.trim())) { + log.warn("[Security] CORS allows all origins. Set MATECLAW_CORS_ALLOWED_ORIGINS in production."); + hasWarnings = true; + } + + if (!hasWarnings) { + log.info("[Security] Startup security check passed."); + } + } +} diff --git a/mateclaw-server/src/main/java/vip/mate/config/WebMvcConfig.java b/mateclaw-server/src/main/java/vip/mate/config/WebMvcConfig.java index f4f2a8fd..43dea5a6 100644 --- a/mateclaw-server/src/main/java/vip/mate/config/WebMvcConfig.java +++ b/mateclaw-server/src/main/java/vip/mate/config/WebMvcConfig.java @@ -1,6 +1,7 @@ package vip.mate.config; import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; @@ -19,6 +20,10 @@ public class WebMvcConfig implements WebMvcConfigurer { private final WorkspaceAccessInterceptor workspaceAccessInterceptor; + /** CORS allowed origins, comma-separated. Default "*" for dev, restrict in production. */ + @Value("${mateclaw.cors.allowed-origins:*}") + private String allowedOrigins; + @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(workspaceAccessInterceptor) @@ -28,7 +33,7 @@ public class WebMvcConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") - .allowedOriginPatterns("*") + .allowedOriginPatterns(allowedOrigins.split(",")) .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .allowCredentials(true) diff --git a/mateclaw-server/src/main/resources/application.yml b/mateclaw-server/src/main/resources/application.yml index 30b1e32d..2ab8cc8a 100644 --- a/mateclaw-server/src/main/resources/application.yml +++ b/mateclaw-server/src/main/resources/application.yml @@ -40,7 +40,7 @@ spring: h2: console: - enabled: true + enabled: ${H2_CONSOLE_ENABLED:false} path: /h2-console # Spring AI Alibaba (DashScope) - Spring AI Alibaba 1.1.x 配置路径 @@ -92,7 +92,7 @@ springdoc: # MateClaw 自定义配置 mateclaw: jwt: - secret: MateClaw-JWT-Secret-Key-2024-Please-Change-In-Production + secret: ${JWT_SECRET:MateClaw-JWT-Secret-Key-2024-Please-Change-In-Production} expiration: 86400000 # 搜索配置已迁移至数据库(mate_system_setting 表),通过 UI 系统设置管理 # MCP server 配置已迁移至数据库(mate_mcp_server 表),通过 UI 管理