Warn once on GString-interpolated GORM HQL queries - #15968
Conversation
Add GormQuerySafetyWarnings and call it from Hibernate query paths. Recommend named parameters in docs. Does not throw; warns with query shape. Assisted-by: Sisyphus:xai/grok-4.5 [gpt-coding]
There was a problem hiding this comment.
Pull request overview
This PR adds a warn-first safety mechanism for GORM HQL queries expressed as GString (interpolated) to encourage migration toward explicit named parameters, while preserving the existing behavior of binding interpolated values as query parameters. It wires the warning into Hibernate GORM static HQL query execution paths and updates the Grails 8 docs to explain the new warning and recommended patterns.
Changes:
- Introduces
GormQuerySafetyWarningsto detectGStringHQL queries and warn once per operation/query shape. - Hooks the warning into Hibernate GORM static HQL query preparation/execution.
- Updates reference/security/upgrade docs with safer query examples and migration guidance.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| grails-doc/src/en/ref/Domain Classes/find.adoc | Adds guidance to prefer named params; documents the new GString warning behavior. |
| grails-doc/src/en/ref/Domain Classes/executeQuery.adoc | Adds guidance to prefer named params; documents the new GString warning behavior. |
| grails-doc/src/en/guide/upgrading/upgrading80x.adoc | Adds an upgrade note explaining the new warning and recommended query patterns. |
| grails-doc/src/en/guide/security/securingAgainstAttacks.adoc | Refreshes SQL/HQL injection guidance and references the new warning behavior. |
| grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/query/GormQuerySafetyWarningsSpec.groovy | Adds unit tests for “warn once” and for avoiding logging interpolated values. |
| grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/GormQuerySafetyWarnings.groovy | Implements one-time warning logic and query-shape redaction for GString queries. |
| grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy | Wires the warning helper into Hibernate static HQL query preparation. |
💡 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 #15968 +/- ##
================================================
+ Coverage 0 51.1124% +51.1124%
- Complexity 0 17614 +17614
================================================
Files 0 2042 +2042
Lines 0 95517 +95517
Branches 0 16592 +16592
================================================
+ Hits 0 48821 +48821
- Misses 0 39413 +39413
- Partials 0 7283 +7283
🚀 New features to boost your workflow:
|
borinquenkid
left a comment
There was a problem hiding this comment.
This solution only works on H7, it needs to work also H5 and neo4j. I am building a compile time solution but if you want to expand the scope to all the other datastores that is a choice.
- Check warnEnabled before building the query shape and bound the dedup cache so it cannot grow without limit - Use datastore-neutral wording so native SQL queries are not mislabeled as HQL - Add a Hibernate spec asserting the warning fires once and does not include interpolated values Assisted-by: Sisyphus:openai/gpt-5.6-terra [gpt-coding]
- Remove the misleading "analogous GString" example that was labeled SQL-injection-vulnerable; an unquoted GString value is parameter-bound by GORM on Hibernate 7, not spliced into the HQL text - Attribute the warning to GORM (not Hibernate ORM) and qualify the find/executeQuery reference pages with the Hibernate 7 scope so they no longer imply framework-wide behavior Assisted-by: Sisyphus:openai/gpt-5.6-terra [gpt-coding]
Review feedback addressedPushed Copilot review comments (all three resolved):
@borinquenkid - Hibernate 5 / Neo4j scope: you're right that the wiring is Hibernate 7-only, so I did not over-promise it. The user-facing docs ( Note for a follow-up: Local verification: |
@jamesfredley Understood, but I would prefer to tie down as much as possible sql injection threats one philosophical way or the other completely. This PR Warns while 15971 is a compile time error. This solution is partial while 15971 covers all bindings affected by SQL Injection. If the PR extends to H5 and neo4j then they would be comparable in range and then the committers can make an apples to apples decision. |
Assisted-by: opencode:gpt-5.6-sol
✅ All tests passed ✅🏷️ Commit: 2439fb3 Learn more about TestLens at testlens.app. |
|
I think #15971 is a much better security approach on this one. The warning wont capture all cases and doesn't prevent it overall. The compile time transformation is a solid way to help reduce risk. |
|
closing for now, if we want to go this way, please do open it back up. just housekeeping @jamesfredley |
Compile-time check for GORM query strings flattened from GString (alternative to #15968)
Description
What was found
What changed
GormQuerySafetyWarnings(in sharedgrails-datamapping-core) detectsGStringqueries with interpolated valuesMAX_WARNED_QUERY_SHAPES= 1000) and thread-safe, and the shape is only built when warn logging is enabledfind/findAll/executeQuery/executeUpdate)executeQuery/findrefs + upgrade note, all scoped to "when using Hibernate 7"; removed a misleading example that mislabeled a parameter-boundGStringas injectableListAppenderintegration test asserting one warning that omits the interpolated valueReview feedback addressed (follow-up commits
244cecd5a5,7ae397fd94)warnEnabledchecked first; cache bounded +synchronized; reset test addedHibernateGormStaticApiSpecLogbackListAppendertestOut of scope / follow-up
THREAT_MODEL.mdGString consistency passContributor Checklist
Issue and Scope
8.0.x.Code Quality
Licensing and Attribution
ai-generated-starting-pointlabel applied.Documentation
Assisted-by: Sisyphus:openai/gpt-5.6-terra [gpt-coding]