Mask exception request parameters case-insensitively#15810
Mask exception request parameters case-insensitively#15810jamesfredley wants to merge 2 commits into
Conversation
Match excluded request parameter names without regard to case when Grails logs exception request parameters, and document the matching behavior in the logging guide and configuration metadata. Assisted-by: Hephaestus:openai/gpt-5.5
There was a problem hiding this comment.
Pull request overview
Updates Grails’ exception request-parameter masking so excluded parameter names are matched case-insensitively while still requiring exact-name matches (so substrings like apiToken are not masked by an excluded token).
Changes:
- Updated
GrailsExceptionResolver#getRequestLogMessageto treat excluded parameter names case-insensitively via a helper method. - Added a regression test covering case-insensitive matching and ensuring no substring-based masking occurs.
- Updated docs and Spring configuration metadata to document case-insensitive matching behavior.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| grails-web-mvc/src/test/groovy/org/grails/web/errors/GrailsExceptionResolverSpec.groovy | Adds coverage for case-insensitive excluded parameter masking and exact-name-only behavior. |
| grails-web-mvc/src/main/groovy/org/grails/web/errors/GrailsExceptionResolver.java | Implements case-insensitive excluded-parameter detection for request log messages. |
| grails-web-core/src/main/resources/META-INF/spring-configuration-metadata.json | Documents the updated matching behavior for the exclusion list. |
| grails-doc/src/en/guide/conf/config/logging/maskingRequestParametersFromStacktraceLogs.adoc | Notes case-insensitive matching in user-facing logging documentation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## 8.0.x #15810 +/- ##
==================================================
+ Coverage 49.4820% 49.4902% +0.0082%
- Complexity 16698 16703 +5
==================================================
Files 1947 1947
Lines 92474 92481 +7
Branches 16152 16154 +2
==================================================
+ Hits 45758 45769 +11
+ Misses 39610 39602 -8
- Partials 7106 7110 +4
🚀 New features to boost your workflow:
|
Ignore null entries while checking excluded request parameters so misconfigured lists do not interrupt request logging. Correct configuration metadata to document the actual mask emitted at runtime. Assisted-by: opencode:gpt-5.5
|
Addressed the Copilot feedback in follow-up commit a52f949. The null exclude-list entry case is now handled explicitly, the metadata mask text matches the runtime output, both review threads have replies and are marked resolved, and the focused resolver test plus web-core resource processing passed locally. |
✅ All tests passed ✅🏷️ Commit: a52f949 Learn more about TestLens at testlens.app. |
|
Pre-release review pass (2026-07-02, dual-reviewer: GPT-5.5 oracle + Codex CLI): APPROVE - no blocking findings. Reviewed the full diff plus local context: the new |
| return false; | ||
| } | ||
| for (String excludedParameterName : excludedParameterNames) { | ||
| if (excludedParameterName != null && parameterName.equalsIgnoreCase(excludedParameterName)) { |
There was a problem hiding this comment.
The null check is unnecessary, equalsIgnoreCase already returns null when the argument is null
jdaugherty
left a comment
There was a problem hiding this comment.
This change should be made against 7.0.x , not 8.0.x
The Problem
GrailsExceptionResolvercan include request parameter names and values in exception log messages when request-parameter logging is enabled. Grails exposesgrails.exceptionresolver.params.excludeso an app can mask sensitive parameters (passwords, tokens, etc.) out of those logs.That masking used an exact, case-sensitive
List.contains()check. So an app that excludedpasswordortokenwould still log the values of parameters namedPassword,PASSWORD, orTOKEN- the exact fields you were trying to hide - simply because of the casing the incoming request happened to use.This is a hardening issue rather than an insecure default (request-parameter logging is not the production default), but once logging is turned on, masking should not depend on request casing.
The Fix
equalsIgnoreCase, soPassword/TOKENare masked whenpassword/tokenare excluded.tokendoes not accidentally mask an unrelatedapiToken.***.Files
GrailsExceptionResolver.java- case-insensitive, null-safe exclusion helper.GrailsExceptionResolverSpec.groovy- coverage for case variants, substrings, and null-entry configs.maskingRequestParametersFromStacktraceLogs.adoc- documents the matching behavior.spring-configuration-metadata.json- documents the***mask.Review feedback
Copilot raised two points, both addressed: null exclude-list entries are skipped before comparison, and the metadata now states the real
***mask emitted byGrailsExceptionResolver#getRequestLogMessage.Testing
:grails-web-mvc:test --tests "...GrailsExceptionResolverSpec",:grails-web-mvc:check,:grails-web-core:check, and:grails-doc:assemblepass.