No CORS configuration — will block frontend or risk misconfiguration #10
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
SecurityConfighas no.cors()configuration. Spring Security defaults to no CORS headers, which will block any SvelteKit frontend on a different origin. When CORS is eventually added, there's a risk of overly permissive configuration (e.g.,allowedOrigins("*")with credentials).Affected files
SecurityConfig.java— no.cors()blockRecommended fix
Add explicit CORS configuration that:
*)maxAgefor preflight cachingSeverity
Medium — currently blocks legitimate frontend access; risk of insecure configuration when added.
👨💻 Kai — Frontend Engineer
CORS is directly my problem — without it, my SvelteKit frontend can't talk to the backend at all. This is a blocker for any local dev work once I have the frontend running on a different port.
What I need from the CORS config
http://localhost:5173(Vite dev server default) must be in the allowed origins during development.credentials: truemust be set on the CORS config — we use session cookies, andfetchrequests withcredentials: 'include'won't work without it. This is non-negotiable for session auth.PATCHmust be in the allowed methods if we use it anywhere (SvelteKit form actions can usePOSTwith method override, but direct API calls may usePATCH).My fetch setup
+page.server.tsgo through the SvelteKit backend (Node.js) which is same-origin with my server — so CORS headers are needed only for browser-initiated requests. Server-to-server calls in load functions won't be blocked by CORS.Questions
localhost:5173, prod allows only the production domain)? That's the right approach — can the backend read allowed origins fromapplication.ymlprofiles?🛠️ Backend Engineer
CORS configuration is one of those things that's trivial to get wrong and painful to debug. Let's get it right the first time.
Recommended implementation
Then in
SecurityFilterChain:Critical:
allowCredentials(true)cannot be combined withallowedOrigins("*")Spring Security (and the browser) will reject this combination. You must specify exact origins. If the list needs to be dynamic (e.g., multiple dev machines), use
setAllowedOriginPatterns()instead ofsetAllowedOrigins()— patterns support wildcards while still being compatible withallowCredentials(true).Profile-based configuration
Allowed origins should come from
application.yml:Then inject via
@Value("${cors.allowed-origins}")or a@ConfigurationPropertiesclass.Questions
@ControllerAdvicethat handlesOPTIONSpreflight requests, or will Spring Security's CORS filter handle that? Thehttp.cors()configuration handles it automatically — just want to confirm we're not double-handling it.🧪 QA Engineer
CORS is one of those areas where the tests need to verify the security properties, not just "does it work" — because a permissive misconfiguration passes functional tests but fails security tests.
Tests I'd add
Preflight request tests:
shouldRespondToPreflightWithCorrectAllowedOrigin()—OPTIONS /v1/recipeswithOrigin: http://localhost:5173→ assert 200, assertAccess-Control-Allow-Origin: http://localhost:5173.shouldNotAllowUnknownOriginInPreflight()—OPTIONS /v1/recipeswithOrigin: http://evil.example.com→ assert noAccess-Control-Allow-Originheader in response (or assert the header is absent/null).shouldIncludeAllowCredentialsTrueInPreflightResponse()— assertAccess-Control-Allow-Credentials: trueis present for allowed origins.Actual cross-origin request tests:
shouldIncludeCorsHeadersOnGetRequest()—GET /v1/recipeswithOrigin: http://localhost:5173→ assertAccess-Control-Allow-Originheader present.shouldNotIncludeCorsHeadersForUnknownOrigin()—GET /v1/recipeswithOrigin: http://evil.example.com→ assert noAccess-Control-Allow-Originheader.Misconfiguration guard test:
shouldNotAllowWildcardOriginWithCredentials()— a unit test or config test that verifies the CORS config bean does not haveallowedOrigins("*")set whenallowCredentials(true)is configured. This is a static assertion, but it's valuable as a regression guard.Question
@SpringBootTest? They need to spin up the full security filter chain to be meaningful — mockingCorsConfigurationSourcein a unit test doesn't verify thathttp.cors()is actually wired up.🔒 Sable — Security Engineer
CORS misconfiguration is a consistent entry in the OWASP Top 10. The issue correctly identifies the two failure modes — let me add the threat model and the specific controls needed.
Threat:
allowedOrigins("*")withallowCredentials(true)This is the most dangerous CORS misconfiguration. It would allow any website to make credentialed requests to our API using the victim's session cookie. Attack scenario:
evil.example.com.fetch("https://mealprep.example.com/v1/meals", { credentials: "include" }).Modern browsers and Spring Security both reject
allowCredentials(true)+allowedOrigins("*")— but the risk is that a developer might useallowedOriginPatterns("*"), which does work with credentials and is effectively the same vulnerability.Controls to enforce
allowCredentials(true)must be set (required for session cookies), but only with explicit origins.allowedMethodsshould be the minimum required — not["*"]. Enumerate the methods the API actually uses.allowedHeadersshould be explicit — not["*"]. At minimum:Content-Type,X-CSRF-Token.exposedHeadersshould be empty unless we explicitly want the browser to read a response header (e.g., a paginationX-Total-Countheader).Questions before closing
Locationon 201 Created,X-Total-Countfor pagination) — those need to be inexposedHeaders.CorsConfigurationentries, not a blanket/**rule.My minimum bar: explicit origin list from config, no wildcards,
allowCredentials(true), minimum method/header sets, integration test that verifies unknown origins are rejected.🎨 Atlas — UI/UX Designer
This is infrastructure work with no direct visual output, but CORS directly affects the development experience and some loading states in the UI.
Developer experience impact
Loading state consideration
One UX question to settle alongside this
GET /actuator/healthneed to be in the allowed CORS paths? It might be useful for a simple "is the backend up?" check from the frontend.No design blockers from my side — this is a prerequisite for development, not a UI feature. Ship it as soon as possible so Kai can start working with real data.