fix(security): add baseline content security policy

This commit is contained in:
yun-zhi-ztl 2026-03-15 17:40:20 +08:00
parent 458fc6b300
commit 39b0f3c852
3 changed files with 20 additions and 1 deletions

View file

@ -8,6 +8,7 @@ import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ -27,6 +28,8 @@ class HealthControllerTest {
.andExpect(jsonPath("$.msg").isNotEmpty())
.andExpect(jsonPath("$.data.message").value("UP"))
.andExpect(jsonPath("$.timestamp").isNotEmpty())
.andExpect(jsonPath("$.requestId").isNotEmpty());
.andExpect(jsonPath("$.requestId").isNotEmpty())
.andExpect(header().string("Content-Security-Policy", org.hamcrest.Matchers.containsString("default-src 'self'")))
.andExpect(header().string("Content-Security-Policy", org.hamcrest.Matchers.containsString("object-src 'none'")));
}
}

View file

@ -33,6 +33,17 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
private static final String CONTENT_SECURITY_POLICY = String.join("; ",
"default-src 'self'",
"script-src 'self' 'unsafe-inline' 'unsafe-eval'",
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
"img-src 'self' data: blob: https:",
"font-src 'self' data: https://fonts.gstatic.com",
"connect-src 'self' ws: wss: http://localhost:* https://localhost:*",
"object-src 'none'",
"base-uri 'self'",
"frame-ancestors 'none'",
"form-action 'self'");
private final CustomOAuth2UserService customOAuth2UserService;
private final SkillHubOAuth2AuthorizationRequestResolver authorizationRequestResolver;
@ -156,6 +167,7 @@ public class SecurityConfig {
)
.headers(headers -> headers
.contentTypeOptions(contentTypeOptions -> {})
.contentSecurityPolicy(csp -> csp.policyDirectives(CONTENT_SECURITY_POLICY))
.frameOptions(frameOptions -> frameOptions.deny())
.httpStrictTransportSecurity(hsts -> hsts
.includeSubDomains(true)

View file

@ -3,6 +3,10 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: blob: https:; font-src 'self' data: https://fonts.gstatic.com; connect-src 'self' ws: wss: http://localhost:* https://localhost:*; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; form-action 'self'"
/>
<title>SkillHub</title>
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="preconnect" href="https://fonts.googleapis.com" />