grails-core icon indicating copy to clipboard operation
grails-core copied to clipboard

optionValue in <g:select> is not escaped when message() is used in a closure

Open camperboy1000 opened this issue 4 months ago • 0 comments

Expected Behavior

When using a closure to transform the optionValue attribute in a <g:select> element, the resulting string returned from message() should be escaped as per section 16.2 of the documentation:

By default, Grails plays it safe and escapes all content in ${} expressions in GSPs. All the standard GSP tags are also safe by default, escaping any relevant attribute values.

Actual Behaviour

The resulting string from message() is not escaped which can lead to XSS.

Additionally, using .encodeAsHTML() on the value passed to the code parameter causes the string to be escaped. However, using .encodeAsHTML() on the string returned from message does not escape the string.

Steps To Reproduce

  1. Create a new Grails app
  2. Prepend the index.gsp page with:
<% def bug = [[id: 1, value: "<script>alert('This is probably a bug');</script>"]] %>
  1. Add a <g:select> element to the GSP body that attempts to transform the value in a closure using message()
<g:select name="bugSelect" from="${bug}" optionKey="id" optionValue="${{message(code: it.value)}}" />
  1. XSS is acheived causing a browser alert to appear

Environment Information

Operating System: Kubuntu Mantic 23.10 JDK Version: Eclipse Temurin 17.0.10

Example Application

No response

Version

Grails 6.1.2

camperboy1000 avatar Feb 26 '24 20:02 camperboy1000