--- description: How to set a Content Security Policy in Spring Boot with Spring Security, including report-only mode and reporting to Report URI. --- # Spring Boot Spring Security handles security headers, and CSP is one of the headers it writes. It is not on by default - CSP is the one header Spring Security makes you opt into, because there is no policy that is safe to guess on your behalf. ## What Spring Security gives you - `contentSecurityPolicy()` on the headers configuration, taking the policy directives as a string. - `reportOnly()` to emit `Content-Security-Policy-Report-Only` instead of the enforcing header. - `ContentSecurityPolicyHeaderWriter` underneath, if you need to drive it directly rather than through the DSL. - The same directive string is used for whichever header is enabled, so switching between report-only and enforcing does not mean rewriting the policy. ## Setting the header Your URL comes from the [Setup](https://report-uri.com/account/setup/) page: ```java @Bean SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.headers(headers -> headers .contentSecurityPolicy(csp -> csp .policyDirectives("default-src 'self'; object-src 'none'; " + "report-uri https://abc123.report-uri.com/r/d/csp/reportOnly") ) ); return http.build(); } ``` Add `.reportOnly()` to the `contentSecurityPolicy` configuration while you are tuning, then remove it and switch the endpoint to `enforce` once the reports are clean. ## Adding a nonce Spring Security does not generate CSP nonces for you. If you need one, generate it in a filter, put it in the request attributes so your templates can read it, and build the policy string per request rather than as a constant. With Thymeleaf that means a `th:attr="nonce=${cspNonce}"` on your inline scripts. ## Things to watch for - CSP is deliberately not enabled by default. If you assumed Spring Security's defaults covered it, they do not - check for the header before assuming you are protected. - The policy is a plain string, so there is no compile-time validation. A typo in a directive name is silently ignored by the browser, which looks identical to the directive working. - If you also set the header at a reverse proxy in front of Spring Boot, the browser gets two policies and enforces both. The effective result is the intersection, which is usually more restrictive than either author intended. ## Official documentation [Spring Security - Security HTTP Response Headers](https://docs.spring.io/spring-security/reference/servlet/exploits/headers.html) ## Start Monitoring with Report URI **Already using us for CSP?** Find your report-uri value on [Setup](https://report-uri.com/account/setup/), or view your [CSP reports](https://report-uri.com/account/reports/csp/). **New to Report URI?** Create an account and grab your report-uri value from the [Setup](https://report-uri.com/account/setup/) page. [Start your free trial](https://report-uri.com/register/?plan=starter2025)