Add default configurable Grails security response headers#15967
Add default configurable Grails security response headers#15967jamesfredley wants to merge 1 commit into
Conversation
Register a OncePerRequestFilter for X-Content-Type-Options, X-Frame-Options, Referrer-Policy, optional HSTS on secure requests, and optional CSP. Configurable via grails.security.headers.* with opt-out and ConditionalOnMissingBean. Assisted-by: Sisyphus:xai/grok-4.5 [gpt-coding]
There was a problem hiding this comment.
Pull request overview
This PR introduces a default, configurable servlet filter in grails-controllers that applies baseline browser-hardening response headers for Grails 8 servlet web applications, along with auto-configuration, configuration metadata, tests, and documentation updates in the user guide and upgrade notes.
Changes:
- Added
GrailsSecurityHeadersFilterplusGrailsSecurityHeadersPropertiesand a servlet-only Boot auto-configuration to register it by default (with opt-out viagrails.security.headers.*). - Added configuration metadata for IDE/property hinting and documented the defaults + customization in the Security guide and Grails 8 upgrade notes.
- Added a Spock spec verifying auto-config behavior, default headers, per-header disablement, overrides, and secure-request HSTS behavior.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| grails-doc/src/en/guide/upgrading/upgrading80x.adoc | Adds Grails 8 upgrade note about the new default security headers filter and how to disable/configure it. |
| grails-doc/src/en/guide/security.adoc | Documents default headers, rationale for HSTS/CSP being opt-in, and example application.yml configuration. |
| grails-controllers/src/test/groovy/org/grails/plugins/web/controllers/GrailsSecurityHeadersAutoConfigurationSpec.groovy | Adds test coverage for auto-configuration and header application behavior. |
| grails-controllers/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports | Registers the new auto-configuration class for Spring Boot discovery. |
| grails-controllers/src/main/resources/META-INF/additional-spring-configuration-metadata.json | Adds Spring configuration metadata entries for grails.security.headers.* properties. |
| grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/GrailsSecurityHeadersProperties.java | Introduces bindable configuration properties and defaults for each supported header. |
| grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/GrailsSecurityHeadersFilter.java | Implements the OncePerRequestFilter that applies headers conditionally based on configuration and existing response headers. |
| grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/GrailsSecurityHeadersAutoConfiguration.java | Adds servlet-only auto-config with conditional registration and a FilterRegistrationBean for ordering. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| applyHeader(response, "X-Content-Type-Options", properties.getContentTypeOptions()); | ||
| applyHeader(response, "X-Frame-Options", properties.getFrameOptions()); | ||
| applyHeader(response, "Referrer-Policy", properties.getReferrerPolicy()); | ||
| applyHeader(response, "X-XSS-Protection", properties.getXssProtection()); | ||
| if (request.isSecure()) { | ||
| applyHeader(response, "Strict-Transport-Security", properties.getHsts()); | ||
| } | ||
| applyHeader(response, "Content-Security-Policy", properties.getContentSecurityPolicy()); | ||
| filterChain.doFilter(request, response); |
|
The proposed change to move header application into a grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/GrailsSecurityHeadersFilter.java |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## 8.0.x #15967 +/- ##
==================================================
+ Coverage 49.6039% 49.6335% +0.0296%
- Complexity 16956 16974 +18
==================================================
Files 1999 2002 +3
Lines 93791 93856 +65
Branches 16421 16423 +2
==================================================
+ Hits 46524 46584 +60
- Misses 40100 40102 +2
- Partials 7167 7170 +3
🚀 New features to boost your workflow:
|
✅ All tests passed ✅🏷️ Commit: 4bc02bf Learn more about TestLens at testlens.app. |
Description
What was found
What changed
GrailsSecurityHeadersFilter(OncePerRequestFilter)GrailsSecurityHeadersAutoConfigurationwith@ConditionalOnMissingBeanX-Content-Type-Options: nosniff,X-Frame-Options: SAMEORIGIN,Referrer-Policy: strict-origin-when-cross-origin,X-XSS-Protection: 0grails.security.headers.*enable/disable and per-header valuesOut of scope / follow-up
Related MD topics
Contributor Checklist
Issue and Scope
8.0.x.Code Quality
Licensing and Attribution
ai-generated-starting-pointlabel applied.Documentation
Assisted-by: Sisyphus:xai/grok-4.5 [gpt-coding]