Grails error.gsp security
The default generated error.gsp view in Grails displays the stacktrace for any exceptions that occur. That's nice for debugging in a development environment but it is a security issue for production as it is information leakage. We can easily turn this off when not in development, and do something useful like redirect to the application homepage.
isDevelopmentEnv
The key piece is knowing when we are in the development environment. This is mentioned briefly in the docs--- follow the api link for full details:
GrailsUtil.isDevelopmentEnv()
We can use this is in a g:if
test to wrap the html in the error.gsp
view:
<html>
<g:if test="${GrailsUtil.isDevelopmentEnv()}">
<head>
<title>Grails Runtime Exception</title>
</g:if>
...
Else
If we are in production (or test) mode, then we may want to display a generic, secure error message and redirect to the application homepage (or any page):
<head>
<% flash.message='System error occurred.' %>
<meta http-equiv="Refresh" content="0;url=<g:createLinkTo dir='/' />">
</head>
<body>
</body>
The createLinkTo
with a directory of /
makes a link to the application
homepage. Play around with this tag (or createLink
), including the
absolute='true'
attribute (hint: set grails.serverURL
in
grails-app/conf/Config.groovy
). We might want to put the generic message and
link in the body section too, just in case the user's browser doesn't
redirect. Warning: don't add in sitemesh layouts or too much code in the
createLinkTo tag. If that code generates an exception, it will throw the user
into an infinite loop.
Bugs
If an exception occurs in a view that has changed the content type, then the error view will be labelled with that content type. We need to change it back to HTML to be sure the error message displays in the browser (or the redirect happens). In one of my projects, I had a gsp view generating XML. An exception in the middle of this produced an error message but the browser thought it was (malformed) XML and wouldn't display it. So we need to reset the content at the top:
<% response.contentType = "text/html" %>
Example
Attached is a complete example, modified from the Grails 1.0.3 generated file
grails-app/views/error.gsp
(other versions of Grails will look slightly
different in the middle):
error.gsp
Updates
In 1.1, g:if
with the env
attribute is working, so you can use:
<g:if env="development">
for the test:
error_11.gsp
(install as grails-app/views/error.gsp
)
In 1.2, the createLinkTo
tag has been deprecated in favor of resource
,
prompting one small change to the error.gsp file:
error12.gsp
Grails 2.3.x doesn't like the g:resource tag
nested inside the quotes of the
meta tag, generating a GrailsTagException with the message "Attribute value
quote wasn't closed". Use a string expression:
<meta http-equiv="Refresh" content="0;url=${g.resource(dir:'/')}">
There's also now an undocumented renderException
tag you can try out, though
it just moves some stuff from the default errors.gsp
into a tag:
<g:renderException exception="${exception}" />